From ed2576f160f9a52f1ec122e92d7f014bdb04d4b7 Mon Sep 17 00:00:00 2001 From: masayume_ht <1936714878@qq.com> Date: Tue, 5 Mar 2024 11:46:18 +0800 Subject: [PATCH] initial commit --- .gitignore | 5 + .gitmodules | 3 + CMakeLists.txt | 52 + anlogic | Bin 0 -> 84352 bytes applog/CMakeLists.txt | 16 + applog/applog.cpp | 121 + applog/applog.h | 20 + capimage/CImageMerge.cpp | 301 + capimage/CImageMerge.h | 15 + capimage/CMakeLists.txt | 20 + capimage/CameraParam.h | 67 + capimage/Capturer.cpp | 845 + capimage/Capturer.h | 70 + capimage/CorrectParam.cpp | 856 + capimage/CorrectParam.h | 51 + capimage/FpgaComm.cpp | 495 + capimage/FpgaComm.h | 217 + capimage/GrayLighting.h | 109 + capimage/ICapturer.h | 52 + capimage/MonoCapturer.cpp | 1045 + capimage/MonoCapturer.h | 74 + capimage/MultiFrameCapture.cpp | 1587 ++ capimage/MultiFrameCapture.h | 171 + capimage/MultiFrameCapture_8458Color.cpp | 1331 + capimage/MultiFrameCapture_8458Color.h | 222 + capimage/MultiFrameCapture_8478_HL.cpp | 1550 ++ capimage/MultiFrameCapture_8478_HL.h | 170 + capimage/SysInforTool.cpp | 182 + capimage/SysInforTool.h | 28 + capimage/correct_ultis.cpp | 658 + capimage/correct_ultis.h | 45 + capimage/deviceconfig.cpp | 127 + capimage/deviceconfig.h | 65 + capimage/gvideo.cpp | 348 + capimage/gvideo.h | 49 + capimage/gvideoisp1.cpp | 918 + capimage/gvideoisp1.h | 24 + capimage/hgutils.cpp | 316 + capimage/hgutils.h | 33 + capimage/jsonconfig.cpp | 442 + capimage/jsonconfig.h | 31 + capimage/scannersysinfo.h | 69 + changelog.txt | 165 + config.h.in | 10 + deviceio/CMakeLists.txt | 16 + deviceio/DevUtil.cpp | 32 + deviceio/DevUtil.h | 94 + deviceio/Gpio.cpp | 95 + deviceio/Gpio.h | 52 + deviceio/Led.cpp | 45 + deviceio/Led.h | 24 + deviceio/PinMonitor.cpp | 76 + deviceio/PinMonitor.h | 19 + deviceio/Pwm.cpp | 38 + deviceio/Pwm.h | 22 + deviceio/xmake.lua | 8 + display/CMakeLists.txt | 18 + display/DisplayCenter.cpp | 61 + display/DisplayCenter.h | 31 + display/Displaydef.h | 83 + display/HgLCDfont.h | 1186 + display/LCDDisplay.cpp | 189 + display/LCDDisplay.h | 205 + display/Lcd.cpp | 780 + display/Lcd.h | 61 + fpgaupdate/CMakeLists.txt | 21 + fpgaupdate/fpgacontrol.cpp | 121 + fpgaupdate/fpgacontrol.h | 23 + fpgaupdate/libmtd.c | 1525 ++ fpgaupdate/libmtd.h | 358 + fpgaupdate/libmtd_common.h | 247 + fpgaupdate/libmtd_int.h | 110 + fpgaupdate/libmtd_legacy.c | 404 + fpgaupdate/libmtd_xalloc.h | 100 + i2c_key/Makefile | 6 + i2c_key/ch455_key | Bin 0 -> 19520 bytes i2c_key/ch455_key.cpp | 330 + imgproc/CMakeLists.txt | 32 + imgproc/CSizedetect.cpp | 285 + imgproc/CSizedetect.h | 42 + imgproc/ContaminationDetection.cpp | 67 + imgproc/ContaminationDetection.h | 51 + imgproc/IPreproc.cpp | 5 + imgproc/IPreproc.h | 13 + imgproc/cvimagex.cpp | 32 + imgproc/cvimagex.h | 22 + imgproc/iimage.h | 34 + imgproc/iimageencode.h | 18 + imgproc/imageencode.cpp | 52 + imgproc/imageencode.h | 31 + imgproc/imageprocess | 1 + imgproc/imemory.h | 17 + imgproc/imgproc.h | 19 + imgproc/memoryex.h | 62 + keymonitor/CMakeLists.txt | 18 + keymonitor/keymonitor.cpp | 204 + keymonitor/keymonitor.h | 71 + main.cpp | 48 + motorboard/CMakeLists.txt | 39 + motorboard/FeedControl.cpp | 69 + motorboard/FeedControl.h | 31 + motorboard/Jtag.cpp | 95 + motorboard/Jtag.h | 41 + motorboard/MotorConfig.cpp | 195 + motorboard/MotorConfig.h | 68 + motorboard/MotorSessionInfo.cpp | 118 + motorboard/MotorSessionInfo.h | 54 + motorboard/SensorConfig.cpp | 147 + motorboard/SensorConfig.h | 59 + motorboard/aje2vec.cpp | 918 + motorboard/ajeutil.cpp | 101 + motorboard/decodel.cpp | 155 + motorboard/jtagupdata.cpp | 26 + motorboard/jtagupdata.h | 22 + motorboard/lzw_lib.cpp | 353 + motorboard/motorboard.cpp | 892 + motorboard/motorboard.h | 273 + motorboard/opcode.h | 142 + motorboard/vec.cpp | 521 + motorcontroller/CMakeLists.txt | 22 + motorcontroller/IState.h | 32 + motorcontroller/Menu.cpp | 51 + motorcontroller/Menu.h | 16 + motorcontroller/MenuComponent.cpp | 157 + motorcontroller/MenuComponent.h | 33 + motorcontroller/Menu_Item.cpp | 24 + motorcontroller/Menu_Item.h | 14 + motorcontroller/MotorController.cpp | 76 + motorcontroller/MotorController.h | 36 + motorcontroller/MotorboardParam.cpp | 176 + motorcontroller/MotorboardParam.h | 39 + motorcontroller/Mt_Count.cpp | 26 + motorcontroller/Mt_Count.h | 12 + motorcontroller/Mt_Error.cpp | 42 + motorcontroller/Mt_Error.h | 12 + motorcontroller/Mt_Idel.cpp | 41 + motorcontroller/Mt_Idel.h | 14 + motorcontroller/Mt_Scan.cpp | 27 + motorcontroller/Mt_Scan.h | 12 + motorcontroller/Mt_Set.cpp | 42 + motorcontroller/Mt_Set.h | 20 + motorcontroller/Mt_Welcome.cpp | 27 + motorcontroller/Mt_Welcome.h | 14 + motorcontroller/Selectable.h | 54 + motorcontroller/StateControl.cpp | 473 + motorcontroller/StateControl.h | 63 + motorcontroller/StateManager.cpp | 4 + motorcontroller/StateManager.h | 30 + motorcontroller/Statedef.h | 38 + motorcontroller/Subject.h | 17 + out.text | 1 + packages/common.pkg/include/BlockingQueue.h | 103 + packages/common.pkg/include/StopWatch.h | 81 + packages/common.pkg/include/ThreadPool.h | 98 + packages/common.pkg/include/autoevent.hpp | 70 + packages/common.pkg/include/base64.hpp | 115 + packages/common.pkg/include/commondef.h | 903 + packages/common.pkg/include/config.h | 10 + packages/common.pkg/include/dailex.hpp | 55 + packages/common.pkg/include/filetools.h | 59 + packages/common.pkg/include/json.hpp | 22875 ++++++++++++++++ .../common.pkg/include/rigtorp/MPMCQueue.h | 280 + packages/common.pkg/include/stringex.hpp | 11 + packages/common.pkg/include/threadex.h | 55 + packages/common.pkg/include/utils.h | 199 + regs/CMakeLists.txt | 15 + regs/regsaccess.h | 10 + regs/serialib.cpp | 583 + regs/serialib.h | 220 + regs/uartregaccessb.cpp | 46 + regs/uartregaccessb.h | 25 + regs/uartregsaccess.cpp | 36 + regs/uartregsaccess.h | 12 + scanner/CMakeLists.txt | 31 + scanner/IScanner.h | 48 + scanner/fsmstate.cpp | 185 + scanner/fsmstate.h | 145 + scanner/iimagehandler.h | 358 + scanner/imagesavehandler.cpp | 62 + scanner/imagesavehandler.h | 17 + scanner/imageusbhandler.cpp | 769 + scanner/imageusbhandler.h | 132 + scanner/imageusbtesthandler.cpp | 38 + scanner/imageusbtesthandler.h | 10 + scanner/scanner.cpp | 1638 ++ scanner/scanner.h | 107 + scanner/scannerregs.cpp | 1231 + scanner/scannerregs.h | 44 + scanner/wakeup.hpp | 207 + scanservice/CMakeLists.txt | 61 + scanservice/main.cpp | 249 + service/CMakeLists.txt | 54 + service/main.cpp | 66 + small_lcd/app_spi_lcd/.DevUtil.o.d | 170 + small_lcd/app_spi_lcd/.Gpio.o.d | 169 + small_lcd/app_spi_lcd/.Lcd.o.d | 172 + small_lcd/app_spi_lcd/.main.o.d | 172 + small_lcd/app_spi_lcd/DevUtil.cpp | 34 + small_lcd/app_spi_lcd/DevUtil.h | 99 + small_lcd/app_spi_lcd/DevUtil.o | Bin 0 -> 30456 bytes small_lcd/app_spi_lcd/Gpio.cpp | 90 + small_lcd/app_spi_lcd/Gpio.h | 58 + small_lcd/app_spi_lcd/Gpio.o | Bin 0 -> 41344 bytes small_lcd/app_spi_lcd/Lcd.cpp | 428 + small_lcd/app_spi_lcd/Lcd.h | 73 + small_lcd/app_spi_lcd/Lcd.o | Bin 0 -> 28720 bytes small_lcd/app_spi_lcd/Makefile | 22 + small_lcd/app_spi_lcd/Parameters.h | 102 + small_lcd/app_spi_lcd/filetools.h | 75 + small_lcd/app_spi_lcd/lcd | Bin 0 -> 44464 bytes small_lcd/app_spi_lcd/main.cpp | 35 + small_lcd/app_spi_lcd/main.o | Bin 0 -> 4280 bytes small_lcd/app_spi_lcd/smalllcd | Bin 0 -> 50080 bytes testcapimage/CMakeLists.txt | 49 + testcapimage/main.cpp | 607 + testdisplay/CMakeLists.txt | 24 + testdisplay/main.cpp | 33 + testimgproc/CMakeLists.txt | 42 + testimgproc/main.cpp | 302 + testkeymonitor/CMakeLists.txt | 27 + testkeymonitor/main.cpp | 69 + testlcd/CMakeLists.txt | 23 + testlcd/main.cpp | 50 + testmotorboard/CMakeLists.txt | 45 + testmotorboard/main.cpp | 281 + testregs/CMakeLists.txt | 41 + testregs/main.cpp | 135 + testscanner/CMakeLists.txt | 53 + testscanner/main.cpp | 94 + testthread | Bin 0 -> 28672 bytes testusb/CMakeLists.txt | 49 + testusb/main.cpp | 117 + testwakeup/CMakeLists.txt | 28 + testwakeup/main.cpp | 45 + tinyfsm-master/COPYING | 21 + tinyfsm-master/ChangeLog | 33 + tinyfsm-master/README.md | 95 + tinyfsm-master/doc/10-Introduction.md | 28 + tinyfsm-master/doc/20-Installation.md | 68 + tinyfsm-master/doc/30-Concepts.md | 38 + tinyfsm-master/doc/40-Usage.md | 238 + tinyfsm-master/doc/50-API.md | 206 + tinyfsm-master/doc/60-Development.md | 26 + tinyfsm-master/doc/70-License.md | 9 + tinyfsm-master/examples/api/Makefile | 63 + tinyfsm-master/examples/api/debugging_switch | Bin 0 -> 16144 bytes .../examples/api/debugging_switch.cpp | 122 + .../examples/api/debugging_switch.d | 1 + tinyfsm-master/examples/api/mealy_machine | Bin 0 -> 14840 bytes tinyfsm-master/examples/api/mealy_machine.cpp | 70 + tinyfsm-master/examples/api/mealy_machine.d | 1 + tinyfsm-master/examples/api/moore_machine | Bin 0 -> 14968 bytes tinyfsm-master/examples/api/moore_machine.cpp | 64 + tinyfsm-master/examples/api/moore_machine.d | 1 + tinyfsm-master/examples/api/multiple_switch | Bin 0 -> 17568 bytes .../examples/api/multiple_switch.cpp | 145 + tinyfsm-master/examples/api/multiple_switch.d | 1 + tinyfsm-master/examples/api/resetting_switch | Bin 0 -> 15512 bytes .../examples/api/resetting_switch.cpp | 110 + .../examples/api/resetting_switch.d | 1 + tinyfsm-master/examples/api/simple_switch | Bin 0 -> 14968 bytes tinyfsm-master/examples/api/simple_switch.cpp | 85 + tinyfsm-master/examples/api/simple_switch.d | 1 + tinyfsm-master/examples/elevator/Makefile | 98 + tinyfsm-master/examples/elevator/README.md | 88 + tinyfsm-master/examples/elevator/elevator | Bin 0 -> 17368 bytes tinyfsm-master/examples/elevator/elevator.cpp | 115 + tinyfsm-master/examples/elevator/elevator.d | 2 + tinyfsm-master/examples/elevator/elevator.hpp | 55 + tinyfsm-master/examples/elevator/elevator.o | Bin 0 -> 13416 bytes tinyfsm-master/examples/elevator/fsmlist.hpp | 19 + tinyfsm-master/examples/elevator/main.cpp | 40 + tinyfsm-master/examples/elevator/main.d | 2 + tinyfsm-master/examples/elevator/main.o | Bin 0 -> 4856 bytes tinyfsm-master/examples/elevator/motor.cpp | 60 + tinyfsm-master/examples/elevator/motor.d | 1 + tinyfsm-master/examples/elevator/motor.hpp | 50 + tinyfsm-master/examples/elevator/motor.o | Bin 0 -> 8600 bytes tinyfsm-master/include/tinyfsm.hpp | 252 + tinyfsm-master/library.json | 24 + tinyfsm-master/tree.h | 0 usb/CMakeLists.txt | 21 + usb/inc/buildconf.h | 12 + usb/inc/camtp.h | 80 + usb/inc/default_cfg.h | 57 + usb/inc/logs_out.h | 124 + usb/inc/usb_gadget.h | 185 + usb/inc/usbdevice.h | 57 + usb/inc/usbstring.h | 42 + usb/inotify.h | 13 + usb/ireceive.h | 17 + usb/itransmit.h | 12 + usb/src/logs_out.cpp | 112 + usb/src/usbdevice.cpp | 1152 + usb/src/usbstring.cpp | 349 + usb/usbimageprocqueue.h | 100 + usb/usbnotify.cpp | 76 + usb/usbnotify.h | 28 + usb/usbreceive.cpp | 60 + usb/usbreceive.h | 21 + usb/usbservice.cpp | 245 + usb/usbservice.h | 36 + usb/usbtransmit.cpp | 66 + usb/usbtransmit.h | 22 + 304 files changed, 66689 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 CMakeLists.txt create mode 100644 anlogic create mode 100644 applog/CMakeLists.txt create mode 100644 applog/applog.cpp create mode 100644 applog/applog.h create mode 100644 capimage/CImageMerge.cpp create mode 100644 capimage/CImageMerge.h create mode 100644 capimage/CMakeLists.txt create mode 100644 capimage/CameraParam.h create mode 100644 capimage/Capturer.cpp create mode 100644 capimage/Capturer.h create mode 100644 capimage/CorrectParam.cpp create mode 100644 capimage/CorrectParam.h create mode 100644 capimage/FpgaComm.cpp create mode 100644 capimage/FpgaComm.h create mode 100644 capimage/GrayLighting.h create mode 100644 capimage/ICapturer.h create mode 100644 capimage/MonoCapturer.cpp create mode 100644 capimage/MonoCapturer.h create mode 100644 capimage/MultiFrameCapture.cpp create mode 100644 capimage/MultiFrameCapture.h create mode 100644 capimage/MultiFrameCapture_8458Color.cpp create mode 100644 capimage/MultiFrameCapture_8458Color.h create mode 100644 capimage/MultiFrameCapture_8478_HL.cpp create mode 100644 capimage/MultiFrameCapture_8478_HL.h create mode 100644 capimage/SysInforTool.cpp create mode 100644 capimage/SysInforTool.h create mode 100644 capimage/correct_ultis.cpp create mode 100644 capimage/correct_ultis.h create mode 100644 capimage/deviceconfig.cpp create mode 100644 capimage/deviceconfig.h create mode 100644 capimage/gvideo.cpp create mode 100644 capimage/gvideo.h create mode 100644 capimage/gvideoisp1.cpp create mode 100644 capimage/gvideoisp1.h create mode 100644 capimage/hgutils.cpp create mode 100644 capimage/hgutils.h create mode 100644 capimage/jsonconfig.cpp create mode 100644 capimage/jsonconfig.h create mode 100644 capimage/scannersysinfo.h create mode 100644 changelog.txt create mode 100644 config.h.in create mode 100644 deviceio/CMakeLists.txt create mode 100644 deviceio/DevUtil.cpp create mode 100644 deviceio/DevUtil.h create mode 100644 deviceio/Gpio.cpp create mode 100644 deviceio/Gpio.h create mode 100644 deviceio/Led.cpp create mode 100644 deviceio/Led.h create mode 100644 deviceio/PinMonitor.cpp create mode 100644 deviceio/PinMonitor.h create mode 100644 deviceio/Pwm.cpp create mode 100644 deviceio/Pwm.h create mode 100644 deviceio/xmake.lua create mode 100644 display/CMakeLists.txt create mode 100644 display/DisplayCenter.cpp create mode 100644 display/DisplayCenter.h create mode 100644 display/Displaydef.h create mode 100644 display/HgLCDfont.h create mode 100644 display/LCDDisplay.cpp create mode 100644 display/LCDDisplay.h create mode 100644 display/Lcd.cpp create mode 100644 display/Lcd.h create mode 100644 fpgaupdate/CMakeLists.txt create mode 100644 fpgaupdate/fpgacontrol.cpp create mode 100644 fpgaupdate/fpgacontrol.h create mode 100644 fpgaupdate/libmtd.c create mode 100644 fpgaupdate/libmtd.h create mode 100644 fpgaupdate/libmtd_common.h create mode 100644 fpgaupdate/libmtd_int.h create mode 100644 fpgaupdate/libmtd_legacy.c create mode 100644 fpgaupdate/libmtd_xalloc.h create mode 100644 i2c_key/Makefile create mode 100644 i2c_key/ch455_key create mode 100644 i2c_key/ch455_key.cpp create mode 100644 imgproc/CMakeLists.txt create mode 100644 imgproc/CSizedetect.cpp create mode 100644 imgproc/CSizedetect.h create mode 100644 imgproc/ContaminationDetection.cpp create mode 100644 imgproc/ContaminationDetection.h create mode 100644 imgproc/IPreproc.cpp create mode 100644 imgproc/IPreproc.h create mode 100644 imgproc/cvimagex.cpp create mode 100644 imgproc/cvimagex.h create mode 100644 imgproc/iimage.h create mode 100644 imgproc/iimageencode.h create mode 100644 imgproc/imageencode.cpp create mode 100644 imgproc/imageencode.h create mode 160000 imgproc/imageprocess create mode 100644 imgproc/imemory.h create mode 100644 imgproc/imgproc.h create mode 100644 imgproc/memoryex.h create mode 100644 keymonitor/CMakeLists.txt create mode 100644 keymonitor/keymonitor.cpp create mode 100644 keymonitor/keymonitor.h create mode 100644 main.cpp create mode 100644 motorboard/CMakeLists.txt create mode 100644 motorboard/FeedControl.cpp create mode 100644 motorboard/FeedControl.h create mode 100644 motorboard/Jtag.cpp create mode 100644 motorboard/Jtag.h create mode 100644 motorboard/MotorConfig.cpp create mode 100644 motorboard/MotorConfig.h create mode 100644 motorboard/MotorSessionInfo.cpp create mode 100644 motorboard/MotorSessionInfo.h create mode 100644 motorboard/SensorConfig.cpp create mode 100644 motorboard/SensorConfig.h create mode 100644 motorboard/aje2vec.cpp create mode 100644 motorboard/ajeutil.cpp create mode 100644 motorboard/decodel.cpp create mode 100644 motorboard/jtagupdata.cpp create mode 100644 motorboard/jtagupdata.h create mode 100644 motorboard/lzw_lib.cpp create mode 100644 motorboard/motorboard.cpp create mode 100644 motorboard/motorboard.h create mode 100644 motorboard/opcode.h create mode 100644 motorboard/vec.cpp create mode 100644 motorcontroller/CMakeLists.txt create mode 100644 motorcontroller/IState.h create mode 100644 motorcontroller/Menu.cpp create mode 100644 motorcontroller/Menu.h create mode 100644 motorcontroller/MenuComponent.cpp create mode 100644 motorcontroller/MenuComponent.h create mode 100644 motorcontroller/Menu_Item.cpp create mode 100644 motorcontroller/Menu_Item.h create mode 100644 motorcontroller/MotorController.cpp create mode 100644 motorcontroller/MotorController.h create mode 100644 motorcontroller/MotorboardParam.cpp create mode 100644 motorcontroller/MotorboardParam.h create mode 100644 motorcontroller/Mt_Count.cpp create mode 100644 motorcontroller/Mt_Count.h create mode 100644 motorcontroller/Mt_Error.cpp create mode 100644 motorcontroller/Mt_Error.h create mode 100644 motorcontroller/Mt_Idel.cpp create mode 100644 motorcontroller/Mt_Idel.h create mode 100644 motorcontroller/Mt_Scan.cpp create mode 100644 motorcontroller/Mt_Scan.h create mode 100644 motorcontroller/Mt_Set.cpp create mode 100644 motorcontroller/Mt_Set.h create mode 100644 motorcontroller/Mt_Welcome.cpp create mode 100644 motorcontroller/Mt_Welcome.h create mode 100644 motorcontroller/Selectable.h create mode 100644 motorcontroller/StateControl.cpp create mode 100644 motorcontroller/StateControl.h create mode 100644 motorcontroller/StateManager.cpp create mode 100644 motorcontroller/StateManager.h create mode 100644 motorcontroller/Statedef.h create mode 100644 motorcontroller/Subject.h create mode 100644 out.text create mode 100644 packages/common.pkg/include/BlockingQueue.h create mode 100644 packages/common.pkg/include/StopWatch.h create mode 100644 packages/common.pkg/include/ThreadPool.h create mode 100644 packages/common.pkg/include/autoevent.hpp create mode 100644 packages/common.pkg/include/base64.hpp create mode 100644 packages/common.pkg/include/commondef.h create mode 100644 packages/common.pkg/include/config.h create mode 100644 packages/common.pkg/include/dailex.hpp create mode 100644 packages/common.pkg/include/filetools.h create mode 100644 packages/common.pkg/include/json.hpp create mode 100644 packages/common.pkg/include/rigtorp/MPMCQueue.h create mode 100644 packages/common.pkg/include/stringex.hpp create mode 100644 packages/common.pkg/include/threadex.h create mode 100644 packages/common.pkg/include/utils.h create mode 100644 regs/CMakeLists.txt create mode 100644 regs/regsaccess.h create mode 100644 regs/serialib.cpp create mode 100644 regs/serialib.h create mode 100644 regs/uartregaccessb.cpp create mode 100644 regs/uartregaccessb.h create mode 100644 regs/uartregsaccess.cpp create mode 100644 regs/uartregsaccess.h create mode 100644 scanner/CMakeLists.txt create mode 100644 scanner/IScanner.h create mode 100644 scanner/fsmstate.cpp create mode 100644 scanner/fsmstate.h create mode 100644 scanner/iimagehandler.h create mode 100644 scanner/imagesavehandler.cpp create mode 100644 scanner/imagesavehandler.h create mode 100644 scanner/imageusbhandler.cpp create mode 100644 scanner/imageusbhandler.h create mode 100644 scanner/imageusbtesthandler.cpp create mode 100644 scanner/imageusbtesthandler.h create mode 100644 scanner/scanner.cpp create mode 100644 scanner/scanner.h create mode 100644 scanner/scannerregs.cpp create mode 100644 scanner/scannerregs.h create mode 100644 scanner/wakeup.hpp create mode 100644 scanservice/CMakeLists.txt create mode 100644 scanservice/main.cpp create mode 100644 service/CMakeLists.txt create mode 100644 service/main.cpp create mode 100644 small_lcd/app_spi_lcd/.DevUtil.o.d create mode 100644 small_lcd/app_spi_lcd/.Gpio.o.d create mode 100644 small_lcd/app_spi_lcd/.Lcd.o.d create mode 100644 small_lcd/app_spi_lcd/.main.o.d create mode 100644 small_lcd/app_spi_lcd/DevUtil.cpp create mode 100644 small_lcd/app_spi_lcd/DevUtil.h create mode 100644 small_lcd/app_spi_lcd/DevUtil.o create mode 100644 small_lcd/app_spi_lcd/Gpio.cpp create mode 100644 small_lcd/app_spi_lcd/Gpio.h create mode 100644 small_lcd/app_spi_lcd/Gpio.o create mode 100644 small_lcd/app_spi_lcd/Lcd.cpp create mode 100644 small_lcd/app_spi_lcd/Lcd.h create mode 100644 small_lcd/app_spi_lcd/Lcd.o create mode 100644 small_lcd/app_spi_lcd/Makefile create mode 100644 small_lcd/app_spi_lcd/Parameters.h create mode 100644 small_lcd/app_spi_lcd/filetools.h create mode 100644 small_lcd/app_spi_lcd/lcd create mode 100644 small_lcd/app_spi_lcd/main.cpp create mode 100644 small_lcd/app_spi_lcd/main.o create mode 100644 small_lcd/app_spi_lcd/smalllcd create mode 100644 testcapimage/CMakeLists.txt create mode 100644 testcapimage/main.cpp create mode 100644 testdisplay/CMakeLists.txt create mode 100644 testdisplay/main.cpp create mode 100644 testimgproc/CMakeLists.txt create mode 100644 testimgproc/main.cpp create mode 100644 testkeymonitor/CMakeLists.txt create mode 100644 testkeymonitor/main.cpp create mode 100644 testlcd/CMakeLists.txt create mode 100644 testlcd/main.cpp create mode 100644 testmotorboard/CMakeLists.txt create mode 100644 testmotorboard/main.cpp create mode 100644 testregs/CMakeLists.txt create mode 100644 testregs/main.cpp create mode 100644 testscanner/CMakeLists.txt create mode 100644 testscanner/main.cpp create mode 100644 testthread create mode 100644 testusb/CMakeLists.txt create mode 100644 testusb/main.cpp create mode 100644 testwakeup/CMakeLists.txt create mode 100644 testwakeup/main.cpp create mode 100644 tinyfsm-master/COPYING create mode 100644 tinyfsm-master/ChangeLog create mode 100644 tinyfsm-master/README.md create mode 100644 tinyfsm-master/doc/10-Introduction.md create mode 100644 tinyfsm-master/doc/20-Installation.md create mode 100644 tinyfsm-master/doc/30-Concepts.md create mode 100644 tinyfsm-master/doc/40-Usage.md create mode 100644 tinyfsm-master/doc/50-API.md create mode 100644 tinyfsm-master/doc/60-Development.md create mode 100644 tinyfsm-master/doc/70-License.md create mode 100644 tinyfsm-master/examples/api/Makefile create mode 100644 tinyfsm-master/examples/api/debugging_switch create mode 100644 tinyfsm-master/examples/api/debugging_switch.cpp create mode 100644 tinyfsm-master/examples/api/debugging_switch.d create mode 100644 tinyfsm-master/examples/api/mealy_machine create mode 100644 tinyfsm-master/examples/api/mealy_machine.cpp create mode 100644 tinyfsm-master/examples/api/mealy_machine.d create mode 100644 tinyfsm-master/examples/api/moore_machine create mode 100644 tinyfsm-master/examples/api/moore_machine.cpp create mode 100644 tinyfsm-master/examples/api/moore_machine.d create mode 100644 tinyfsm-master/examples/api/multiple_switch create mode 100644 tinyfsm-master/examples/api/multiple_switch.cpp create mode 100644 tinyfsm-master/examples/api/multiple_switch.d create mode 100644 tinyfsm-master/examples/api/resetting_switch create mode 100644 tinyfsm-master/examples/api/resetting_switch.cpp create mode 100644 tinyfsm-master/examples/api/resetting_switch.d create mode 100644 tinyfsm-master/examples/api/simple_switch create mode 100644 tinyfsm-master/examples/api/simple_switch.cpp create mode 100644 tinyfsm-master/examples/api/simple_switch.d create mode 100644 tinyfsm-master/examples/elevator/Makefile create mode 100644 tinyfsm-master/examples/elevator/README.md create mode 100644 tinyfsm-master/examples/elevator/elevator create mode 100644 tinyfsm-master/examples/elevator/elevator.cpp create mode 100644 tinyfsm-master/examples/elevator/elevator.d create mode 100644 tinyfsm-master/examples/elevator/elevator.hpp create mode 100644 tinyfsm-master/examples/elevator/elevator.o create mode 100644 tinyfsm-master/examples/elevator/fsmlist.hpp create mode 100644 tinyfsm-master/examples/elevator/main.cpp create mode 100644 tinyfsm-master/examples/elevator/main.d create mode 100644 tinyfsm-master/examples/elevator/main.o create mode 100644 tinyfsm-master/examples/elevator/motor.cpp create mode 100644 tinyfsm-master/examples/elevator/motor.d create mode 100644 tinyfsm-master/examples/elevator/motor.hpp create mode 100644 tinyfsm-master/examples/elevator/motor.o create mode 100644 tinyfsm-master/include/tinyfsm.hpp create mode 100644 tinyfsm-master/library.json create mode 100644 tinyfsm-master/tree.h create mode 100644 usb/CMakeLists.txt create mode 100644 usb/inc/buildconf.h create mode 100644 usb/inc/camtp.h create mode 100644 usb/inc/default_cfg.h create mode 100644 usb/inc/logs_out.h create mode 100644 usb/inc/usb_gadget.h create mode 100644 usb/inc/usbdevice.h create mode 100644 usb/inc/usbstring.h create mode 100644 usb/inotify.h create mode 100644 usb/ireceive.h create mode 100644 usb/itransmit.h create mode 100644 usb/src/logs_out.cpp create mode 100644 usb/src/usbdevice.cpp create mode 100644 usb/src/usbstring.cpp create mode 100644 usb/usbimageprocqueue.h create mode 100644 usb/usbnotify.cpp create mode 100644 usb/usbnotify.h create mode 100644 usb/usbreceive.cpp create mode 100644 usb/usbreceive.h create mode 100644 usb/usbservice.cpp create mode 100644 usb/usbservice.h create mode 100644 usb/usbtransmit.cpp create mode 100644 usb/usbtransmit.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aac651f --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.vscode/* +.cmake/* +.xmake/* +build/* +app.log diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..ccee3e5 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "imgproc/imageprocess"] + path = imgproc/imageprocess + url = https://gitee.com/huagaochina/ImageProcess.git \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..87fb8c3 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,52 @@ +cmake_minimum_required(VERSION 3.13) + +if(CMAKE_HOST_WIN32) +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_C_COMPILER_WORKS 1) +set(CMAKE_CXX_COMPILER_WORKS 1) +set(tools D:/arm-build/gcc-linaro-6.2.1-2016.11-i686-mingw32_aarch64-linux-gnu/bin) +set(CMAKE_CXX_COMPILER ${tools}/aarch64-linux-gnu-g++.exe) +set(CMAKE_C_COMPILER ${tools}/aarch64-linux-gnu-gcc.exe) +set(CMAKE_FIND_ROOT_PATH D:/arm-build/gcc-linaro-6.2.1-2016.11-i686-mingw32_aarch64-linux-gnu/aarch64-linux-gnu/libc ) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +endif() +project(hgscanner_boardsys) +# 加入一个配置头文件,用于处理 CMake 对源码的设置 +configure_file( + "${PROJECT_SOURCE_DIR}/config.h.in" + "${PROJECT_SOURCE_DIR}/packages/common.pkg/include/config.h" +) +set(CMAKE_VERBOSE_MAKEFILE ON) +# set(CMAKE_BUILD_TYPE Release) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -DNDEBUG") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -DNDEBUG") +add_subdirectory(applog) +add_subdirectory(capimage) +add_subdirectory(deviceio) +add_subdirectory(display) +add_subdirectory(fpgaupdate) +add_subdirectory(imgproc) +add_subdirectory(keymonitor) +add_subdirectory(motorcontroller) +add_subdirectory(motorboard) +add_subdirectory(regs) +add_subdirectory(scanner) +add_subdirectory(scanservice) +add_subdirectory(service) +add_subdirectory(testcapimage) +add_subdirectory(testimgproc) +add_subdirectory(testdisplay) +add_subdirectory(testkeymonitor) +add_subdirectory(testlcd) +add_subdirectory(testmotorboard) +add_subdirectory(testregs) +add_subdirectory(testscanner) +add_subdirectory(testusb) +add_subdirectory(testwakeup) +add_subdirectory(usb) + + + + + diff --git a/anlogic b/anlogic new file mode 100644 index 0000000000000000000000000000000000000000..35790d2cae6297fcb129a2112852a9c2fa95bbce GIT binary patch literal 84352 zcmeFa4V=|gwg3M;XAUqtC?lYvl5+-75mBB@K`qWOARwqbj74e93^N0ajttBUib8Qv z{zX@B@lCq=OVKj}6`~ax74*dT(2ZMm!-u+Dvl@_+(h46crqKDlKl{7)nSBm3YIXnr z`})6Lef7)UYwfkyT6^ua*M9hZ&v({NpL2OU77N@}5PTyLbYx_NN!fz7(k_}*Fe&I8 zq=Mq$%%C^ry|^7+etOhab7>*8x(c`x+>_#hj!(~s(1A;xbfuEl(>3|0QHe_f)0*gC z>3Zb(sQk$D5l5G9=ojJlo)o37p43yl#Y-;sS+SIjAZPQ(D@%ibrh+W`P z(dwG}tL7S$|3(DU9nodeJ1wD0UA=kKlb-MNDzb$0t-PM>QlyUJa;fWwvGsL}#@5%I zUthOu<*M_msv4`8UUcCFO$`@}kJ>H%qMdQoHL7mJ1AL!~P@nMBi!2Iq5z_Q=m<`(mC8$abGQfYcBUZ z?gaw4q`~{S7Yg9|0Qa@rH>~~an&D^Mbp9V(ZhrKkDT&qnKXS##U%cW2U;5I?ccxAl za`678W3Qe0vmd>1f4_T|zrN+>kDlK&z2VU_etF@NrESCZ)_tMsOJf^1rC`(JRS@(K zDwD?-7X&8kG=*I_pz#r)WKc)w{zweDj_Lt_a}RRA*u%KEu!r{kxd;5c zJ^0D3J#HI}y~S_0 z^!xMpUuf~|dHBzQ9|WIK+ad-|?iH4PX`b9>OTX<45&aq~_dj~jXT9aqme;OxE&gzx zK2t0{ornJl@kH&N_7N*EGDq+!OaDY3|1&LqZyr8iowmGrX=80wjaFylf{Iz?S60;2 zHr6hwYih1-EWfg>zF}EydDWu&+NiAClA9arnrp?Yskx^5yz|8BqM)K;$&C%mDw>+B z8k;LBf{G6=Xs&OXRlT5j{P^mnRgD$Rja7BcAf_*<;-BgBDVVsZs;REJqM@l7jc%M( zUQs@-V)}xME9TF>YC-eG6&2O1R*fG&enLbAQQfj7vld)fvEbbm<>M=+Pe;a8hS{|7 z({D0B^Y{xR;=09_XE*YvmyMr3ceV;9R?KQ>s1R^K#zdU=Iu&4P)t$KSzc{Dg|q`uc|IiludQlJu^g zKl|_IRyMwSt(?&s-o|Ke)h*Qv##cmbpWcmO|DLu-z4Q+>w`#%ktML}PwR%-m#UfmM zSw(eKbM;cw7j=zI)92TbT~>9YC8=Fj;}JApRK2vZVOhh(iuX+zKY`IvRdY*4HJx$8 z#AOXP8;7f@nrr-S_TTOy7gsRus+y~u6k{Xvts~r*)j09vKl`gU8<{= zS5@Qk(=mqSIBmk;%klW}_?E5}k(*v>tR*@%+-!9Cn@1hv`O1o>+UAP-+GR_cmzt*F zjFT%W4AYAGh9yLs+Q!C)M#lf&CnMW$bH!jmbK^S;aYWa=5Z7}w$d7P;yB#K|LmQSM zb7gfiV}APdn@l8H&^%$>;)ceXs~T%6h~SM?%?-rmswID)DJDw_t!l2FKL5tZZT@yu z$HAngu4#EgQ|;gDZFKtrn!B9Q$vo3UjAVk~|G%$Q#)%l^RrNXJ)5XZQoLI7c-%#H) zU9sh=zauidyP7$)@$WT;2?NZ`H%5~(xh2&wjLu>zuDGdUzMbmJ>Z_WXYMX+JYnI(y zN8p=Z+qCjVGpSccRhyPG-!?A}7B?_I28)|(>+6H%E1R42j|?5q^_rUk6BC1~MGcM3 z1X6Kj0kF8Lu0B{?+d%y#wawM$-=+Yoss`<2h}x)&|E#KO4sNWyk)f+1{tp&6)z;o1 zT=nu>g2hN^sts<;R<5pUs;$0pdC=5UUA1hn>MYBm>T7G4Th5E?G>zX{D*};MRA3HS zS1XhotLl~oP0L&(8*6KWB^AvzjTKF*LAI{ZIDo|}R+Fu|zP4gQC3zl zkpC{;j<1d()Q!-(^58CBqoD;bMPS>J; z6DIA&iDhqY;ky2dgGm@lm2}<0i%REt5k()93fGG}4lkFF;2CqjFt! zNAG5*)hGBl^@V%p%Qvtx?-jgk;T5Jl5&YT0&F6j^?zG*WC%g0I0=Lny`=g`w{Mq3v zn~k_2u;+pfzv~kbzAz8J_45(FC=b8utO!5zm(hm7@p1ctxp{cEUt5@uxBH07JiOaa zt;)l@{YyFz@Agw0^6+jycuyYQ?FTb?c(?!BmWOxytX+9{w?Asj!@GUo-aNe9Kkm!J zyM5@mgSqx}@KQ@3qkm7aU8rQahd<53Z}jk^Jp2w1{~iy&-@})A_;wFJ&BIT!dg_tR zB_2L#kMxhDr^c+i3O&4YQI!>WcpN@^4fXI0tn8Ka@C?uFHOj*?FtXP;56{raUXwh$ z9YUro<>49d*=weUACSco7d-q49)6*RKheWidia4JeyN9dF+s)4J-p76+_lQX`{zGt z4?oxulWy?vdM4tojUN7Fha|nn!~6c0@$jd5^xHiAP!GSu!~6cZ%fp}U(YJYc_e@U3 zdp-OxkA9zrf0u{f@8Qq%@a-PH*ux+8@JSDU#KV_(_@f?vxQ7o8bou`X4`1lvM|$`o z4{t-NDIMzJZ74VRq=!Gp<1@;`pX=erdHB&Dev*ej&%>uY{1^{E)5Ghm&|Pyq`~?n4 zy3oUq_3)J*ew>G2>fy(G_~jmcf`?z_;U{|dw1>aY!*B5L@AmK;J^V!;{vHp1v4_ui z_(>jqn}?t5;dgj=KThuQ@Rxe@Z65wI55L#Lzt_X>^YBwV{C*Fg^6>2*zSP4X_V80Z z{1FfD&kILA{B(~#u=9fA|K%RO(8JI0@I@YeriUNu;b(dHq=&!4!@se5&x3Ci1mU3+p>^590`+dTLt;8qX575Fg^{wVN4555gJ zp6HVQG2r1I{4c;$J@}Kri#+(#z_)quzX7*;@MnP^^Wgh|4|;GbaJ*NS{Lcdq_u%co zQ$6@gz>7Ti5#ZZA`0K!}9{f$<$2|DEzz03}G2nRbF8TisJlunS06f)${}XtT2R{vb zn+N|CxYdK71Afede*t{ZgAW47`*g|wHSll`{w?rS5B@#yA`gBQ_%;vz6L6~s{{{Fl z4}KH)pa;iGkzd#)zc=u35AFv%)q_t2UgW`pfNzW7cLnLE&*c79L9qQmL8{~6h#>qm z@u`g%6l|N(@i=Mqz8M`)kgji^(NW&ndG|xyru^j@9jPGL`Alc$sV+z3t&5AOnIO>N6Zgr5Rt4R6awgm(b5XRzfX!;b^AN3rE2 z!`p$~{NdW!S@!OyoX)aYW^Ay#WiV;kyTXf43pQmQ55kMjARV0Q2okA|%r|Rh&}WuhxtsOu ziXax0EB}b?hmWZaGG87RY+^q)MET#4Zxen??~ax&mv>~oaCt`(zla5k?oSs4*CmHm zo|$>5_Zvp9)Y)O?q08U641QmQuj;dJ+@$uf{@m1FFnBckry;N5=PJ7hT-?FXu=W8N}r7A|-BWGuYVEDXx=ogq)i4jL1Tf#PK9l}|ut#zQjol<+O5GA<}HZ9%ULa4;%(Dnoue^>=#p z4c_Bbhb*6$(^+;rARiUqHNm~HV`a~@cijJU<@MiwHPigetLdSKUQMoPyEiyC?HTF7 zo_$DnbxWvQdGE)bZu`?WUrp`%*{hY+hi$$2re418iWeHg8EmR?p?=S-#Xj^0@vD4? z`a||w6c7X+hAn3F#62K+=%y_Ty}yH!4g*Ay4^gBG}DM5<#Veq`Ejbs2&V z!LVRKWt{$n#`qTXkD$L#*H5~lN2W7sV|Vf=_awh}&+=cVPEYcUtVFP)MSetE#uXBu zXdgBnV#*4;$`;wOp{{H|S6OM_sGjBoQ?ID2>>gXDSeIgK#)J2UN@Hzjn=}Z{3129P zZ;zjno`1e+U#cUDci*#p7L7B_V=c@Jd(>~|aX-L#yEm9DUP0!Z@Sy5yo=XJt)VFGn zeC3XW+LoqnG%nP?8CzF;GUq`zELbs9{(moHe`xW7416;Wkmpqt@kq-)Dhq-M*|IgU z!Q!L(rcdGZJNmQ*I-^tDIpKGt6M8tEenz<|Yd5_TZ`Zfx+$r1wls; zqzARH4JLP<5$x_fmHTS)v+>b^@G6XSs+7+&9yn7NB081D))XvgKO^$V|DfHE z1H~BnYI}P@!S*Teq0i>elm8>@*Cy@|etu zXJ&Wxi-{Mj@JHfB=9jtsV#?%?u51ndDEm-f_Rhdd{USQ`i((|>1K+|=R8BsI{j_d# zG^|g{WnbCb;L-&qHng$U43fh6yIr)&EQ$5K1VOje}ZcT zqod-U;3~oBt9D1WI5&LsudMlF=|S%Y_jC0XW21Odu;KtdVstAq^O1>TRlO`OZPpeB z_b6jrbB@}0MEoD1ZytaLG5t|&Zg@b?+{Jtt?B=|9h$%mW4E)@bZ)9D9Pndir;(ZYR zPEu#{K-RnJw;pKd$3dGM4Z1oxTh2&zw9>aux2;wXWC}R!71`5cxL`Uf8Zx2@*zv>))Ujw zQ$8adTJRB-PhmarnDr^yPwNSvZ=mtx))Uk*vZ=52L}m{$Vq`F{n7R2dK2)MTV*0$} z_IXJ&o=1oBM|kfGo}AIqLc8Q627VYA*}xs6oxi3$`mK5NJG$uEw?zJ3>Cr!*M}Me` zevqS2d-Tud(Ld2epB+D$(cvq9iN=riny$Yx&hKqM?8L_S>HOR^#kb8m(Csl>nSZuu zZ9%`c#aMG*ieFsJ&Ajq?;?w7diCbC!ZW)`}-OAk3axr~%X=?X}PQlp1^!zt|BS~!hd2J;3f~rFi1+2)^4?|iHvQLjUicN-Pk#|tqy5G$w6%DB zEN4EeH1~Q{D$W%;ZKed~fxVtzRtawsmVlDF~ z^^;30CrO8-+Fp6S_>FFXt_pslH)DdjuP`Q3$ay@^PGd#)hZtkCbaL?%1uM|6+~isJ zS6X{rjQkeLjf}SQL)iy9Y~42$p0P1Gf+O3XuC{FG-u67V8gdQe)~7#F^b5PE*BaZW zEf6g+-OZ8oQ&vyS-#%@Mwql#@23IMY2U=&K_XXiulxZxyv3hTgubNos`8;c_-Rx<1 zn>816im9KzAUv7+@=eJvp+9`N&rznmSQYk5B13yN$r5d{e^7oh?T>Nx2K-8LNBXk? zXKC7(M!Jm+wI0%V_IZ9!@{r%coEGUYHau)_#8l3*pe@&Y84#n3M@IW)t%nV5``GX| z9i4ao8QWzT%NfR&bV<3n6@SE+J06zadFz!V{QivZ7(U5y;eWyBSK?#WnT8K@FY>cv z@3Y0EW5cewf+kTP#vHKv-B!^&AvlgZu{bS5ghPRo^nQ!vSGJ{jQOQ4gTlp5NM@t@r$ z&-xFYCU@~Te$BvIc=W~-x?-a2REa){&F@8@414Iy)PKZ7tuuon;}1RZ+zL$rbrfHM zM0)<$^LUqPZzn$JC0UPZ4<|SgsBaCf#Ni6NaO)IHL^q%dcfj~9{nk(07r60;4AwQf znbS`)YYcp>P4aqJb78~z7t0RRcYR(d8`J-@Wn=Aq=xePp4oC-`18L5(`wi^Wv%R5l z_Lfc`%#(9~aben*nGg9p2nVX|v_oqM)tkZ^<~H>Wu;O$EzUeqRYaD`W@%G|f zaeQL91>ZBV9Gc%-`}wr7HufCQh<}Ugugt{o4@aXhVf1O67`_B7IkJQLP-o`S;WX(f zdtfWqFP)DUbM72H1C?Ly`DLHodtNH&*z;r3PSU?}|C!sa2h91yi8iR_Cw zAHxT}C%G>abYxyA>%h*h1o&AF4fv(#K-r3Rr+;u^D4%)+d>cOZob$Kzg;~Dumo3mK z^HRjupQE#UG7+DQXyLP0z5x9;C(oPL+lSCM)dRy;%3~i%&!4S2FU&CUaUJ7j%i}@V z`V8|dei%!=I~46FMT1Q;KZcHTq1YgJ&=;DU51d3EA1fXbtXM}riH~NmPrHqwv2?^^ z5o6i4e_c^f{<#-|aO;*{;g;%tVe40|yi7#fm@ltSuFhvtzJ4!x@z5g0_py8PxC(r03tMKD2GD(wg0~Q%o|^IV&@Dv5`5$ zmzf5K%oE>EX69levlW>QlF7PHIw}seAk*lToD`0MkNkq5KE$3S5hqf2{Z@7GOM?R@ zMsAM{#O{AC>!`N;%-J?DyzYSaVUX+qZ_%U`_sEZ+Ok*{Jo>@HkcL`6sOq<~Q zfcD6Y@60b}F#aFi#@M&#P|>qG_L95z5S!byC-U~Q2JVW-=w#Lo#HwgsdZs`2qizQO zUN76jL+2Xa{I<`F=h^yOp>gpxV19ek@hOgcA%?$}7SN~AjpO|c#Y(3eHZ^BphyF|( zC678?&nBWhh*{T-rA?Y^*oSC;Yo3)`X;!GQKdccw?}lkXTfLy-R{ikK3pE zb*EBS``(B2+z#C{tXJmgOj^%E3L}3J?$?w{_oVtTJvqEiGDVXJUb#|n3L34Y4-kJo zrE!aW;v_kkqw*~sKEVdb>96h>Lk_Q!6o6#z^8dU%sQI> z$5uJ(=%?Y!d!$jl)Ft6BsF&m{t_Ymg)VvF8Qk^#lc5CkJvnbXV=({5MA~BM@@Jijf z;*HhzxrNpg8iR}lqhsZJvh#WsI>=W|`{`r(i_2@g!2h`YI5B3>dB}2f@;}2j{T{Qg zmft-9-#^M1Jm0QVti-o@2Xx4PF>cnee(kQDP1}%+#tX8OS|^kLhW0Am@Y34&E5y`8 zimQ}6ouvCC*i-V{v$xJNo^SLCIu7*V489L@2kTvAtY9z5GuVQ`nm-QoF>Sen`sPeQ zblB$xowt>62h-Ml@BqF=duOLc@$8o8Gw?Mr+&n+A{E5p(Mo)F+pGltm>KR3QLDY|x ztb4lCOEEs>=~k+_7Ckk$4M)!dYg3cSk1k<+(SMUq!6ttzAI*`&hXsQVtZn0Lr9`|2 z!?T}K$5%e+o|~AqPT`plb53VNl(rN9-E*w=2I4EvvDztXpF-Yyj%CX9Jja#s+@Kv^ zs?QiXsU4o?c@8|ByzDyx*h_mCol^&_#f$fI&d55jgf&zN?;Yg7PtqE#^Y_KlQ^Izh z@nJ8Gliejnsa>(6VAq}4Doc~;o<`?ZS(>))X>Rpt+PkM&(M5BFe(F}Ar9MrvdzuQL zCe=O7`+SNp5}1H zdBv{&%w3r&&>=^3id&g4Blq?oit%4gO&-rX7t$%CIh}L)mvtTy$(zUCe77%${n7ju z=otI6OVFhiKBY^mCMm9{j$~FTj-!{JrHH5W)*9fj*3RhVbkws}(Yg7^#NUB7Mz=+0 zv2B_&+oN?2ze5Ti1D*<87M&U1abO^4K{l?L_+w+O+b>gpNAT?#I)CYS4m-Q|hh4ld zYt5@!Ytl}i_Q&cI@I3D@@8zg%>?KZWfsU9xx`g+0uxI!0=Um-3S$4PrJG`VeV*BoV z!aX0{vj_R#GV5KlPQyOoy^@GBy~Dy;#-0Xz{RZwO++%^ylkZ0LtEAsKLC1ZPO&LCH_{NT{eMY(lyvLZ) zb2aE=N7p{1^5lTF&q{8F=ReYcx$^0IU#GtKo)_7n)a|3weat>Jmf>AkjnnpCW=}h{ zUwZyGsUzK58q&MP3p>2@1Fa{3dDiEiYh~?!1-fdD$~-(d(_sCY`sTTo^bS&=Rv+Le zGFbL^^Mgfd!CSQhjedahlBmo^H<4svL*I4vXOWDJGN)UXX=3T{KbxsVvuK7@s%&h z4%c(G?d4ezXPt2b~d`rj(neY zb2^NFL9+ zpUGFdX^YRtJl{rU$)7k!fPe9^fhz_`zRCAlQIBmjMzwB8lJ=2IQ&w!sQs8v z@PtQyp2hCgS&QQ#T)_VEZ>jIs)iWy2FFq~VCRV|}I~{nBuA{~Im~=Zf^BL*JduS$( z@_t>1cmzq>2oL487jFNru6G$y*zx!35A0!l%k!0%imr98^Fu>t*VZO3u8wSG&P4Fx znBI3L#Rhl8lC0IxMRV{XJLc3U0ev8UN^wTy^VqKUh0)_5>gxrxbHQ8m_0^PLjf^0% z;*08MY!XYRpYG1SrjOyJ{*?WgEX+HBj3@R)@1TFZx{~?7(yy!2W;|zO6mg^E)whms zr{$Gr>k>l-QKp!#epRe;asT^oMq^sBt&Q{9f4CoK(@*w2u5QOH?~a-=!#kIXV?TJO zV-}vSKeJ;N9>Tq&KK1H5`KtTB(zhD3-Hb*5{JB!&E*Z_u|8Sr1p0Is)xBECc#jcg6 zczuG7ZyN`BA2_E^sG~jmJMI&&zKJKc?*B@k5Kk1_(%3yGJ~MWvyu!F+PJNG3#^I%; ziiK~i{()U9NAIzjvzz{QY^@E5-}K*V)>AigYt7SN^API^<}J-x8gm)RBOeSo)2wGJ zyNS0B$G1p_7}`WID3-EoE*CfL8tWeE$R0VPSn932J}tcV#vcA(h11@cwLfh)&w;eJ zQ{LEty`l0|R;M==N7s6B-sF3j(@j}7b2@7xvxe~JbZC=qPM=75H+J&JhMBX_?Z1zx zO{tFmQc4?sLYkysp4FWG{`Bt5&G2<=0Q%3Y0n`uRnOjfF&@V0IrOy;%QTrEi=U09M zru9w-adfn36wlyyI%9WUDhT>z*ux1=Jn2Y|BYce5-NN2abY{IwT@%-!)7i6l#l)L(@suB_ zuGSL5WvbDaesgCz(1tCX>$Fru&pZCw6Sh>Rv3ugFR{ER$x!G?QP+v49?8{?1OC+z~ z1e~C`1p4ec7~i1Htex9#vFn#XMyBZV*Ye0R`(T~T=q$^fFX;?aXJXNr&1ALLv=tbA zpECNI@e|9w^RNC*!S6NsPo52AOTE{e^-&A78OFJ6?vI;FWV?Pe_9r&+drb500(+m1Ue?bFte?e51AM;g{Yv``kmn|5 zZ@ZRv(#nGsd!u)=ca)6ld)zY<(M_PglJLQ%yZHvlkd)1jAzx|pId|0d40;}S+GX?2=Ln5q%Ge3rora>gKx8WJtJ+mdGEY_ zN02EDKPsDWmXP!OZy?X*25Kzuo{(&-{duNe_#yETo@d@!d|SWp{SMEw<}ALwUpUX< zIZw~xll{Zl4$tq;viQpWp`KqG{(3*j$xZhU>F)?X)Wc``hm#$iJw%qit$#St;gcS| zy?=PV!;kdv$pIn1^NskA^6-@dI8(KF-eJx1&kP99aCpuPviP4$Vv1!w}67MmwH`}c} zzQ#qB&JoG0?_%VQKhwW@=W7me#MEgkrfuo@`}zf&zE{Az8I%WFx54+1jGKV6ik57AaRaVBYoeX@k)Z;7qk9qX#Ed6sH z&k}GS@n~8s%~N?a&E3%Kb#n3Te7Q?K`bRC#Z|Cu>@MvPT&0o!G71z0*_{$rBVEI{w12f@Gg#l86%G7DkqoN zkT3W59({}DIW>>xuRNLqmPYZ&2V zfcekG6&IUxXj0wNys_H;-bnGAy@~&xvTPZQ49xGrmh!B+1UrDnJ%stLf#rpM<~?Pz#s~K^^NtdAn5SZ_ zjg9_o#o;yd>B;gBc$oPMzUKQ6z^?9-J=DFNx=}y7--C6%2i9_``8`;6o;7pmsa9Wf zn8G~USMw}+BZsxKd5_Bar?2A}ksrxSKW(MQ$8fVz#Ir!xI zu=S}^*<0wj2hUcvp!?Rr*mw%}rQG<5>@7Is+At+*!zavp5w;DdraIP159;Ww!?cU% z1Z#wYM;1q0Zx&8{h@GXI`rh@)0Cd*#VN;(zmaQuDd;ou0AzTno54s3H(m9ZCvtRPw z+XJ#0dYFDicYP}-s{^{euNz(Gb))N?x6t(fa{d-wH7@dX-5I^xn(d<%**LmubF6RKewoEHJ!j8dR!7qZ*j~@QTA*viw&$yDuCK7kNzNvD_Phfgv-9k! z=Xp-X18*V2yl3OdII4FQ@43(VT(%Uh!pQO8hvg2Gd@He?R_33W)G%)nrEb!>b2pMY4n-k z>IG3OQ@wU%h^M}v)QfsrZz~pLV;Z&`#`3g`A6&W*LiRBB(Hv;c%}L_rn~yzqkfY53tfHYIMqKy{p0L% zwf2eM%XyB@JJ=mMM`$5_wc_6<=Gb?>_-L`eI6Ycgq>kJ1IJA*yg>9qWRvHC-tm{=e{wWp-|t&kY6i? zSY7mvwuw>jTc@_mr)3{&zpc`nK8xNR$n$CDFxTGfZ-(h>r#JFvn{P=(>y~*L&Z+g= zaWec`tx_RG5Z^HaBBAzYPa-azN1a^^*yYG`u+WE+b;ONu69{p zJb+KQHtW1uw*HK4&3M!KBXZ1dHq`zW<{;H8wZ3YeS@Q0f@poIc&z9+&{Wu-LIUU(^ zZ}Roz@6R2tqw(L!zvigjIsVl3{TMUfdTqW|ygYa~uxO0_#gPvF8E3|`8SS4xHn0A9 zf@z=e3;5`HW3(1<-ygESGqW(vABNurOw@8#a(>wLU0_nU0Q z*g)?+Tpc$t>wI{bc=JLK#u<~p18$kvH_QNEMgFT-Pu;EjK=S(DnZ}a&-Wj-l5pMgl zq|sP-jNjuF+IP7&Rq-glUm1C zp2T}zF}_n6Y)=m|zf(28nc0I3=~%pp{vuUB$L=A|Z+tReV9b7*zWg#{BA0Zm}8NY+~Z}7VmGL5Wt_ zm>RPE0dS&w5xPHWoRB|6-td728Bbk^A7sj6X8b7S8xPwLQujc?$!5$9mMrjT%WDg; z&WBBZg1^<`rIY$v{-RX3#@ioR%e=Ar-;ZAd$Og>kt&IOI*yXFVLH4+U`mNNFj^goQ z!5SybyDH~AYg5+tz_-(9qT2ruWkL8WE8m@! zyq%p@m+vPqAGx_I_gz2El;2@lmrmlTdYVsUH`b(P?P8vhQdW-NsEw{H@-G|npl7XO z`^0{?tt|RolkY#iANuo$Zg;yG!S; zGB>8M?<4p(gw#2*)}*#qNABJ;d23e%)117zIhqn7uK3=L@Z=Y z{InaJ8R%WUggpC(XwSyDW#ZO5l^qjFT`YUza4tr5Hm)cJFfMfF^HtiPVcZhK84p87%a6nx*_-_Fp5@IR)bTUF zPh)On{?+%JCm%qUc6^bw#1FfEQ?@NT-x--(Cm@KxOAIi6X&MR9HL_N|f& z-D0KGsWEUo{G?LpAX{xI2!9XUN}APSL_zqVr8$o@s{{1s02>{kY1tA#PKT6q0Pl3T zU3`G2E2U1EfeXSLl^Q#s!{dqYN5HM5Ssls};RZ|7k2I?TebpP-=m1U2;|0g*P%It5 zI~^8@5AaB()EREzL@4`4cAzg`=oLN;+)A3&p}JSN#M1ocMNbF%{#U?82WVPeNF1lb zn>srK?{p{?AK(I|)QK6mS19{Rhk_lE4+P0m!l*x^-{>29$^*(viBUg9Eu~edL()j8esZVqSr>dvIzv)y@O@PST%{qd1;Jlgy?09W=S?Kkxg+cKs4l{ChkI z=SzRm!JL0!o6*Xzh}zP%?*>;N;kHY@KS%g;q}y-HW-)9gUYA(@hq292ow0!X0J!WL z8~7T_`I~zzenZ3my%|E0Q|+kSs$Z( zBCuqChcuG!exs9XKkey^e8p+%#h_QJ7;I#cPlEH?ILz{vzvQ+pm$%RNrC&#UALcjt zu5bE9d~*7xm*xGb<9PRAH+)$7J|q6tZu`hPyN$JW`-7GLJ5t|nzXA5`_A6jB{HSovSI{N)>=zB_&%IFUq#jojcq8xArWY-RT@wXL&knE9JW(E$4Ne zwLPluguwe;c(jt5xgZ#-v$lPKzUyOk`;Jm@_8e|sj56RI!LAt{-&NTQK{!-ANDYsq z<-vD+Y$K#7CD~N@C#DmoENI5+wg^$|ud-HklO&!PMK9!A#g?}P#B{e)M zogR~o{Z#%h`8<-7vpnulSy?QU|Fn`C9%-k?M!z1JL zxFr0fEnk|?L;hfGT1Oe{+h}f}Up@q^zWx@enJ=*CLW}#l!xhBB1s3-ehZ_+Kud+DV z-_$LOg|jT~3l4{#(=4u4IJ4$96s_7z)s*06RE#EVBsJ?I_&wSU zzZUB04CqYwiGDHk<_w5@HF?7in(P_S?XmC%(URt$0exCyAABcr#A`V9vu8lyJ1l+} zc=gLQ@KLI}>kKH0Io+PYF<-bdxIV}-YaIIYpuYdf*#3a@0@nQTv}BPV3N9OmfQML_ z7m-H&)pgF>txWIS@3(yaFJII6eOx z*h%?-zk#t1_^S?1_YJFnzwBWCc1Emkdj3NW=I?5hQ2qsAjiVrWT6ngxeL;APw6)r< z<5Q=xrj3W+P#I~AI*;o6jN}(t`a6{tB*NdT9;q3Zs&_lTt>4E^oB!`DPl>gfMn^uQ-MdipC%U(hFf(eUq+rT?bk-zV(l=;=>G--bT7_X&Sy z_;=BN$?)$Jb_g$h=QwA{GFu_$}i`G{TjC&C~2vJT{->tO~0IeJP3S>E2pm>0nY9t=!-7_>pf-@%jp9SL%Y@q*!c6n*)dyC z7`6gu+ov&z&CX){=HTe3WIhgioso~jrl;iL1_8^rhG4gB971keK?Q%q$vYRT;Ebw* z_r_U=wCG%nJ%#%2AY+?zF0+47|NH_tcdyXJLv>zJEZ~f*+p{-M#-mn-{6KQ{Qm>bl z<9y@sw~-~fpZu-zu$$yP?8~#hr#SXjZ402={TA}n{(!#PaU9K8bDrx3X8m?r__G(X zF=3+_Fx|nnUrK?E&Du{3KM9}gz8j#eusNJ7Vfn;9z0vR zc=))*UFmR-^Zd`^W(sH4SwFJRin{z<{-eI0#ahedFDDBR@RxY`i^&HE z*U$e0-&1q^CV1sz$vfU-Jp8#H{%j9F!pkSg`##-S(D%4!jqKzk!qg)qUw>q%F?e=dV3;#PW4E$ z^$HT$MEG%)k*e*X>XDyd>5aaR_cH#|N}8=# z)+@Y4G^Dc8?W#w9q;Sv~eXDziJAhkBv-Mu+72Y5k(h};eR6X*i2nU_?wd;v!>@oMe zbdWMq7Yn{?*2%rYzN$mN*!4t2&)oD&(UUs*M???&hVY{IV+V8BGlqW`{pSt;KH)2l z-o*~Hz9|g9Z}@ku4?b)77lyxb^wE04>R%Xs%kb}_|D@qx82-1T=Wn`YTr4Z-8-CgF z*WZhY)=#$?{(ZwAS$d773Bp;Q7JPw&X`A5D4n}vuXFJ%gU4}at*)ht`1YY9icl`7b zWM${-vV!nA;Hj=0f86euzrcD0ID5{C-?jSXx3gXWp5W@^U!V2MNAwCG10LM z_RAk&a9 z4&?iVyw`MqcbeLHPlM-eH?YAi@8mtFcHV6&-Wgl*FzXTJwbyM2{}T`PW_BVXV1_vK}OKgIK|7M=fUt$}^y zleZ`i3&yU3R|?iyMdp%lDZh`({)UR*nbqq(OlU=SLlnO`uaCaj)0Vd;tEN1EP4;0c ztAzU3y88NEt90TVOZL*a7ViKU{oOP8x6)tVyLbAF?{vY^zwMH6Ql9=Vd-`AM$Nq)d+WHX)i&VII(k1Avz}RQ_;;=2%0v(TlaAhx#brEiGyJ>OWfvR%@$fcB@5f@| z+Csy>i~c;rKOWv>>1DT{>HET7Y}MbdFtClC&p6n|&L2D2`t1)LjIJ^GeIGc@dryO- zelTlk$$8Y`PXJ#!jI|dsFC(8~y--NHu2+Q9I!d?#(nl>$>nP#g7I(hIb%0x^ zcje$W3S3E1ls}7n3wj7YoP6n!C|^uIc3PAlro6?UrhH+9KZX2(lcRjL9kf^N(08D- zu@_$$fh`rczDVlUu4h`@Hix56PqVl!4o80uvAFvkjy@Y`asNlS9@egAoZ0@kLH76J z$Px$J{;0Ng|FYhp6&-lB<3kp&_ts5+P`01E?7USrm7T%q@8Jrk@1dLi0Qa93_gPZY zAK?DO;`DcPOVl6Wo={%>LH<$lG0XG23+P_w!a|h@0;{xw88x6W+vYXf)qQhJlgymhqeR$~O89ulYS2^U4@~8_ToRvs$n6 zEW@;2?+#*v;ppYs`#Hu*c3wKh{Hy1f*wd9aOFwMwVDtBdz4_%;=_~%4Z_q>Egoy0t z-huYs;duak?+qsFUH9xaQqg&ibXNSb@#qWEnRn)6=*oADCMWd`8}hC9T0Nk>S$cDJ zu6NXno!)9U-y<-(LNi^u3&(d8%zNw58a=6J^hSn(d1qhW-Hh~h@3nQWx3A|%&~wjU z>DRwTKJl=AbAY~ryVLm!>D&o@C-kd=$kur}56#yZTB9TNjLz^jFmeyR6P@o4CU3>w zzTQ{+dUMY7GWKu5wmEv=-DO9`*sR|CPTPFbmUf!=(%o9cv-^vj9h%<&*tWG7BuBeG zY1cWU-zQ%C4$GIk_U#vJ{X+4s1ijx$A8qA(z^n< z?cBH(TIyC>8*W90o>eK%NuK;|B|fZgXB!&6 z;m{pTJv7?$MSM=|mZln-a~%!u(Rat^gV5kBme1huiEi|n2hFLDru|gjzdl~)nb2s@ z7wL0Gx3Z={qqTLQb$arQaN92;|A>4f?>$=fPyTO8s)+S1?6ur)N)Bi&%ZBV%#_HWh z}K1!qaXx)1>0q@56XWz%*p%~p# zO{^{pLViob-&OJ7ca7fZHSa?6E{xXs>;>Vto- zF5@>U(cGkZk?o>>aKGP?Ua^2(y1lw`4if~^8yg!MFG*HcElVzIXihdPuU(dGURs-6 zTvuN!DqCK+?53*vx|(El!;LpqEvrdZEni++)p&e)O;vMMSK;yH%~i{jP0dx!wT{U0 zH}#qutClUUZA>n%LU@g&XXTsnn`#^D7T=On99*;PhGh*mFH0Ie(97|QxQBZ80P;MC zCS>H|0fXfET*+C>malA1mNhI}T(@LpV^woq!?NV%D3MHFl1wJgYT}C!_L^Q_wY;ge zCfQtfV{LNOS&NfRwbc#FYMRdN7m-w5UpwKZ+Ug6cmoGOp#wE`_J2~985@n?;MqJ)l z+tif2v7x5+g5icPIVuux*0>1^l{+^X!KNnqMdn}J(0F52bMoe;^iu7r+Uk|fb<36{ z8*8g-l1+7u$+~3`0qU1T)m{I+HG}1i4b{>|JQ^C4O*LZG)ZDnTT9z=Z%4f|t9LuLg z=}ZgHw6JZV^OKpVG`74^9Z7#0t;ZyjE2H)|EU#9>jltA6x<+!V&q|loH!P{Eu9y#l z((7x*2M)MQV>6ErgJ4Mo7OtpntiE>Khm!9}j$4JnR*gw^p~rWRp5UP+c+twmxZ1U6 z)pX&L;=kw?d^5{9*@Hf{%W8}^x%!qZty?~;Ms4d-*l*8OD{ov>+c@gnv6B#RR*f-0 z!}1DK!8Ika3Vf@pnrf3+*U2$3*3W?#%*uspY8O|nte2&1e@LaI@tw%2qoFk>xxBts z{HvGNR^MR8J5Ic;)^v9ypkLBdomImKkX`(CcdrJ-}jjTEOx&Hu5tILb;N;7)Q2ug3fL1Yq5+j!Qq)4bGLlU0O}u z72Fqbzn5EAS429FOPY|3kJ9lL9v{KuZTWaxKHip(kIE@F z^rVI!G7H;sTc2uCxvfui1Ka+bS-Yydp^PSGry4K{94l*+XUTrLG)@O`pTVto&3Dg? zO*yv@W^&Kt-uM>x2PqS;dhV6n@{Nykzg3<8$+Dj0qe4)_G+t9%pEqwWt6Q{4BgGVI zl~iBfP;C|<(X7n_i`rW%v=(Seo|T-?HOzx(-p{K~SjuORb)H=Ry2=QiX5@~lZ(x{v z&h-}SxLNh}wM(k%lU?hqXtGV7wK5vus+;8In{kNz0_K`OeZll{a~2vlKY1#t}ROQw4xt+*%uJ9j3rBiF-2lCESXY8r!?LcXMkF zxQzQf+~47rt_Qg_QU8qlFWf2aQtqkTmvhhH{uVdC#|_H3r*W%OE4deOS98nchq-kv zs%m2O7fo%KTvBl*t0TJ-O)gtmUvHKGW<3*;n}6e8-etY^%PxTlWfa!dERndNrmits z?$`=dtbJ~(t*CFfIYOKj*%O0B^J^YIV{8f?+h7JlF1bXaSlBJD$u985*?D!mP5;*R zu^y^tmJb^1nv?{K8k(0%!(|Q2Ogrk9Mfx_Zq|@!yojtB-u39pRL7U$W=P$FC)io!t zhbU>x6&P5RDg-B4=Q-|yx1;RB&8e;t`yTl>)z-`2HxW$hnwHmB-JWot;B_Q=c?N`aFlm3rUaO(%G3Now)}7q~#xlFX;}_qof1Y!naQlT(_>Xb0+ED z^_`u|Nh?3r*~xcPf|`Fp4(WwFs60Zt>yyY~Q0@H`a!5zq$3|4&Bt* zxr21(XF5CglWrnCLb{W5C%R-#3D~C%`vRAf zRsuJZZXi8O+D7{Nqv%6g`55+QvS}urM7n`=F6qOht4NbRp?} z(t6S(q#H_O_8>dE+u`QbR+42f5&d5(@5KuejhnFc@60((hTWb(w(GBN%xbc zNjE%+Je8B~B^~f1Rko`arr z66r?L>qvKzCZF%@JWP6+w4Fu5{sYuwb3g7Nen6Tbok?2x0(uC42>&E~{@2JO|T=w~_QR{s7!A(lIY1hjiTU@Jkjluak}=E&l`kPr8*f zP1;6Ugg%E!N0A;OO_2`eFmNg9G}4Wvt4Mc|ZX?}By-}~gpHvrSGFR-@`9WgUnXxkl z@QV|!k=(<$H(XC&2vK@sa&zMTg3=S-RriaZTO!b+o5nqp!{xc89^Jfrx_XM2zXQ5W z(A@*wb-Db?eSXqSSM1igbByMF?)~{$vEU4+|AmxEw^isrCPp9JPKTGCxbO7R6OWv} z`AY@&e^E^-z3btE`1D`={Fwp8DzSBjK;Mk~HNakbuJh%K_hr!Sg>EM)bmKPnzP}et z}`>za%fSytDK5h%UJr z#Z~`F@N1YehH1hqJ<-XDulE>;?se#vH_=~tbYUKy_}sIyvvWW$UFltg@wL9*(VQZzX{e-MXX^~<+aZjJQ5aTpsW0J z*3X@O$N70Vbeo`C$XW)unb_tb_YX#J!Gd^JMe$n$-4pjR-q91fte+QL9Lu5G3f=k) z<1o)JQduh7|IjUM$@+OwyyisXe}}*yZe=`?BFFhv!MrXphHe0B!=i1>C6GZ^Wcz7` zC&u{Mg_cfj5Zw&xXLG<0qrQ(aO)_ROZcPDh22Z@srU#F)ZPK};Bp&P^6 zaBCjF#d-Xmhi)5d$DDTSGFG28)YD!=<1z7nOufp@1McsSI#ciJx2f-E3P1XbpZ`Ryi1dFL`eV@7OU@cY z@A*z7f+BMb;onWfjY;fbl-Kx@iIsmC{DpaV`Oy>L$AMQKde`2|{r*(h%g~L1Zd@*% zAI6Qp4Pg%@Id4aI8FZIHS03^6+QiZ?TGkkTHP9`EZtih(n|jTSy4%p*3Ef8M)aSIr zjsKZ`J7fp`K0>ewI^RBO-;=h!^=oH`9KROb>(H&I{@c+FV{f?X9nejKt{%GU;O*({ z4|mgl_0VOy(R)4k``&?^hoO^w-cIjlp?fFoI|iNFmyGmw_R1M2ve(D~tQVoP{^0sK z$8XdZbD$Hy{C=qc-~0~rz7sn6$=kJWCv?}n1G?v-oBIyv5)8>{(7m0%kAZFubdw@` zIXleu{c{Xu_gVb{#fJwNbX{w4*3N6PV?%6YtM%|5!&yaA2*$hOtn7Xt_zS^b7U7*d z=9^8u5NZO9>OTS9Oz3>OEB`$BY2d{RzDdo~((f|xbHVROpx-%0zjVRoarcik@$`aC z=NF7(We~+L@fk_IeY@GaMtq8U5f*gB@ zUV5jXuOXj!jo_JMKc+JqTO?NW1JI)x`ZW2(Glt$<>#=RiqnF-KIDNj6&;NLR>Y+d4 z==BAF9DRb(~p^ zls^{d=ri@M0h{`NreB;G8BJIhV#Dj8pS#D-i*ZB$w)3Lu>BHi8x_ZwsX|wjto8P;g zPoI=L+N1qm;w4kh&8MYz^^0%xJ5av7vxs=aS)7d%ZatI}=cUg`(V@=}`S~8hH;q1- z#O7)DmlCMTd zW9sV~C*pS}bnBs0-jjRWJiZgU^gH19Jak*%0l$RK=H7-*u{;;$2VU5EwqjygKej#g(Xq;R| zCk^;d`VD`OzV>`D?stUxp+S_$c6Melo-6lt=!X5|?c?V#&b*I8 zx5m?Nsumw*pGo{%!SuW1_r#d|{%ikFe)`O_HhdaCE~j4Vr?g-7ysNV_He?vck%BEQj5?;h`_fE7G2G92%(_R?d*9S`&%_F;9 zX3o&mk|cVJNo3)o2(An!(YocfDS0#l@_4+HIz_58E>UT$X88_W2yTBYaU`a;b!%9< zC&$nOa;*9{*mTsK1gDntYkPsr$(Nn*hz*J0`FP^KM35;+>>yvT)F_dON!c;7^JR(W z`(P>_QeKzfRAH(5WIesnORRSE3cd})Ucug2VqY&#yA$c&L7M*Q6+9eIWO@g?;)#vD zgG2E|TkqgVJh7uUf7(PGwiYCKOiJ&Of3_ge-aB~RM|uZa6T`ozY9;ALfx#S&Zj;c0v; ze%6iue#f@>$-c1U3F(}~*1quNnQ49ESYfa#ahSg*gM0UuL-JQR;mq@0y6$lAV0}En zvs^~WhCUpWCwBD-_Qn(2`UJ1X6Z=uOK*oExAaS%$u&W?(xDQqqx0eeNJjuN?q5OS` z#65+Hw~9ZG1-1sb0`>~2@~2qU`}n%~EPZN53&K>TO=PYe9h0{^tYKP~W23;h4V z0%u1`RyIfJu1`ei*3Vn`tSEK=x&>!`dZi_B_!rrJ>vHfbdGK(%X&w-f1(nGt!_k_# z#%zmHUNbS*k>?{$XIMCCQ~R1oQ1tVt+?=^k=Jw=&e6zDbr1$6e72vy4XdU zE2U?!TpYcdYmm)YGV@y*6|gnQxooxI@Gm3zR!p$UGG;YzF57(b4zCc0ZNnVClJ{S9 zIlZ;+*2QV0xmdNC>#v)vg;}kb>xhM4wTgFG*y&}-{>PG}?T5WD zM)o*t{p+xW+ijXJFm3Tme;?J`mq+)cg|~ens@axT{)B}`S-;tD;SH8wzPz5`bTTUW zXZlY&$O1k2L1Z2F4hJKDb?~cXgwgOeN3m$=bMS)9Vjx+O(;th*ut;Eeeun zpEdH$Aw!0wQ|AmlyHqDaM~b+3@3N@KoDT&96I{GYlt^&A{SWgm8ju({a^zWO^Uuh{ z5Tg3Jb*1A6#$vIx>(;G%1p&d)4P1qVorQh-u_a4a76(Pi;&iIy6!bePf;aV#cTM#2 z|FC{RYTTKw{Y5ZFy^@noD2NrDa8gO>x^+m8|0VurD!Knu?8D2c=^5h&7A=u_g{PFH z(o*Fu^-E2Cl5?B#^76IZ(^8PHO%?^6C!c)sHJ@1vloG+*tM<-ZyLaYH6{nKL$+>gN zQmL!w&b=-bsB41TK6b_Y*7;X_ES(Of-nKRt6b%|QsFNForTfO@JsURs=93#XY`Z6j zPhAJw^!nMOibl;y!*1LkMvhD$y056byt8~wQGnq~=AAwCoN3diS4^KiEl8)=uV4S> zZMWZ+?o4x0HI*D{CLiNNL2}%~)#I=-9=7O%{~iRxmkb{?C^ha=>9R3JW6Gd^8~=H` z_7^5b3_pAH@V|^yg8#<)_U(IGUEjX5KJgK9G5q0ZpQA;ee)ZE__v__geEWg_XWGai z1BZ;9wtl_QFF7>1QA4BNm`-+Mz`a{{A44QTII@*jXX4R_=tmD<>}J1@$WPrh3>>3Hf*?h;mGp!htPKU zz@p@BQzx7lkH2^7)JF8V?bhM$>eriifLV0ST32eC_cr54R^g6DI0L+BTv2i1hMD6| zj79eOhvomjJbq@Bm0gk?HLZ409lwmf=z@tCj5~k)r1NTO7foI{{@e(WoG@2~-5DDkEWm^q?82#%LjgxD9Hs1lAOal91)@Sy4l&>mDy398 zMr9ii;1nWuIVy}H-|K#FccypdtUFIhH?!Zoe*O3Q_3PI&^8$p+6#_p-;>(pEiLa>J zjR7`lIjl&r7sL3)b-OZ*U!uhR3gau4*ll6_QYH3a7=L};ZVcm>)$QjnzN$Wdh4B`3 zZbJ|;*UQ!AO6>07-Q{Yv>SensjANXBBZvr}HR@h^3CTK^@7bG~V3)yJGkYpN($~WQxmA;{QdeMF}qUzoBoI zAA>i`!)F%E_cB#VfFN)PpU&d}5SLHme^mSY0{Aklvh4mfd|FhmRj-#oPxZ2K(&2>9 zTJ)wp*EQK~m!ZRm{!xqm&A^uh`knff4#THeKIs|cWf5|F3-i}6fEpG7KF#u<*L<3B zlW(&eei-yo?P=&&s~uMRBd|8g*}(Br9}h7;#Pll||32dx#)Y1S3Gvxy;X8D?7S;1M zX22)G<@+0QSMaHgf|#@5r!3smt3|Di#Mh}FYy2AeHR_n9mwt`%N449_x?by4FY}T5 zUWR#sRww>0jNhU8tX6k^+29V}{(HtBWn88cY3GxVh50-S`lxo6@;tsR zOfTg*!~Es0@E`fMAm;q*82*NSy*k0|AgLtZ9Ycbcv*bJRl`#G?*Y^zLZG2nG^So7_ z>tRzaRNvdPVgADB#ZzJYg&6sia<+aoOfTbFaFJUX*H<#V$d!!iwTufri6xEegoT@Y z*DKrqg74GnadD2@8Jn5cra$vPCPyic;lEA|S>xrsn!bSxeTDIiHIDwA z`9Ejzp9fBQUa`OP02k{?#>EdReneBAE7W=RKT0hOzD5mxM-X%VCHO@3yP;pLR-O#g zOMeM&S_98ZYO)s9c{ofj{kV$xNIOVBwlXe!q#xH>xbVN-5Azp%#L8E2KL$S=gTFW% z&Hun$H15aXcgNt5#NbcG;Hz$n&i6nJej)~cDh59ngRlBPbiNy7@WB{-J_bJ-gFhLA zKOcjy)DP1%$}0W7F$UikgO_6PyJPTUG5Dz%{HYjx)g6tp)0LEe(8A4le1p2@M=|st zjK&Kw_QNTdG{`+Iff7B|clz-mBrTnKJ3YM}l9?!<$=VI`+yze92g#Ta+ zK5OBo-`A;qRN%lNe9nG40OHcnuUE&d{UedX5iVzjll7qe$*z!nQ(F#K#>nA@AB6MG z#`L3;5^0 ze%VUHU+lvX&UZKPD0z5T<1MQFGlr0!NvGq982XR_quRd@OW8H(-=jY@ga?@ajliSm3mR`x z@?6IC%)iLE_+f<4hhq5L$Mn6dAO4c_Jpr8BU;K4E?A2pT-*c}aOfdZq7(ZP!fXLhb zG9OvLh@Kg`-1PhY9z$P({YS?H@K)+aYrdXh`o}rnAw#Y{ta1JkIMKUt)Gzm1^6+2` z{Yl_dU$IZFXI@vXj&A?!G~V!wo?!Z3;A<{w_Dk<(da<`pu%O%uobnYrNAjH_J}AFD zZzJ;j0j8JrskG-~%>T%=DaZ+yhaWM%>WIOmAAhF#uTwkNj$(54g2vaYGgiC(9{9Cf z$KYvQYjpc;0#5ak^?N%fx`lD^8;G8~Cx*`#nO@e9Qr~AZeT({?C2tq6i7rn@<1Om= zjiw;_8yvVi#Q2Jj8vIUkQeOeC$K$i6W#$?G4%0vWrv^C64flekU$5@8+YLCigZRTU z%;z!;>Ni79#J?^5dmV717k`4(_anfg^Z>nk7KLAY1>r5~-p`v1@8x{Ic^&YJn)idQ zW%?6chEU`r#rWf+2ABFyFusEMi{7B`YEiytHyQdDIp5C!CwZ3V!V-*s893Ef?Eg;2 zzr%bsZa2X5jGxvx{|KC(XL@^lA;@o}K6xDkkIK3KKEvd@+>h62JiwSQeWt&1hXJM- zzXv##U;G22_s+%ep?AQDUe-<0@AS@BR6pLK@fMXhXfmAVaz4O#`!R!mm&^0pnEIZI z;eYuG)-&uMNHCwLW9Wz9Xv%NT3-4oG{3@)dukl=BF1;?vIdnDonijPGN?A7cL7b$uJ_$9cvd1U<>8Jg+GI@+IaY{#CJC ze#7*4^LXd!OTEnW$3J2i%Q$LXYszoy!*>Cv^0!tD{Tc4x1B~1HoZhe_dVAl0M$>a; z0;juyQ@u9we45~Up94;EXxncObG}1X`M)2-|DEfi`=tgvN}lhD!JpQ6i<12m{Y@j3 z^|!#O{5!1jx31@Q;0}M0>$OSa{3CGM2At+)d*6SU`J6grh);5wL%^wh#J?(X`)^F2 z$QnZF-)A%)$dE7pkLicrX#o8VH(a*W`!O@6xNuGjYVE7d`f%=Ce+nXM6sPxvjpY>G?=1z?d(`f$R3X!vH;ue~K9T1cg#Qza+j8|3l)3}!B2V{PK{RUHh*?$y$vK=_lA7?!v^uxfT=CyJR{*f5`A&s}- z+s3Ap_^FRaW9YvJoYo^f&n?q*^M+jgC-X^g|31$6ON>AFego_`$<&+PYT8)`A;7J( zOyAD<{9OhpF@7WC_wxjmVEiEC$9O;^JAM3QxoJ0fu3!b@w}YPKT=qS$Wc;}1!#@J2 zZ!^8^$Ghxpru;{C7~=acGUvAdC;s+2q6>H;z*jDBWO~_;mhyj!`5*XeL-`~pc!cR~ zIr#wYw>eSM9?ZsB!0e(K|+jGyNLCwlU4 zfs>q{W;s8_^j~FqTaSH<@sTb=xS#3IFrJt2SdZWB9xeIO(@1neb8O^D&L{kHG1b7<~0ROh4M|qrJe1zt02r7|Y>v zF?MN5(+4u-%MZoiKaRnF%K096w_&h?1#SiGU9E2|{i!xj*Q%RK#nH{<`TXWwu9~0d z?%ae=^-s@k8ZS?8?%v$i#{ZgcX7g3wX{)FW1+`)JHE{x?A{gZnCBQxGie^~Mq6!mGOeq?<=z60Zh|Ld6{~RYr3qx8PT* zH8(dst0>4>$@9HJ+m_Cbj%XqmA&H7^u3F8_xn9|?&Z)6#ZqjoL)02~PND}zvg3=F> zPUebb9j?W_HR}&KTc?U%-aA~ZAv&0Zj8N{ad$zhR`oqo7&JHCV6xBq?LZFBIA$O`$ zD(2@>AR`VPIyg%XH9$V&2JA-gpGwtJ!LV-btwTtsu$O@`#59 zf?J)f5uu0Aic){v8=I1}#ZbhS(&Ep$s!k8mO+J4M7VyiEr|a}mH0a)1~kCcd59UIhL2 zp}qZmLr5|`>ZaXscY^XR-sY)6Z{{XxhV6)jVX6@(hn#iNy)7KBqrVIC<~S)u5j1oH z#K(wAIEZ+FrAn?q4dIo>Hc?62Dp|<>w&A|rcvWi8AoZUfgL1un&rNP>2NO{IJ$LXu zd-`^#2S67ZC514cg|lAKz1y}SVvjr0*FTgZ2`T3$dwaJJrTYi=?Q=WYIsxs;`cAt` zA^2Q`E%DMrlTHdyr;H)QOTqw8_qqAh(5RD2Z9%w}2~ekovmM0J>6ZRMB)^f$&0apU z3kn5oMa|NU$Y}2HU}{Dq)Ot>`=J|sXm?eemx41NL5vnQ~jGL0qqZAGWOmY!2vgp^+ z`BXNCKdF?O^d|FDb6gWQ+2(8kdyr#XKtvGQ5u-bgKtAJ@>RcM4Pj&37-(hwmZpztG z2ZcN}yepfedL?_LUK|Fje{Ko^cm_;tOsXMTZBqa??dbCLVn{d&x?sT|WOhQw0E{%j*3K@5~_!sJfwxmPc zJD`4&PIi*a1YEjlqY&vD;}7*NdF5~eahi6b)`6`MEz@NQPmy}X;Dm4=&Q%NPxC*0! z!_-LKRd2F_;7XYEU_X@eUYc5<)1RC2jQA|N?r6zO9!)snX1BN)BwF1dtM2?nwNkG1 z6gY@$x|H?1bUfGeP{~Q*KgHYA2b2Z4l)z+ommXiHk-DhDgC<0gJ6_FAOv%xZ1dnCo@?QWKPpQYDk32N5hV>sLoA{ggvB zlP3W|cPv(YJIP?cFH+B`8QsNMKiSUG)==Y^LomVRXLIf-jM6fx_54I{FXpel{9sWkZ+_; z$d`x;Ew$Av=MZVoEsmx4)v81dZm?q!^4KrpMmp2yj<^|Uk5reAIR*t{22ch=9u@V) zT#1-`FzXhxq^p=JS0X?b|MJOVQhCZU!`Qi3!|ksz=If|-UbkjA8$ z_54)1fcS(I3~=j6U&hrjQjrSXV$YuKP`f*0I#+8JOrX^Hp?Sj0pq+skv@w$E*13)& zjIv^3RL~~8lzA}Cv!e@}1LEOQOy5vbjAP;Cy&r2SFWjDbOtOk}+Ns%%tfu#5-46HW zB5D!HyEoHQ6Bexy!JRr)vnP_M^%!@0M1cYx~k{VM5UTJN^Xqm=}9t*_!^fhEwVD+)b zaeC8@80ZHv^_v*u6d+g^iPkV$oebX62Fs=mcJ=J63!}PLA+hl1+?jR|X8jJdD-7+0 zZ9{D+b@?htKh!+z0VdME5{>L%{<;cU;+?Z(|Mni8Ic^0+^d3NQOiUqD7M zxA`!puyWV&*eO(F6%$F5fRR>py2)x9KumG0ne$LPWg|cJ22Ra-h*-_$W9=YXGYjJt ztOl1+%zWsA}K56ws=DW_WW*gOOY21 zVWlH2jz*n_;VD9`DP%L%7#-FQl?vBfj_m7&7Pei5;uzcEt~SA8j?zCr*^L0Uh03Ix z%Tp-qu%U(J8Z9&IcBz}(PM6r+uC`BV=~AlmHm_P)YIBgv*6ol9%N#3QS>^I-_VT+{33&_H5)Qd=m-BG39gucbGQ2!_p$S5rZaNsA`db-|=)!n+%ZJ1e-YI>=Y0s~7I)%&h)?&|VF>2rBu+HEChi2Th< zT!X_F4s-}is7zk3#G?dz3ED8kUFu;RO;Ns>C9Le~8Yb+vGGoz6lIN<~Z)F6H+OCsA zFb7(^VZYF9SFG}EH$l#2Z7yOtFA+-6xO9bt+U(y7e%ck~5tyGu945|S07yL+A)J9I_)K%6R z#(`fo+E38zTQ^qG*8bvnghOvpZOf_@X4i#Hc(5_72`^rsEho-d7RZ{9hPqAE_lAH<~byX7uh#PeuYBo3Hu|m#Z;WAd4YIc}! zp;=+?w2$QlH9^4Qs4bz{X;uzwe;64FOxjD{4#DuvPg=e+JwH`Fz2FOZP$4mTfwzTJ z8JSvHEKZHhqq|v~+FPPbZKoTywo6`fa+{AqM4PsINZGLwz1Y2%V9P9CKvJn0GQ;%{ zBJW)Lh0Q{=kk_NLG1ZgH0Gpe%N9t8+;6^ziAyZ`CnQ^V%2HM7N3}&ROPw|)p7BH!o z<)JqBNC&-OLCx;qu+?@(oIHu~0naW|z)OUbt z+Qx*li}vbiD}%hf%^MjsX0Zd`JZ_s^PWJGXz4o;6bkjhT1-028ADF1XM(G2-wraY=h z8#e|`_Xrkt^1J}`eCWx9`dTZvigok|&sIvcRHSFrvcDGg(4pJnc5fT=1UAA(Dx<}6 zKBL!(0iTl|^63#6h4p8sVEfY(R3o(W!(tS!)WVNj1m&o%r%4sp_iGE}N8;&tQ4$*1 zqh!v>(8j3vQ?!!T4iz|FZYm$9N1KMd+Vmv(#0LiO90|EV&GP}IY(i^8x?{$fZkwgp zCR=Huhc)VZso}|HMbfU~dW z?u8XFSt)p0@XZX}QJMC|1mjFDn`*=>@71Ejk7c%vPD2nj z6$`43eof?R6RNE+R|Y?G_N(R&IlGIMa_EPPdsX=VC;?whm3-AkPI%P@XAA!7vEEj# z=yJAs6Z}Xi9_~~1UtpTgyWVWxoAU7xA}M3d!#r(jc*ym^JQ59E`HeZVM&iKLhBX3JTgf0yzLotzIL zJ;g+k-|~I!`k6AtLFK2mlkyWr$8GpexTKfwaLZZZvPk}tUh02@)A!>{hs1f2v&4m= z^pwU<|4CrfCR9E;4kYxcewOzy3~I_M*L40k{s+_FnIKdtIZsjL0!J%f%lUr%4yKp) zh2?z1U4g{7l=2HoufGJ-%lE|PEcpn%RU9?X>81VUyW?^`b-AQ8XFLDnR{Hw)$-iOf z>AOF6R>7GY=ki{-p#mTlnNgJ-vKCz4gCM8le*o@>|Zo#0@IHY|(E-+i?gZ0IT&A;}zE?VyIY>G= zUyQ`T^zvTq#%D|ddEZeAAnD{ceOHSxX+L@IclPIoqL-9=;IPxL;r!bJG;}HH`STd{ zyHr*>f@iCW`u=gw{~R;82Izm`zvM6a>r!A+cAb#_9KFiqunOb%7 literal 0 HcmV?d00001 diff --git a/applog/CMakeLists.txt b/applog/CMakeLists.txt new file mode 100644 index 0000000..22c52db --- /dev/null +++ b/applog/CMakeLists.txt @@ -0,0 +1,16 @@ +project(applog) +add_compile_options(-std=c++14) +#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -O2") +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -O2") +aux_source_directory(${PROJECT_SOURCE_DIR} DIR_SRCS) +file(GLOB DIR_HEADS "${PROJECT_SOURCE_DIR}/*.h" "${PROJECT_SOURCE_DIR}/*.hpp") +set(DIR_SRCS ${DIR_SRCS} ${DIR_HEADS}) + +add_library(${PROJECT_NAME} STATIC ${DIR_SRCS}) + +target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR}/../packages/common.pkg/include + + ) + +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../bin) \ No newline at end of file diff --git a/applog/applog.cpp b/applog/applog.cpp new file mode 100644 index 0000000..1f625df --- /dev/null +++ b/applog/applog.cpp @@ -0,0 +1,121 @@ +#include "applog.h" +#include "spdlog/spdlog.h" +#include "spdlog/sinks/stdout_color_sinks.h" +#include "spdlog/sinks/basic_file_sink.h" +#include "spdlog/sinks/rotating_file_sink.h" +#include "stringex.hpp" +#include +#include + +inline std::string string_toupper(const std::string& str) +{ + std::string s = str; + transform(s.begin(), s.end(), s.begin(), toupper); + return s; +} + +void log_init(const std::string& name, bool benv) +{ + if(spdlog::get(name)) + return; + + const auto max_size = 1048576 * 5; + const auto max_files = 3; + + auto console_sink = std::make_shared(); + char *pathvar = getenv(("APP_" + string_toupper(name) + "_CONSOLE_LOG").c_str()); + console_sink->set_level(pathvar ? std::min(spdlog::level::from_str(pathvar), spdlog::level::off) : spdlog::level::off); + auto file_sink = std::make_shared("app.log", max_size, max_files); + pathvar = getenv(("APP_" + string_toupper(name) + "_FILE_LOG").c_str()); + file_sink->set_level(pathvar ? std::min(spdlog::level::from_str(pathvar), spdlog::level::off) : spdlog::level::off); + auto logger = std::shared_ptr(new spdlog::logger(name, {console_sink, file_sink})); + pathvar = getenv(("APP_" + string_toupper(name) + "_LOG").c_str()); + logger->set_level(pathvar ? std::min(spdlog::level::from_str(pathvar), spdlog::level::off) : spdlog::level::off); + spdlog::register_logger(logger); +} + +void log_info(const std::string& name, const std::string& msg) +{ + if(auto log = spdlog::get(name)) + { + log->info(msg); + log->flush(); + } +} + +void log_warn(const std::string& name, const std::string& msg) +{ + if (auto log = spdlog::get(name)) + { + log->warn(msg); + log->flush(); + } +} + +void log_trace(const std::string& name, const std::string& msg) +{ + if (auto log = spdlog::get(name)) + { + log->trace(msg); + log->flush(); + } +} + +void log_debug(const std::string& name, const std::string& msg) +{ + if (auto log = spdlog::get(name)) + { + log->debug(msg); + log->flush(); + } +} + +void log_error(const std::string& name, const std::string& msg) +{ + if (auto log = spdlog::get(name)) + { + log->error(msg); + log->flush(); + } +} + + +void log_critical(const std::string name, const std::string& msg) +{ + if (auto log = spdlog::get(name)) + { + log->critical(msg); + log->flush(); + } +} + +bool log_set_level(const std::string& name, int type ,int level) +{ + if (auto log = spdlog::get(name)) + { + spdlog::level::level_enum actLevel = (spdlog::level::level_enum)std::min(std::max((int)spdlog::level::trace, level), (int)spdlog::level::off); + if(type < log->sinks().size()) + log->sinks()[type]->set_level(actLevel); + else + log->set_level(actLevel); + + return true; + } + + return false; +} + +bool log_get_level(const std::string& name, int type ,int& level) +{ + if (auto log = spdlog::get(name)) + { + if(type < log->sinks().size()) + level = log->sinks()[type]->level(); + else + level = log->level(); + + return true; + } + + return false; +} \ No newline at end of file diff --git a/applog/applog.h b/applog/applog.h new file mode 100644 index 0000000..56c4526 --- /dev/null +++ b/applog/applog.h @@ -0,0 +1,20 @@ +#pragma once +#include +#define LOG_INIT() log_init(loggername, true) +#define LOG_INITX() log_init(loggername, false) +#define LOG_INFO(X) log_info(loggername, X) +#define LOG_WARN(X) log_warn(loggername, X) +#define LOG_TRACE(X) log_trace(loggername, X) +#define LOG_DEBUG(X) log_debug(loggername, X) +#define LOG_ERROR(X) log_error(loggername, X) +#define LOG_CRITICAL(X) log_critical(loggername, X) + +void log_init(const std::string& name, bool benv); +void log_info(const std::string& name, const std::string& msg); +void log_warn(const std::string& name, const std::string& msg); +void log_trace(const std::string& name, const std::string& msg); +void log_debug(const std::string& name, const std::string& msg); +void log_error(const std::string& name, const std::string& msg); +void log_critical(const std::string& name, const std::string& msg); +bool log_set_level(const std::string& name, int type ,int level); +bool log_get_level(const std::string& name, int type ,int& level); diff --git a/capimage/CImageMerge.cpp b/capimage/CImageMerge.cpp new file mode 100644 index 0000000..58560a7 --- /dev/null +++ b/capimage/CImageMerge.cpp @@ -0,0 +1,301 @@ +#include "CImageMerge.h" +#include +CImageMerge::CImageMerge() +{ +} +CImageMerge::~CImageMerge() +{ +} +cv::Mat CImageMerge::MergeImage(cv::Mat &srcMat, int dstwidth, int dstheight) +{ + cv::Mat retMat(dstheight, dstwidth, CV_8UC3); + + if (!srcMat.empty()) + { + std::vector ch_mats; + int blockcnt = 12; + int spitWidth = srcMat.cols / blockcnt; + + for (int i = 0; i < 4; i++) + { + for (int j = 0; j < 3; j++) + { + ch_mats.push_back(srcMat(cv::Rect(spitWidth * (i * 3 + j), 0, spitWidth, dstheight))); + } + cv::merge(ch_mats, retMat(cv::Rect(spitWidth * i, 0, spitWidth, dstheight))); + ch_mats.clear(); + } + return retMat; + } +} + +cv::Mat CImageMerge::MergeImage(bool iscolor, cv::Mat &srcMat, int dstwidth, int dstheight, unsigned int fgpaversion) +{ + int blockcnt = 12; + int spitWidth = srcMat.cols / blockcnt; + int abortwidth; // = spitWidth == 3888 ? 432 : (spitWidth == 2592 ? 216 : 144); + if (!iscolor) // 灰度 + { + abortwidth = spitWidth == 1296 ? 432 : (spitWidth == 648 ? 216 : 144); + } + else + { + abortwidth = spitWidth == 3888 ? 432 : (spitWidth == 1944 ? 216 : 144); + } + if (fgpaversion == 0x00090002) + { + int blockcnt = iscolor ? 18 : 6; + int spitWidth = srcMat.cols / blockcnt / 2; // 一面的灰度图像宽度 + int abortwidth = spitWidth == 1296 ? 432 : (spitWidth == 648 ? 216 : 144); + + cv::Mat dst(dstheight, dstwidth - 2 * abortwidth, CV_8UC(iscolor ? 3 : 1)); + if (!iscolor) + { + for (int i = 0; i < 2; i++) + { + for (int j = 0; j < 6; j++) + { + int index = i == 0 ? 5 : 11; + int bandindex = (i * 6 + j); + if (bandindex == 0 || bandindex == 11) + { + if (bandindex == 0) + srcMat(cv::Rect(bandindex * spitWidth, 0, spitWidth - abortwidth, srcMat.rows)).copyTo(dst(cv::Rect(spitWidth * (index - j), 0, spitWidth - abortwidth, srcMat.rows))); + else + srcMat(cv::Rect(bandindex * spitWidth + abortwidth, 0, spitWidth - abortwidth, srcMat.rows)).copyTo(dst(cv::Rect(spitWidth * (index - j) - abortwidth, 0, spitWidth - abortwidth, srcMat.rows))); + } + else + { + if (bandindex >= 6) + srcMat(cv::Rect(bandindex * spitWidth, 0, spitWidth, srcMat.rows)).copyTo(dst(cv::Rect(spitWidth * (index - j) - 2 * abortwidth, 0, spitWidth, srcMat.rows))); + else + srcMat(cv::Rect(bandindex * spitWidth, 0, spitWidth, srcMat.rows)).copyTo(dst(cv::Rect(spitWidth * (index - j), 0, spitWidth, srcMat.rows))); + } + } + } + srcMat.release(); + } + else + { + std::vector m_splits = { + cv::Mat(dstheight, dstwidth - 2 * abortwidth, CV_8UC1), + cv::Mat(dstheight, dstwidth - 2 * abortwidth, CV_8UC1), + cv::Mat(dstheight, dstwidth - 2 * abortwidth, CV_8UC1)}; + int item_index[3][4] = { + {11, 2, 35, 26}, // R + {17, 8, 29, 20}, // B + {14, 5, 32, 23} // G + }; + + for (size_t j = 0; j < 3; j++) + { + // Front + srcMat(cv::Rect((item_index[j][0] - 0) * spitWidth, 0, spitWidth, srcMat.rows)).copyTo(m_splits[j](cv::Rect(spitWidth * 0, 0, spitWidth, srcMat.rows))); + srcMat(cv::Rect((item_index[j][0] - 1) * spitWidth, 0, spitWidth, srcMat.rows)).copyTo(m_splits[j](cv::Rect(spitWidth * 1, 0, spitWidth, srcMat.rows))); + srcMat(cv::Rect((item_index[j][0] - 2) * spitWidth, 0, spitWidth, srcMat.rows)).copyTo(m_splits[j](cv::Rect(spitWidth * 2, 0, spitWidth, srcMat.rows))); + srcMat(cv::Rect((item_index[j][1] - 0) * spitWidth, 0, spitWidth, srcMat.rows)).copyTo(m_splits[j](cv::Rect(spitWidth * 3, 0, spitWidth, srcMat.rows))); + srcMat(cv::Rect((item_index[j][1] - 1) * spitWidth, 0, spitWidth, srcMat.rows)).copyTo(m_splits[j](cv::Rect(spitWidth * 4, 0, spitWidth, srcMat.rows))); + srcMat(cv::Rect((item_index[j][1] - 2) * spitWidth, 0, spitWidth - abortwidth, srcMat.rows)).copyTo(m_splits[j](cv::Rect(spitWidth * 5, 0, spitWidth - abortwidth, srcMat.rows))); + // Back + srcMat(cv::Rect((item_index[j][2] - 0) * spitWidth + abortwidth, 0, spitWidth - abortwidth, srcMat.rows)).copyTo(m_splits[j](cv::Rect(spitWidth * 6 - abortwidth, 0, spitWidth - abortwidth, srcMat.rows))); + srcMat(cv::Rect((item_index[j][2] - 1) * spitWidth, 0, spitWidth, srcMat.rows)).copyTo(m_splits[j](cv::Rect(spitWidth * 7 - 2 * abortwidth, 0, spitWidth, srcMat.rows))); + srcMat(cv::Rect((item_index[j][2] - 2) * spitWidth, 0, spitWidth, srcMat.rows)).copyTo(m_splits[j](cv::Rect(spitWidth * 8 - 2 * abortwidth, 0, spitWidth, srcMat.rows))); + srcMat(cv::Rect((item_index[j][3] - 0) * spitWidth, 0, spitWidth, srcMat.rows)).copyTo(m_splits[j](cv::Rect(spitWidth * 9 - 2 * abortwidth, 0, spitWidth, srcMat.rows))); + srcMat(cv::Rect((item_index[j][3] - 1) * spitWidth, 0, spitWidth, srcMat.rows)).copyTo(m_splits[j](cv::Rect(spitWidth * 10 - 2 * abortwidth, 0, spitWidth, srcMat.rows))); + srcMat(cv::Rect((item_index[j][3] - 2) * spitWidth, 0, spitWidth, srcMat.rows)).copyTo(m_splits[j](cv::Rect(spitWidth * 11 - 2 * abortwidth, 0, spitWidth, srcMat.rows))); + } + cv::merge(m_splits, dst); + m_splits.clear(); + } + srcMat.release(); + // static int index=0; + // cv::imwrite(std::to_string(++index)+".bmp",dst); + return dst; + } + else if (fgpaversion == 0x00090001) + { + int blockcnt = 12; + int spitWidth = srcMat.cols / blockcnt; + int abortwidth; // = spitWidth == 3888 ? 432 : (spitWidth == 2592 ? 216 : 144); + if (!iscolor) // 灰度 + { + abortwidth = spitWidth == 1296 ? 432 : (spitWidth == 648 ? 216 : 144); + } + else + { + abortwidth = spitWidth == 3888 ? 432 : (spitWidth == 1944 ? 216 : 144); + } + + cv::Mat dst(dstheight, dstwidth - abortwidth * 2, CV_8UC(iscolor ? 3 : 1)); + if (!iscolor) + { + for (int i = 0; i < 2; i++) + { + srcMat(cv::Rect((dstwidth / 2 + abortwidth) * i, 0, dstwidth / 2 - abortwidth, dstheight)).copyTo(dst(cv::Rect(dst.cols / 2 * i, 0, dst.cols / 2, dstheight))); + } + srcMat.release(); + } + else + { + std::vector m_splits; + std::vector m_index = {0, 3, 8, 11, 2, 5, 6, 9, 1, 4, 7, 10}; + for (int i = 0; i < 3; i++) + { + int startindex = i == 0 ? 0 : (i == 1 ? 4 : 8); + cv::Mat t_mat(dstheight, dstwidth - abortwidth * 2, CV_8UC1); + srcMat(cv::Rect(spitWidth * m_index[startindex + 0], 0, spitWidth, dstheight)).copyTo(t_mat(cv::Rect(0, 0, spitWidth, dstheight))); + srcMat(cv::Rect(spitWidth * m_index[startindex + 1], 0, spitWidth - abortwidth, dstheight)).copyTo(t_mat(cv::Rect(spitWidth, 0, spitWidth - abortwidth, dstheight))); + srcMat(cv::Rect(spitWidth * m_index[startindex + 2] + abortwidth, 0, spitWidth - abortwidth, dstheight)).copyTo(t_mat(cv::Rect(spitWidth * 2 - abortwidth, 0, spitWidth - abortwidth, dstheight))); + srcMat(cv::Rect(spitWidth * m_index[startindex + 3], 0, spitWidth, dstheight)).copyTo(t_mat(cv::Rect(spitWidth * 3 - abortwidth * 2, 0, spitWidth, dstheight))); + m_splits.push_back(t_mat); + } + cv::merge(m_splits, dst); + m_splits.clear(); + } + srcMat.release(); + return dst; + } + else if (fgpaversion == 0x0009000a) + { + auto switchblock = [](std::vector> v, cv::Mat &src, cv::Mat &dst, int block_width, int block_height, int abortwidth) + { + int copyindex = 0; + for (int i = 0; i < v.size(); i++) + { + if (v[i].second == 5 || v[i].second == 6) + { + src(cv::Rect(v[i].second == 6 ? block_width * v[i].first + abortwidth : block_width * v[i].first, 0, block_width - abortwidth, block_height)).copyTo(dst(cv::Rect(copyindex, 0, block_width - abortwidth, block_height))); + copyindex += block_width - abortwidth; + } + else + { + src(cv::Rect(block_width * v[i].first, 0, block_width, block_height)).copyTo(dst(cv::Rect(copyindex, 0, block_width, block_height))); + copyindex += block_width; + } + } + }; + std::vector> v{{3, 0}, {5, 1}, {4, 2}, {1, 3}, {0, 4}, {2, 5}, {10, 6}, {9, 7}, {11, 8}, {6, 9}, {8, 10}, {7, 11}}; + if (!iscolor) + { + int abortwidth = srcMat.cols / 12 == 1296 ? 432 : (srcMat.cols / 12 == 648 ? 216 : 144); + cv::Mat dst(srcMat.rows, srcMat.cols - abortwidth * 2, CV_8UC1); + switchblock(v, srcMat, dst, srcMat.cols / 12, srcMat.rows, abortwidth); + return dst; + } + else + { + cv::Mat retMat(srcMat.rows, srcMat.cols / 3, CV_8UC3); + int spitWidth = srcMat.cols / 12; + for (int i = 0; i < 4; i++) + { + // 1 2 0 + std::vector ch_mats; + if (i < 2) + { + ch_mats.push_back(srcMat(cv::Rect(spitWidth * (i * 3 + 0), 0, spitWidth, srcMat.rows))); + ch_mats.push_back(srcMat(cv::Rect(spitWidth * (i * 3 + 2), 0, spitWidth, srcMat.rows))); + ch_mats.push_back(srcMat(cv::Rect(spitWidth * (i * 3 + 1), 0, spitWidth, srcMat.rows))); + } + else + { + ch_mats.push_back(srcMat(cv::Rect(spitWidth * (i * 3 + 2), 0, spitWidth, srcMat.rows))); + ch_mats.push_back(srcMat(cv::Rect(spitWidth * (i * 3 + 0), 0, spitWidth, srcMat.rows))); + ch_mats.push_back(srcMat(cv::Rect(spitWidth * (i * 3 + 1), 0, spitWidth, srcMat.rows))); + } + cv::merge(ch_mats, retMat(cv::Rect(spitWidth * i, 0, spitWidth, srcMat.rows))); + ch_mats.clear(); + } + int abortwidth = retMat.cols / 12 == 1296 ? 432 : (retMat.cols / 12 == 648 ? 216 : 144); + cv::Mat dst(retMat.rows, retMat.cols - abortwidth * 2, CV_8UC3); + switchblock(v, retMat, dst, retMat.cols / 12, retMat.rows, abortwidth); + printf(" dst.cols = %d dst.rows = %d dst.channels = %d \n", dst.cols, dst.rows, dst.channels()); + return dst; + } + } + else if (fgpaversion == 0x0009000b) + { + int copy_size = 0; + int ratio = iscolor ? 3 : 1; + int spitWidth = srcMat.cols / 12; + int abortwidth = spitWidth == 1296 ? 432 : (spitWidth == 648 ? 216 : 144); + if (iscolor) + abortwidth = spitWidth == 3888 ? 432 : (spitWidth == 1944 ? 216 : 144); + spitWidth /= ratio; + cv::Mat dst(srcMat.rows, srcMat.cols / (iscolor ? 3 : 1) - abortwidth * 2, CV_8UC(iscolor ? 3 : 1)); + std::vector> v = {{spitWidth * (3 * ratio + 1), spitWidth}, {spitWidth * (3 * ratio), spitWidth}, {spitWidth * (3 * ratio + 2), spitWidth}, {spitWidth * 0, spitWidth}, {spitWidth * 2, spitWidth}, {spitWidth * 1, spitWidth - abortwidth}, {spitWidth * (9 * ratio + 1) + abortwidth, spitWidth - abortwidth}, {spitWidth * (9 * ratio), spitWidth}, {spitWidth * (9 * ratio + 2), spitWidth}, {spitWidth * (6 * ratio), spitWidth}, {spitWidth * (6 * ratio + 2), spitWidth}, {spitWidth * (6 * ratio + 1), spitWidth}}; + if (!iscolor) + { + for (int i = 0; i < v.size(); i++) + { + srcMat(cv::Rect(v[i].first, 0, v[i].second, srcMat.rows)).copyTo(dst(cv::Rect(copy_size, 0, v[i].second, srcMat.rows))); + copy_size += v[i].second; + } + } + else + { + std::vector m_splits; + std::vector m_index_f = {0, 2, 1}; + std::vector m_index_b = {2, 0, 1}; + for (int j = 0; j < 3; j++) + { + cv::Mat tmp_dst(srcMat.rows, srcMat.cols / (iscolor ? 3 : 1) - abortwidth * 2, CV_8UC1); + for (int i = 0; i < v.size(); i++) + { + if (i > 5) + srcMat(cv::Rect(v[i].first + m_index_b[j] * 3 * spitWidth, 0, v[i].second, srcMat.rows)).copyTo(tmp_dst(cv::Rect(copy_size, 0, v[i].second, srcMat.rows))); + else + srcMat(cv::Rect(v[i].first + m_index_f[j] * 3 * spitWidth, 0, v[i].second, srcMat.rows)).copyTo(tmp_dst(cv::Rect(copy_size, 0, v[i].second, srcMat.rows))); + copy_size += v[i].second; + } + copy_size = 0; + m_splits.push_back(tmp_dst); + } + cv::merge(m_splits, dst); + m_splits.clear(); + } + srcMat.release(); + return dst; + } + else if (fgpaversion == 0x0009000c) + { + // cv::imwrite("src.bmp",srcMat); + cv::Mat dst(dstheight, dstwidth - abortwidth * 2, CV_8UC(iscolor ? 3 : 1)); + int copy_size = 0; + int ratio = iscolor ? 3 : 1; + spitWidth /= ratio; + std::vector> v = {{spitWidth * (ratio * 3 + 2), spitWidth}, {spitWidth * (ratio * 3 + 1), spitWidth}, {spitWidth * (ratio * 3), spitWidth}, {spitWidth * 2, spitWidth}, {spitWidth, spitWidth}, {0, spitWidth - abortwidth}, {spitWidth * (ratio * 9 + 2) + abortwidth, spitWidth - abortwidth}, {spitWidth * (ratio * 9 + 1), spitWidth}, {spitWidth * (ratio * 9), spitWidth}, {spitWidth * (ratio * 6 + 2), spitWidth}, {spitWidth * (ratio * 6 + 1), spitWidth}, {spitWidth * (ratio * 6), spitWidth}}; + if (!iscolor) + { + for (int i = 0; i < v.size(); i++) + { + srcMat(cv::Rect(v[i].first, 0, v[i].second, srcMat.rows)).copyTo(dst(cv::Rect(copy_size, 0, v[i].second, srcMat.rows))); + copy_size += v[i].second; + } + } + else + { + std::vector m_splits; + std::vector m_index_f = {0, 2, 1}; + std::vector m_index_b = {2, 0, 1}; + for (int j = 0; j < 3; j++) + { + cv::Mat tmp_dst(dstheight, dstwidth - abortwidth * 2, CV_8UC1); + for (int i = 0; i < v.size(); i++) + { + if (i > 5) + srcMat(cv::Rect(v[i].first + m_index_b[j] * 3 * spitWidth, 0, v[i].second, srcMat.rows)).copyTo(tmp_dst(cv::Rect(copy_size, 0, v[i].second, srcMat.rows))); + else + srcMat(cv::Rect(v[i].first + m_index_f[j] * 3 * spitWidth, 0, v[i].second, srcMat.rows)).copyTo(tmp_dst(cv::Rect(copy_size, 0, v[i].second, srcMat.rows))); + copy_size += v[i].second; + } + copy_size = 0; + m_splits.push_back(tmp_dst); + } + cv::merge(m_splits, dst); + m_splits.clear(); + } + srcMat.release(); + return dst; + } + return srcMat; +} diff --git a/capimage/CImageMerge.h b/capimage/CImageMerge.h new file mode 100644 index 0000000..0fa52c7 --- /dev/null +++ b/capimage/CImageMerge.h @@ -0,0 +1,15 @@ +#pragma once +#include + +class CImageMerge +{ +private: + /* data */ +public: + CImageMerge(/* args */); + ~CImageMerge(); + +public: + cv::Mat MergeImage(cv::Mat &srcMat, int dstwidth, int dstheight); + cv::Mat MergeImage(bool iscolor, cv::Mat &srcMat, int dstwidth, int dstheight, unsigned int fgpaversion = 0x00090001); +}; diff --git a/capimage/CMakeLists.txt b/capimage/CMakeLists.txt new file mode 100644 index 0000000..ffc9213 --- /dev/null +++ b/capimage/CMakeLists.txt @@ -0,0 +1,20 @@ +project(capimage) +add_compile_options(-std=c++14) +#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -O2") +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -O2") + +aux_source_directory(${PROJECT_SOURCE_DIR} DIR_SRCS) +aux_source_directory(${PROJECT_SOURCE_DIR}/imageprocess DIR_IMGPROC) +file(GLOB DIR_HEADS "${PROJECT_SOURCE_DIR}/*.h" "${PROJECT_SOURCE_DIR}/*.hpp") +set(DIR_SRCS ${DIR_SRCS} ${DIR_HEADS} ${DIR_IMGPROC}) + +add_library(${PROJECT_NAME} STATIC ${DIR_SRCS} ${DIR_IMGPROC}) + +target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR}/../packages/common.pkg/include + ${PROJECT_SOURCE_DIR}/../regs + ${PROJECT_SOURCE_DIR}/../deviceio + ${PROJECT_SOURCE_DIR}/../applog + ) + +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../bin) \ No newline at end of file diff --git a/capimage/CameraParam.h b/capimage/CameraParam.h new file mode 100644 index 0000000..036e8b5 --- /dev/null +++ b/capimage/CameraParam.h @@ -0,0 +1,67 @@ +#pragma once +#include + +#define LIGHT_DIFF(maxthre, x) ((maxthre)-x) +#define BLACK_DIFF(x) (8 - x) +#define FMT_STEP(x) \ + do \ + { \ + if (x < 1 && x > 0) \ + { \ + x = 1; \ + } \ + if (step < 0 && step > -1) \ + { \ + x = -1; \ + } \ + } while (0) + +struct FPGAConfigParam +{ + unsigned int ExposureF[3]; // RGB + unsigned int GainF[6]; // 123456 + unsigned int OffsetF[6]; // 123456 + unsigned int ExposureB[3]; // RGB + unsigned int GainB[6]; // 123456 + unsigned int OffsetB[6]; // 123456 + unsigned int DpiMode; + unsigned int ColorMode; + unsigned int MaxBright; + unsigned int MaxExp; + unsigned int Sp; + unsigned int HRatio; + unsigned int VRatio; + std::string LutPath; + std::string TextLutPath; + std::string Flat_BwPath; + std::string Flat_WhitePath; +}; + +struct FPGAConfigParam_8478 +{ + unsigned int ExposureF[3]; // RGB + unsigned int GainF_R[9]; // 123456 + unsigned int OffsetF_R[9]; // 123456 + unsigned int GainF_G[9]; // 123456 + unsigned int OffsetF_G[9]; // 123456 + unsigned int GainF_B[9]; // 123456 + unsigned int OffsetF_B[9]; // 123456 + unsigned int ExposureB[3]; // RGB + unsigned int GainB_R[9]; // 123456 + unsigned int OffsetB_R[9]; // 123456 + unsigned int GainB_G[9]; // 123456 + unsigned int OffsetB_G[9]; // 123456 + unsigned int GainB_B[9]; // 123456 + unsigned int OffsetB_B[9]; // 123456 + unsigned int DpiMode; + unsigned int ColorMode; + unsigned int MaxBright; + unsigned int MaxExp; + unsigned int Sp; + unsigned int HRatio; + unsigned int VRatio; + std::string LutPath; + std::string TextLutPath; + std::string Flat_BwPath; + std::string Flat_WhitePath; +}; \ No newline at end of file diff --git a/capimage/Capturer.cpp b/capimage/Capturer.cpp new file mode 100644 index 0000000..2d7f7e5 --- /dev/null +++ b/capimage/Capturer.cpp @@ -0,0 +1,845 @@ +#include "Capturer.h" +#include "DevUtil.h" +#include +#include +#include +#include "Gpio.h" +#include "FpgaComm.h" +#include "gvideoisp1.h" +#include "config.h" +#include +#include +#include "applog.h" +#include "stringex.hpp" +#include +#include "filetools.h" +#include "CameraParam.h" +#include "correct_ultis.h" + +using namespace std; +#define LOG_PATH "/usr/local/correct.log" +FileTools ft(LOG_PATH); + +static std::string loggername = "Capturer"; + +bool isAutoCorrect = true; +double Radio = 1; +cv::Mat mBuffMat; +cv::Mat out; + +Capturer::Capturer() + : vdd_cis_3voff_pin(new GpioOut(CIS_3v3_Off)), + vdd_vis_5ven_pin(new GpioOut(CIS_5v_En)), + reset_pin(new GpioOut(Fpga_Reset)), + image_in_transfer_pin(new Gpio(Image_In_Transfer)), + initDone_pin(new Gpio(Fpga_InitDone)), + fpgaLoad(new GpioOut(Fpga_Load)), + bcorrecting(false) +{ + LOG_INIT(); + fpgaComm.reset(new FpgaComm()); + fpga_reset(); + fpgaComm->resetADC(); + fpgaComm->setDelayTime(0X3e8); + + video.reset(new VIDEO_CLASS()); +} + +Capturer::~Capturer() +{ +} + +void Capturer::Fpga_regsAccess_reset(bool enable) +{ +} +void Capturer::open() +{ + cisconfigs = getcisparams(); + int height = 6000; + set_sp(0x0208); + fpgaComm->setColorMode(1); + // int height = 2000; + // set_sp(0x0bf0); + // fpgaComm->setColorMode(0); + fpgaComm->setDpi(1); + fpgaComm->setSample(256); + fpgaComm->enableLed(true); + // 设置曝光值等 + int exp[2][3]; + int gains[2][6]; + int offsets[2][6]; + for (int i = 0; i < 3; i++) + set_expo(i, 0x300); // 0x1b0); + + for (int i = 0; i < 2; i++) + { + set_gain(i, 300); + set_offset(i, 150); + } + + fpgaComm->setFrameHeight(12); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + fpgaComm->capture(); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + video.reset(new VIDEO_CLASS()); + + video->open(1632, height); + fpgaComm->setFrameHeight(12); + for (int i = 0; i < 1; i++) + { + fpgaComm->capture(); + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + } + fpgaComm->setFrameHeight(height); +} +static int val = 0; +static double exp_ratio = 0.1; +void Capturer::open(HGScanConfig config, FPGAConfigParam fpgaparam) +{ + if (val > 4000) + val = 0; + + if (exp_ratio > 2.0) + exp_ratio = 0.1; + cisconfigs = getcisparams(); + auto hgsize = papersMap[(PaperSize)config.g200params.paper]; + int height = hgsize.height; + fpgaComm->setColorMode(config.g200params.color ? 1 : 0); + auto info = Get_static_jsonconfig().getscannerinfo(); + // set_sp(config.g200params.color ? cisconfigs.color.sp : cisconfigs.gray.sp); //0x03fa : 0x0bf0 + int clrsp, graysp; + // if (scannerSp.count((SpeedMode)info.speedmode) <= 0) + // { + // #ifdef G200 + // clrsp = scannerSp[SpeedMode::PPM100].colorSp; + // graysp = scannerSp[SpeedMode::PPM100].colorSp; + // #else + // clrsp = scannerSp[SpeedMode::PPM70].colorSp; + // graysp = scannerSp[SpeedMode::PPM70].colorSp; + // #endif + // } + // else + // { + // clrsp = scannerSp[(SpeedMode)info.speedmode].colorSp; + // graysp = scannerSp[(SpeedMode)info.speedmode].colorSp; + // } + clrsp = info.color_sp; + graysp = info.gray_sp; + set_sp(config.g200params.color ? clrsp : graysp); + printf("\n capture color sp =%d, gray sp =%d", clrsp, graysp); + // set_sp(config.g200params.color ? 0x335 : 0x99f); //G100 0x438 0xca8 60 ppm 0x335 : 0x99f 100ppm + // G200 SP极限值205 0x27c 0x775 140ppm + fpgaComm->setDpi(config.g200params.dpi); // 0 300dpi 1 200dpi + fpgaComm->setSample(256); + fpgaComm->enableLed(true); + // 设置曝光值等 + + configFPGAParam(false, config.g200params.color); + + // fpgaComm->setFrameHeight(12); + // std::this_thread::sleep_for(std::chrono::milliseconds(1)); + // fpgaComm->capture(); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + + video->open(1632, config.g200params.color ? height : height / 3); + fpgaComm->setFrameHeight(12); + for (int i = 0; i < 1; i++) + { + fpgaComm->capture(); + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + } + fpgaComm->setFrameHeight(config.g200params.color ? height : height / 3); + // fpgaComm->update(); +} + +void Capturer::close() +{ + if (video) + { + video->close(); + } +} +void Capturer::start() +{ + if (video) + video->start(); +} + +void Capturer::stop() +{ + if (video) + video->stop(); +} + +void Capturer::reset() +{ + fpga_reset(); + fpgaComm->resetADC(); + fpgaComm->setDelayTime(0X3e8); + fpgaComm->setRegs(0x00, fpgaComm->getRegs(0x00)); + fpgaComm->setRegs(0x01, fpgaComm->getRegs(0x01)); +} + +void Capturer::set_size(int width, int height) +{ + if (video) + video->set_size(width, height); +} + +void Capturer::snap() +{ + fpgaComm->capture(); +} + +std::shared_ptr Capturer::regs() +{ + return fpgaComm; +} + +void Capturer::fpga_reset() +{ + reset_pin->setValue(Gpio::Low); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + reset_pin->setValue(Gpio::High); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); +} + +void Capturer::fpga_reload() +{ + // fpga 代码重载 + fpgaLoad->setValue(Gpio::Low); + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + fpgaLoad->setValue(Gpio::High); + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + fpgaComm->resetADC(); +} + +void Capturer::set_expo(int ix, int val) +{ + switch (ix) + { + case 0: + fpgaComm->setAExposureB(val); + break; + case 1: + fpgaComm->setAExposureG(val); //!< ok + break; + case 2: + fpgaComm->setAExposureR(val); //!< ok + break; + case 3: + fpgaComm->setBExposureB(val); + break; + case 4: + fpgaComm->setBExposureG(val); + break; + case 5: + fpgaComm->setBExposureR(val); + break; + default: + break; + } + std::this_thread::sleep_for(std::chrono::milliseconds(1)); +} + +void Capturer::set_gain(int ix, int val) +{ + for (int i = 0; i < 6; i++) + { + if (ix) + fpgaComm->setAGain(i, val); + else + fpgaComm->setBGain(i, val); + } +} + +void Capturer::set_offset(int ix, int val) +{ + for (int i = 0; i < 6; i++) + { + if (ix) + fpgaComm->setAOffset(i, val); + else + fpgaComm->setBOffset(i, val); + + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } +} + +void Capturer::configFPGAParam(bool iscorrect, int mode) +{ + int exposures[2][3]; + int gains[2][6]; + int offsets[2][6]; + if (iscorrect) + { + memcpy(&exposures[0][0], mode == IMAGE_COLOR ? cisconfigs.colorCorrect.expF : cisconfigs.grayCorrect.expF, sizeof(int) * 3); + memcpy(&exposures[1][0], mode == IMAGE_COLOR ? cisconfigs.colorCorrect.expB : cisconfigs.grayCorrect.expB, sizeof(int) * 3); + memcpy(&gains[0][0], mode == IMAGE_COLOR ? cisconfigs.colorCorrect.gainF : cisconfigs.grayCorrect.gainF, sizeof(int) * 6); + memcpy(&gains[1][0], mode == IMAGE_COLOR ? cisconfigs.colorCorrect.gainB : cisconfigs.grayCorrect.gainB, sizeof(int) * 6); + memcpy(&offsets[0][0], mode == IMAGE_COLOR ? cisconfigs.colorCorrect.offsetsF : cisconfigs.grayCorrect.offsetsF, sizeof(int) * 6); + memcpy(&offsets[1][0], mode == IMAGE_COLOR ? cisconfigs.colorCorrect.offsetsB : cisconfigs.grayCorrect.offsetsB, sizeof(int) * 6); + } + else + { + memcpy(&exposures[0][0], mode == IMAGE_COLOR ? cisconfigs.color.expF : cisconfigs.gray.expF, sizeof(int) * 3); + memcpy(&exposures[1][0], mode == IMAGE_COLOR ? cisconfigs.color.expB : cisconfigs.gray.expB, sizeof(int) * 3); + memcpy(&gains[0][0], mode == IMAGE_COLOR ? cisconfigs.color.gainF : cisconfigs.gray.gainF, sizeof(int) * 6); + memcpy(&gains[1][0], mode == IMAGE_COLOR ? cisconfigs.color.gainB : cisconfigs.gray.gainB, sizeof(int) * 6); + memcpy(&offsets[0][0], mode == IMAGE_COLOR ? cisconfigs.color.offsetsF : cisconfigs.gray.offsetsF, sizeof(int) * 6); + memcpy(&offsets[1][0], mode == IMAGE_COLOR ? cisconfigs.color.offsetsB : cisconfigs.gray.offsetsB, sizeof(int) * 6); + } + + // static int val = 0; + + // int step = 100; + + // for(int i = 0;i<2;i++) + // { + // for(int j =0 ;j<3;j++) + // { + + // exposures[i][j] =i==0? cisconfigs.gray.expF[j]*exp_ratio:cisconfigs.gray.expB[j]*exp_ratio; + // printf("exp_ratio = %0.2f \r\n",exp_ratio); + // } + // } + // val+=step; + // exp_ratio += 0.1; + + // for (int i = 0; i < 2; i++) + // { + // for (int j = 0; j < 6; j++) + // { + + // printf("gains[%d][%d] = %d \r\n", i, j, gains[i][j]); + // printf("offsets[%d][%d] = %d \r\n", i, j, offsets[i][j]); + // if (j < 3) + // { + // printf("exposures[%d][%d] = %d \r\n", i, j, exposures[i][j]); + // } + // } + // } + + setFGPAParmas(exposures, gains, offsets); +} +void Capturer::setFGPAParmas(int exposures[2][3], int gains[2][6], int offsets[2][6]) +{ + // set exposuretime + fpgaComm->setAExposureB(exposures[0][0]); + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + fpgaComm->setAExposureG(exposures[0][1]); + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + fpgaComm->setAExposureR(exposures[0][2]); + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + fpgaComm->setBExposureB(exposures[1][0]); + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + fpgaComm->setBExposureG(exposures[1][1]); + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + fpgaComm->setBExposureR(exposures[1][2]); + // set Gain and offset + for (int i = 0; i < 6; i++) + { + // LOGD("setAGain %d =:%d", i , gains[0][i]); + fpgaComm->setAGain(i, gains[0][i]); // A面增加 + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + fpgaComm->setBGain(i, gains[1][i]); // B面增益 + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + fpgaComm->setAOffset(i, offsets[0][i]); // A面偏置 + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + fpgaComm->setBOffset(i, offsets[1][i]); // B面偏置 + } +} + +void *Capturer::readFrame(int timeout) +{ + auto ret = video->read_frame(timeout); + unsigned int val; + // fpgaComm->update(); + return ret; +} + +bool Capturer::is_runing() +{ + return true; +} + +int Capturer::color() +{ + return fpgaComm->getColorMode() ? 16 : 0; +} + +int Capturer::height() +{ + return fpgaComm->getFrameHeight(); +} + +int Capturer::width() +{ + return 1632; +} + +void Capturer::set_sp(int sp) +{ + fpgaComm->setSp(sp); +} + +void Capturer::init_autocorrect(int colormode) +{ + std::thread t_correctthread = std::thread(&Capturer::autocorrect, this, colormode); + t_correctthread.detach(); +} + +void Capturer::autocorrect(int colormode) +{ + bcorrecting = true; + cisconfigs = getcisparams(); + scannerinfo = getscannerinfo(); + ft.clear(); + ft.append_log("start correct"); + if (m_captureCallback) + { + m_captureCallback(colormode, colormode ? "------开始彩色校正------\r\n" : "------开始灰度校正------\r\n"); + } + creatcorrectconfig(colormode ? IMAGE_COLOR : IMAGE_GRAY); + creatLUTData(colormode ? IMAGE_COLOR : IMAGE_GRAY, CISVendor::HUALIN_CIS_V0); + if (colormode) + { + memcpy(cisconfigs.color.offsetsF, cisconfigs.colorCorrect.offsetsF, sizeof(int) * 6); + memcpy(cisconfigs.color.offsetsB, cisconfigs.colorCorrect.offsetsB, sizeof(int) * 6); + memcpy(cisconfigs.color.expF, cisconfigs.colorCorrect.expF, sizeof(int) * 3); + memcpy(cisconfigs.color.expB, cisconfigs.colorCorrect.expB, sizeof(int) * 3); + } + else + { + memcpy(cisconfigs.gray.offsetsF, cisconfigs.grayCorrect.offsetsF, sizeof(int) * 6); + memcpy(cisconfigs.gray.offsetsB, cisconfigs.grayCorrect.offsetsB, sizeof(int) * 6); + memcpy(cisconfigs.gray.expF, cisconfigs.grayCorrect.expF, sizeof(int) * 3); + memcpy(cisconfigs.gray.expB, cisconfigs.grayCorrect.expB, sizeof(int) * 3); + } + savecisparams(cisconfigs); + initLut(); + if (m_captureCallback) + m_captureCallback(4, colormode ? "------彩色校正完成------\r\n" : "------灰度校正完成------\r\n"); + reset(); + bcorrecting = false; + printf("init_autocorrect exit \n"); +} + +void Capturer::creatcorrectconfig(int mode) +{ + std::string msg = mode == IMAGE_COLOR ? "彩色" : "灰度"; + // LOG_TRACE("creatcorrectconfig \r\n"); + ft.append_log("开始" + msg + "暗场校正"); + if (m_captureCallback) + m_captureCallback(mode, "开始" + msg + "暗场校正\r\n"); + openDevice(mode); + bool isDone = false; + int i = 1; + initStep(); + while (!isDone) // 先暗场 + { + configFPGAParam(true, mode); + string log = "==============================第" + to_string(i) + "次=============================== \r\n"; + ft.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + fpgaComm->enableLed(false); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + // fpgaComm->update(); + fpgaComm->capture(); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + isDone = saveLutImg(mode, mode == IMAGE_COLOR ? 0 : 2); // 0 color_black 1 color_white 2 gray_balck 3 gray_white + i++; + } + i = 1; + isDone = false; + initStep(); + ft.append_log("开始" + msg + "明场校正"); + if (m_captureCallback) + m_captureCallback(mode, "开始" + msg + "明场校正 \r\n"); + while (!isDone) // 后明场 + { + configFPGAParam(true, mode); + string log = "==============================第" + to_string(i) + "次=============================== \r\n"; + ft.append_log(log); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + fpgaComm->enableLed(true); + // fpgaComm->update(); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + fpgaComm->capture(); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + isDone = saveLutImg(mode, mode == IMAGE_COLOR ? 1 : 3); + // isDone = true; + i++; + } + LOG_TRACE(string_format("creatcorrectconfig %s \r\n", (mode == IMAGE_COLOR ? " Color" : " Gray"))); + video->close(); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); +} + +void Capturer::openDevice(int mode) +{ + this->reset(); + // #ifdef G00 + int width = 1632; + int height = 6000; + // #else + // int width = 1728; + // int height = 6000; + // #endif + video->open(width, mode == IMAGE_COLOR ? height : height / 3); + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + fpgaComm->capture(); + video->read_frame(200); // 丢弃第一张无效图像 + LOG_TRACE(string_format("cisconfigs.grayCorrect.sp = %d \r\n", cisconfigs.grayCorrect.sp)); + // fpgaComm->setSp(mode == IMAGE_COLOR ? cisconfigs.colorCorrect.sp : cisconfigs.grayCorrect.sp); + auto info = getscannerinfo(); + fpgaComm->setSp(mode == IMAGE_COLOR ? info.color_sp : info.gray_sp); // 0x438 : 0xca8 + fpgaComm->setSample(256); + fpgaComm->setDpi(1); + fpgaComm->setColorMode(mode == IMAGE_COLOR ? 1 : 0); + fpgaComm->setFrameHeight(mode == IMAGE_COLOR ? height : height / 3); + fpgaComm->enableLed(true); +} + +static int savelutindex = 0; +bool Capturer::saveLutImg(int mode, int index) +{ + int offset_indexs[12] = {0, 1, 2, 5, 4, 3, 3, 4, 5, 2, 1, 0}; + int count = 1; + int height = 6000; + int width = 1632; + bool isNeedSave = true; + string log; + for (int i = 0; i < 1; i++) + { + void *data = video->read_frame(1500); + if (data == NULL) + { + log = "图像采集失败!\r\n"; + ft.append_log(log); + isNeedSave = false; + if (m_captureCallback) + m_captureCallback(mode, log); + } + if (data && isNeedSave) + { + if (mode == IMAGE_COLOR) + { + cv::Mat mergeMat = GetMergeMat(data, this->width(), this->height(), this->color()); + cv::cvtColor(mergeMat, mergeMat, CV_RGB2BGR); + if (i == 0) + { + double values[2][3]; + cv::Scalar a = cv::mean(mergeMat(cv::Rect(0, 0, mergeMat.cols / 2, mergeMat.rows))); + cv::Scalar b = cv::mean(mergeMat(cv::Rect(mergeMat.cols / 2, 0, mergeMat.cols / 2, mergeMat.rows))); + for (int j = 0; j < 3; j++) + { + values[0][j] = a.val[2 - j]; + values[1][j] = b.val[2 - j]; + } + double offValues[12]; + for (int n = 0; n < 2; n++) + { + cv::Mat img = mergeMat(cv::Rect(mergeMat.cols * n / 2, 0, mergeMat.cols / 2, mergeMat.rows)); + int offset_total = 0; + for (int s = 0; s < 6; s++) // + { + int k = n * 6 + s; + int offset_wdth; + if ((s == 0 && k == 0) || (s == 5 && k == 11)) + offset_wdth = 288; + else + offset_wdth = 432; + + cv::Scalar mean; + mean = cv::mean(img(cv::Rect(offset_total, 0, offset_wdth, img.rows))); + if ((s == 0 && k == 0) || (s == 5 && k == 11)) + offset_total += 288; + else + offset_total += 432; + offValues[k] = mean.val[0]; + } + } + + log += " 彩色A面RGB值:" + std::to_string(values[0][0]) + "," + std::to_string(values[0][1]) + "," + std::to_string(values[0][2]) + "\r\n"; + log += " 彩色B面RGB值:" + std::to_string(values[1][0]) + "," + std::to_string(values[1][1]) + "," + std::to_string(values[1][2]) + "\r\n"; + ft.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + if (index % 2 == 1) + { // 明场 + // imwrite(std::to_string(savelutindex++) + "clwh.jpg", mergeMat); + log = "开始彩色明场校正 \r\n"; + for (int s = 0; s < 2; s++) + { + int *exposures = (int *)(s == 0 ? cisconfigs.colorCorrect.expF : cisconfigs.colorCorrect.expB); + for (int x = 0; x < 3; x++) + { + int k = (3 * s + x); + int diff = LIGHT_DIFF(scannerinfo.clr_maxbright, *((double *)values + k)); + log += " 明场:" + std::to_string(k) + ";diff:" + std::to_string(diff) + "\r\n"; + + double step = diff * Radio; + int preStep = *((int *)expStep + k); + if (step * preStep < 0) + { + step = 0 - preStep / 2; + } + FMT_STEP(step); + bool isMinStep = abs(step) == 1 && step == *((int *)expStep + k); + bool isOutBounds = exposures[x] >= 1770 && step > 0; + isOutBounds |= exposures[x] <= 0 && step < 0; + if (isOutBounds) + log += " 第" + to_string(x) + "个明场校正异常 \r\n"; + else if (abs(diff) >= 1 || isMinStep) + { + *((int *)expStep + k) = (int)(step); + exposures[x] += step; + if (exposures[x] > 1770) + { + exposures[x] = 1770; + } + if (exposures[x] < 0) + exposures[x] = 0; + isNeedSave = false; + } + log += " 曝光值:" + to_string(exposures[x]) + "\r\n"; + log += " 调整步长:" + to_string(*((int *)expStep + k)) + "\r\n"; + if (isNeedSave) + log += "彩色明场校正完成\r\n"; + } + } + ft.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + } + else // 彩色暗场 + { + int *offsets; + // imwrite(std::to_string(savelutindex++) + "clrblk.jpg", mergeMat); + log = "开始彩色暗场校正"; + for (int s = 0; s < 2; s++) + { + offsets = (int *)(s == 0 ? cisconfigs.colorCorrect.offsetsF : cisconfigs.colorCorrect.offsetsB); + for (int j = 0; j < 6; j++) + { + int k = s * 6 + j; + double diff = BLACK_DIFF(offValues[k]); + double step = Radio * diff; + int preStep = offsetStep[k]; + if (step * preStep < 0) + { + step = 0 - preStep / 2; + } + else + { + Radio = 1; + } + FMT_STEP(step); + bool isMinStep = abs(step) == 1 && step == offsetStep[k]; + bool isOutBounds = offsets[j] >= 255 && step > 0; + isOutBounds |= offsets[j] <= 0 && step < 0; + log += " 暗场校正 :" + std::to_string(k) + ";diff:" + std::to_string(diff) + ";light:" + std::to_string(offValues[k]) + ";offset:" + std::to_string(offsets[j]) + ";step:" + std::to_string(step) + "\r\n"; + if (isOutBounds) + log += " 第" + std::to_string(k) + "条带暗场校正异常,暗场值无法降低 \r\n"; + else if (abs(step) > 1 || isMinStep) + { + offsetStep[k] = (int)(step); + offsets[offset_indexs[k]] += step; + log += "offsetStep" + std::to_string(k) + " = " + std::to_string(offsetStep[k]) + ", offset_indexs" + std::to_string(k) + " =" + std::to_string(offset_indexs[k]) + "\r\n"; + + if (offsets[offset_indexs[k]] < 1) + offsets[offset_indexs[k]] = 1; + if (offsets[offset_indexs[k]] > 255) + offsets[offset_indexs[k]] = 255; + isNeedSave = false; + } + log += (s == 0 ? "彩色正面" : "彩色背面"); + log += "偏移值:" + std::to_string(offsets[0]) + "," + std::to_string(offsets[1]) + "," + std::to_string(offsets[2]) + "," + std::to_string(offsets[3]) + "," + std::to_string(offsets[4]) + "," + std::to_string(offsets[5]) + "\r\n"; + + if (isNeedSave) + log += (s == 0 ? "彩色正面暗场校正完成 \r\n" : "彩色背面暗场校正完成 \r\n"); + } + } + ft.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + } + if (isNeedSave) + { + mBuffMat.release(); + mBuffMat = mergeMat; + } + } + if (isNeedSave && i == 0) + { + if (i > 0) + { + out.release(); + cv::vconcat(mBuffMat, mergeMat, out); + } + else + { + mergeMat.copyTo(out); + cv::cvtColor(out, out, CV_BGR2RGB); + } + char buffer[40]; + sprintf(buffer, "/usr/local/huago/lut_%d.bmp", index); + imwrite(buffer, out); + LOG_TRACE(string_format("save image %s ", buffer)); + } + else if (i != 0) + { + cv::vconcat(mBuffMat, mergeMat, mBuffMat); + } + } + else + { // 灰色模式 + cv::Mat src = GetMergeMat(data, this->width(), this->height(), this->color()); + // imwrite(std::to_string(savelutindex++) + "graywh.jpg", src); + char buffer[40]; + sprintf(buffer, "/usr/local/huago/lut_%d.bmp", index); + double values[2]; + values[0] = cv::mean(src(cv::Rect(0, 0, src.cols / 2, src.rows))).val[0]; + values[1] = cv::mean(src(cv::Rect(src.cols / 2, 0, src.cols / 2, src.rows))).val[0]; + + double offValues[12]; + for (int n = 0; n < 2; n++) + { + cv::Mat img = src(cv::Rect(src.cols * n / 2, 0, src.cols / 2, src.rows)); + int offset_total = 0; + for (int s = 0; s < 6; s++) // + { + int k = n * 6 + s; + int offset_wdth; + if ((s == 0 && k == 0) || (s == 5 && k == 11)) + offset_wdth = 288; + else + offset_wdth = 432; + + cv::Scalar mean; + mean = cv::mean(img(cv::Rect(offset_total, 0, offset_wdth, img.rows))); + if ((s == 0 && k == 0) || (s == 5 && k == 11)) + offset_total += 288; + else + offset_total += 432; + offValues[k] = mean.val[0]; + } + } + + if (index % 2 == 1) // 灰度明场 + { + log = "-----开始灰色明场校正-----\r\n"; + log += " 灰色扫描灰度明场均值:" + to_string(values[0]) + "," + to_string(values[1]) + "\r\n"; + for (int s = 0; s < 2; s++) + { + int *exposures = (int *)(s == 0 ? cisconfigs.grayCorrect.expF : cisconfigs.grayCorrect.expB); + int diff = LIGHT_DIFF(scannerinfo.gray_maxbright, values[s]); + double step = diff * Radio; + log += " 明场:" + to_string(s) + ";diff:" + to_string(diff) + "\r\n"; + int preStep = expStep[s][0]; + if (step * preStep < 0) + { + step = 0 - preStep / 2; + } + else + { + Radio = 1; + } + FMT_STEP(step); + + int exp = *(exposures + 1); + std::string ss1(string_format("exp[%d] = %d step = %.3f \r\n", s, exp, step)); + log += ss1; + bool isMinStep = abs(step) == 1 && step == expStep[s][0]; + bool isOutBounds = exp >= 1770 && step > 0; + isOutBounds |= exp <= 0 && step < 0; + if (isOutBounds) + log += " 第" + to_string(s) + "个明场校正异常 \r\n"; + else if (abs(diff) > 1 || isMinStep) + { + exp += step; + if (exp < 0) + exp = 0; + if (exp > 1770) + exp = 1770; + + float coffe[3] = {1, 1, 1}; // 0.2, 1,0.51 + for (int k = 0; k < 3; k++) + { + *(exposures + k) = (int)(exp * coffe[k]); + expStep[s][k] = (int)(step); + std::string exps(string_format("expStep[%d][%d] = %.3f\r\n", s, k, step)); + log += exps; + std::string ss(string_format("exposures[%d] = %0.3f \r\n", k, exposures[k])); + log += ss; + } + isNeedSave = false; + } + } + ft.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + } + else // 灰度暗场 + { + log = "开始灰色暗场校正 \r\n"; + for (int s = 0; s < 2; s++) + { + int *offsets = (int *)(s == 0 ? cisconfigs.grayCorrect.offsetsF : cisconfigs.grayCorrect.offsetsB); + for (int j = 0; j < 6; j++) + { + int k = s * 6 + j; + double diff = BLACK_DIFF(offValues[k]); + double step = Radio * diff; + int preStep = offsetStep[k]; + if (step * preStep < 0) + { + step = 0 - preStep / 2; + } + else + { + Radio = 1; + } + FMT_STEP(step); + bool isMinStep = abs(step) == 1 && step == offsetStep[k]; + bool isOutBounds = offsets[j] >= 255 && step > 0; + isOutBounds |= offsets[j] <= 0 && step < 0; + log += " 暗场校正 :" + std::to_string(k) + ";diff:" + std::to_string(diff) + ";light:" + std::to_string(offValues[k]) + ";offset:" + std::to_string(offsets[j]) + ";step:" + std::to_string(step) + "\r\n"; + if (isOutBounds) + log += " 第" + std::to_string(i) + "面暗场校正异常,暗场值无法降低 \r\n"; + else if (abs(step) > 1 || isMinStep) + { + offsetStep[k] = (int)(step); + offsets[offset_indexs[k]] += step; + log += "offsetStep" + std::to_string(k) + " = " + std::to_string(offsetStep[k]) + ", offset_indexs" + std::to_string(k) + " =" + std::to_string(offset_indexs[k]) + "\r\n"; + + if (offsets[offset_indexs[k]] < 1) + offsets[offset_indexs[k]] = 1; + if (offsets[offset_indexs[k]] > 255) + offsets[offset_indexs[k]] = 255; + isNeedSave = false; + } + } + log += " 灰度偏移值:" + std::to_string(offsets[0]) + "," + std::to_string(offsets[1]) + "," + std::to_string(offsets[2]) + "," + std::to_string(offsets[3]) + "," + std::to_string(offsets[4]) + "," + std::to_string(offsets[5]) + "\r\n"; + + if (isNeedSave) + log += "灰色暗场校正完成 \r\n"; + } + // final report + ft.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + } + if (isNeedSave) + { + LOG_TRACE(string_format("save image path %s", buffer)); + imwrite(buffer, src); + } + } + } + } + return isNeedSave; +} \ No newline at end of file diff --git a/capimage/Capturer.h b/capimage/Capturer.h new file mode 100644 index 0000000..5228b06 --- /dev/null +++ b/capimage/Capturer.h @@ -0,0 +1,70 @@ +#pragma once +#include +#include "hgutils.h" + +class FpgaComm; +class gVideo; +class Gpio; + +class Capturer : public ICapturer +{ +public: + Capturer(); + virtual ~Capturer(); + virtual void Fpga_regsAccess_reset(bool enable); + virtual void open(); + virtual void open(HGScanConfig config, FPGAConfigParam fpgaparam); + virtual void close(); + virtual void start(); + virtual void stop(); + virtual bool is_runing(); + virtual void snap(); + virtual void stopsnap() {} + virtual int getautosizeheight() { return 0; } + virtual void set_size(int width, int height); + virtual void set_sp(int sp); + + virtual void *readFrame(int timeout); + + virtual void set_gain(int ix, int val); + virtual void set_offset(int ix, int val); + virtual void set_expo(int ix, int val); + + virtual std::shared_ptr regs(); + virtual void reset(); + virtual int width(); + virtual int height(); + virtual int color(); + virtual void init_autocorrect(int colormode); + virtual void setcapturecall(std::function callback) + { + m_captureCallback = callback; + }; + virtual void single_correct(std::uint32_t mode) override {} + +private: + void setFGPAParmas(int exposures[2][3], int gains[2][6], int offsets[2][6]); + void configFPGAParam(bool iscorrect, int mode); + void fpga_reset(); + void fpga_reload(); + void autocorrect(int colormode); + void creatcorrect(int mode); + void openDevice(int mode); + void creatcorrectconfig(int mode); + bool saveLutImg(int mode, int index); + std::shared_ptr vdd_cis_3voff_pin; + std::shared_ptr vdd_vis_5ven_pin; + std::shared_ptr reset_pin; + std::shared_ptr image_in_transfer_pin; + std::shared_ptr initDone_pin; + std::shared_ptr fpgaLoad; + std::shared_ptr fpgaComm; + + std::shared_ptr video; + std::function m_captureCallback; + HGScanConfig m_configParam; + bool bcorrecting; + std::thread m_correctthread; + HGCorrectConfigs cisconfigs; + ScannerNativeParam scannerinfo; +}; diff --git a/capimage/CorrectParam.cpp b/capimage/CorrectParam.cpp new file mode 100644 index 0000000..f85b0ab --- /dev/null +++ b/capimage/CorrectParam.cpp @@ -0,0 +1,856 @@ +#include "CorrectParam.h" +#include +#include +#include +#include +#include +#include "commondef.h" + + +using namespace std; + +#define JSONPATH "/usr/local/huago/cameraparam.json" +#define JSONPATH_8478 "/usr/local/huago/cameraparam_8478.json" +#define JSONPATH_8458_COLOR_LVDS "/usr/local/huago/cameraparam_8458_color_lvds.json" +#define JSONPATH_8478_HL_LVDS "/usr/local/huago/cameraparam_8478_HL_lvds.json" + +#define TEXTLUT200COLORPATH "/usr/local/huago/Textlut200clr.bmp" +#define LUT200COLORPATH "/usr/local/huago/lut200clr.bmp" +#define LUT200_COLOR_BLACKPATH "/usr/local/huago/lut200clrbw.bmp" +#define LUT200_COLOR_WHITEPATH "/usr/local/huago/lut200clrwhite.bmp" + +#define TEXTLUT200GRAYPATH "/usr/local/huago/Textlut200gray.bmp" +#define LUT200GRAYPATH "/usr/local/huago/lut200gray.bmp" +#define LUT200_GRAY_BLACKPATH "/usr/local/huago/lut200graybw.bmp" +#define LUT200_GRAY_WHITEPATH "/usr/local/huago/lut200graywhite.bmp" + +#define TEXTLUT300COLORPATH "/usr/local/huago/Textlut300clr.bmp" +#define LUT300COLORPATH "/usr/local/huago/lut300clr.bmp" +#define LUT300_COLOR_BLACKPATH "/usr/local/huago/lut300clrbw.bmp" +#define LUT300_COLOR_WHITEPATH "/usr/local/huago/lut300clrwhite.bmp" + +#define TEXTLUT300GRAYPATH "/usr/local/huago/Textlut300gray.bmp" +#define LUT300GRAYPATH "/usr/local/huago/lut300gray.bmp" +#define LUT300_GRAY_BLACKPATH "/usr/local/huago/lut300graybw.bmp" +#define LUT300_GRAY_WHITEPATH "/usr/local/huago/lut300graywhite.bmp" + +#define LUT600COLORPATH "/usr/local/huago/lut600clr.bmp" +#define TEXTLUT600COLORPATH "/usr/local/huago/Textlut600clr.bmp" +#define LUT600_COLOR_BLACKPATH "/usr/local/huago/lut600clrbw.bmp" +#define LUT600_COLOR_WHITEPATH "/usr/local/huago/lut600clrwhite.bmp" + +#define LUT600GRAYPATH "/usr/local/huago/lut600gray.bmp" +#define TEXTLUT600GRAYPATH "/usr/local/huago/Textlut600gray.bmp" +#define LUT600_GRAY_BLACKPATH "/usr/local/huago/lut600graybw.bmp" +#define LUT600_GRAY_WHITEPATH "/usr/local/huago/lut600graywhite.bmp" + +#define LUTslow_moireCOLORPATH "/usr/local/huago/lutslow_moireclr.bmp" +#define TEXTLUTslow_moireCOLORPATH "/usr/local/huago/Textlutslow_moireclr.bmp" +#define LUTslow_moire_COLOR_BLACKPATH "/usr/local/huago/lutslow_moireclrbw.bmp" +#define LUTslow_moire_COLOR_WHITEPATH "/usr/local/huago/lutslow_moireclrwhite.bmp" + +#define LUTslow_moireGRAYPATH "/usr/local/huago/lutslow_moiregray.bmp" +#define TEXTLUTslow_moireGRAYPATH "/usr/local/huago/Textlutslow_moiregray.bmp" +#define LUTslow_moire_GRAY_BLACKPATH "/usr/local/huago/lutslow_moiregraybw.bmp" +#define LUTslow_moire_GRAY_WHITEPATH "/usr/local/huago/lutslow_moiregraywhite.bmp" + +#define LUTslow_moire_300_COLORPATH "/usr/local/huago/lutslow_moire300clr.bmp" +#define TEXTLUTslow_moire_300_COLORPATH "/usr/local/huago/Textlutslow_moire300clr.bmp" +#define LUTslow_moire_300_COLOR_BLACKPATH "/usr/local/huago/lutslow_moire300clrbw.bmp" +#define LUTslow_moire_300_COLOR_WHITEPATH "/usr/local/huago/lutslow_moire300clrwhite.bmp" + +#define LUTslow_moire_300_GRAYPATH "/usr/local/huago/lutslow_moire300gray.bmp" +#define TEXTLUTslow_moire_300_GRAYPATH "/usr/local/huago/Textlutslow_moire300gray.bmp" +#define LUTslow_moire_300_GRAY_BLACKPATH "/usr/local/huago/lutslow_moire300graybw.bmp" +#define LUTslow_moire_300_GRAY_WHITEPATH "/usr/local/huago/lutslow_moire300graywhite.bmp" + +#define LUTLong_Manuscript_200_COLORPATH "/usr/local/huago/lutLong_Manuscript200clr.bmp" +#define TEXTLUTLong_Manuscript_200_COLORPATH "/usr/local/huago/TextlutLong_Manuscript200clr.bmp" +#define LUTLong_Manuscript_200_COLOR_BLACKPATH "/usr/local/huago/lutLong_Manuscript200clrbw.bmp" +#define LUTLong_Manuscript_200_COLOR_WHITEPATH "/usr/local/huago/lutLong_Manuscript200clrwhite.bmp" + +#define LUTLong_Manuscript_200_GRAYPATH "/usr/local/huago/lutLong_Manuscript200gray.bmp" +#define TEXTLUTLong_Manuscript_200_GRAYPATH "/usr/local/huago/TextlutLong_Manuscript200gray.bmp" +#define LUTLong_Manuscript_200_GRAY_BLACKPATH "/usr/local/huago/lutLong_Manuscript200graybw.bmp" +#define LUTLong_Manuscript_200_GRAY_WHITEPATH "/usr/local/huago/lutLong_Manuscript200graywhite.bmp" + +#define LUTLong_Manuscript_300_COLORPATH "/usr/local/huago/lutLong_Manuscript300clr.bmp" +#define TEXTLUTLong_Manuscript_300_COLORPATH "/usr/local/huago/TextlutLong_Manuscript300clr.bmp" +#define LUTLong_Manuscript_300_COLOR_BLACKPATH "/usr/local/huago/lutLong_Manuscript300clrbw.bmp" +#define LUTLong_Manuscript_300_COLOR_WHITEPATH "/usr/local/huago/lutLong_Manuscript300clrwhite.bmp" + +#define LUTLong_Manuscript_300_GRAYPATH "/usr/local/huago/lutLong_Manuscript300gray.bmp" +#define TEXTLUTLong_Manuscript_300_GRAYPATH "/usr/local/huago/TextlutLong_Manuscript300gray.bmp" +#define LUTLong_Manuscript_300_GRAY_BLACKPATH "/usr/local/huago/lutLong_Manuscript300graybw.bmp" +#define LUTLong_Manuscript_300_GRAY_WHITEPATH "/usr/local/huago/lutLong_Manuscript300graywhite.bmp" + + +CorrectParam::CorrectParam() +{ + initdefaultpapram(); +} + +CorrectParam::~CorrectParam() +{ +} + +std::vector CorrectParam::GetCorrectParams() +{ + std::ifstream i(JSONPATH); + json j; + i >> j; + i.close(); + std::vector vct_param; + for (json::iterator it = j.begin(); it != j.end(); ++it) + { + auto tmv = it.value(); + FPGAConfigParam param; + from_json(tmv, param); + vct_param.push_back(param); + } + return vct_param; +} + + +std::vector CorrectParam::GetCorrectParams_8458_Color_Lvds() +{ + std::ifstream i(JSONPATH_8458_COLOR_LVDS); + json j; + i >> j; + i.close(); + std::vector vct_param; + for (json::iterator it = j.begin(); it != j.end(); ++it) + { + auto tmv = it.value(); + FPGAConfigParam param; + from_json(tmv, param); + vct_param.push_back(param); + } + return vct_param; +} + +FPGAConfigParam CorrectParam::GetFpgaparam_8458_color_Lvds(int dpi, int mode){ + std::lock_guard lc(m_lock); + FPGAConfigParam param; + auto filejson = GetCorrectParams_8458_Color_Lvds(); + bool isfind = false; + for (size_t i = 0; i < filejson.size(); i++) + { + if ((filejson[i].ColorMode == mode) && + (filejson[i].DpiMode == dpi)) + { + param = filejson[i]; + isfind = true; + break; + } + } + return param; +} + + +FPGAConfigParam CorrectParam::GetFpgaparam(int dpi, int mode) +{ + std::lock_guard lc(m_lock); + FPGAConfigParam param; + auto filejson = GetCorrectParams(); + bool isfind = false; + for (size_t i = 0; i < filejson.size(); i++) + { + if ((filejson[i].ColorMode == mode) && + (filejson[i].DpiMode == dpi)) + { + param = filejson[i]; + isfind = true; + break; + } + } + if (isfind == false && dpi == 0x10) + { + FPGAConfigParam nodeparam; + json t_j; + nodeparam.ColorMode = 1; // 彩色 + nodeparam.DpiMode = 2; // 300 dpi + nodeparam.MaxBright = 200; + nodeparam.MaxExp = 1100; + nodeparam.HRatio = 1065353216; + nodeparam.VRatio = 1065353216; + // 慢速摩尔纹 彩色 + nodeparam.MaxBright = 200; + nodeparam.ColorMode = 1; // 彩色 + nodeparam.DpiMode = 0x10; // 200 dpi + nodeparam.LutPath = LUTslow_moireCOLORPATH; + nodeparam.TextLutPath = TEXTLUTslow_moireCOLORPATH; + nodeparam.Flat_BwPath = LUTslow_moire_COLOR_BLACKPATH; + nodeparam.Flat_WhitePath = LUTslow_moire_COLOR_WHITEPATH; +#ifdef G100 + nodeparam.Sp = 875; +#else + nodeparam.Sp = 878; +#endif + for (size_t i = 0; i < 6; i++) + { + if (i < 3) + nodeparam.ExposureB[i] = nodeparam.ExposureF[i] = 650; // 1500 + nodeparam.GainF[i] = nodeparam.GainB[i] = 170; + nodeparam.OffsetF[i] = nodeparam.OffsetB[i] = 125; + } + filejson.push_back(nodeparam); + param = nodeparam; + // 慢速摩尔纹 灰度 + nodeparam.MaxBright = 220; + nodeparam.ColorMode = 0; // 灰度 + nodeparam.LutPath = LUTslow_moireGRAYPATH; + nodeparam.TextLutPath = TEXTLUTslow_moireGRAYPATH; + nodeparam.Flat_BwPath = LUTslow_moire_GRAY_BLACKPATH; + nodeparam.Flat_WhitePath = LUTslow_moire_GRAY_WHITEPATH; +#ifdef G100 + nodeparam.Sp = 2626; +#else + nodeparam.Sp = 2637; +#endif + filejson.push_back(nodeparam); + if (mode == 0) + param = nodeparam; + json j = json::array(); + for (size_t i = 0; i < filejson.size(); i++) + { + json t_j; + to_json(t_j, filejson[i]); + j.push_back(t_j); + } + ofstream ofs(JSONPATH); + ofs << std::setw(4) << j << std::endl; + ofs.close(); + } + return param; +} + +void CorrectParam::SaveCorrectParam(FPGAConfigParam &parms) +{ + std::lock_guard lc(m_lock); + auto filejson = GetCorrectParams(); + for (size_t i = 0; i < filejson.size(); i++) + { + if ((filejson[i].ColorMode == parms.ColorMode) && + (filejson[i].DpiMode == parms.DpiMode)) + { + memcpy(filejson[i].ExposureB, parms.ExposureB, sizeof(parms.ExposureB)); + memcpy(filejson[i].ExposureF, parms.ExposureF, sizeof(parms.ExposureF)); + memcpy(filejson[i].GainB, parms.GainB, sizeof(parms.GainB)); + memcpy(filejson[i].GainF, parms.GainF, sizeof(parms.GainF)); + memcpy(filejson[i].OffsetB, parms.OffsetB, sizeof(parms.OffsetB)); + memcpy(filejson[i].OffsetF, parms.OffsetF, sizeof(parms.OffsetF)); + filejson[i].LutPath = parms.LutPath; + filejson[i].TextLutPath = parms.TextLutPath; + filejson[i].Flat_BwPath = parms.Flat_BwPath; + filejson[i].Flat_WhitePath = parms.Flat_WhitePath; + filejson[i].Sp = parms.Sp; + filejson[i].HRatio = parms.HRatio; + filejson[i].VRatio = parms.VRatio; + break; + } + } + json j = json::array(); + for (size_t i = 0; i < filejson.size(); i++) + { + json t_j; + to_json(t_j, filejson[i]); + j.push_back(t_j); + } + ofstream ofs(JSONPATH); + ofs << std::setw(4) << j << std::endl; + ofs.close(); +} + +void CorrectParam::initdefaultpapram() +{ + + json js = json::array(); + json js_8478 = json::array(); + { + FPGAConfigParam param; + FPGAConfigParam_8478 param_8478; + json t_j, t_j_8478; + + // 彩色 300 dpi + param_8478.ColorMode = param.ColorMode = 1; // 彩色 + param_8478.DpiMode = param.DpiMode = 2; // 300 dpi + param_8478.MaxBright = param.MaxBright = 200; + param_8478.MaxExp = param.MaxExp = 1100; + param_8478.HRatio = param.HRatio = 1065353216; + param_8478.VRatio = param.VRatio = 1065353216; + param_8478.LutPath = param.LutPath = LUT300COLORPATH; + param_8478.TextLutPath = param.TextLutPath = TEXTLUT300COLORPATH; + param_8478.Flat_BwPath = param.Flat_BwPath = LUT300_COLOR_BLACKPATH; + param_8478.Flat_WhitePath = param.Flat_WhitePath = LUT300_COLOR_WHITEPATH; + param_8478.Sp = 4680; + param.Sp = 1200; + for (size_t i = 0; i < 9; i++) + { + if (i < 6) + { + if (i < 3) + param.ExposureB[i] = param.ExposureF[i] = 700; // 1500 + param.GainF[i] = param.GainB[i] = 170; + param.OffsetF[i] = param.OffsetB[i] = 125; + } + if (i < 3) + param_8478.ExposureB[i] = param_8478.ExposureF[i] = 200; // 1500 + param_8478.GainF_R[i] = param_8478.GainB_R[i] = param_8478.GainF_G[i] = param_8478.GainB_G[i] = + param_8478.GainF_B[i] = param_8478.GainB_B[i] = 80; + param_8478.OffsetF_R[i] = param_8478.OffsetB_R[i] = param_8478.OffsetF_G[i] = param_8478.OffsetB_G[i] = + param_8478.OffsetF_B[i] = param_8478.OffsetB_B[i] = 180; + } + to_json(t_j, param); + to_json(t_j_8478, param_8478); + js.push_back(t_j); + js_8478.push_back(t_j_8478); + + // 灰度 300 dpi + param_8478.ColorMode = param.ColorMode = 0; // 灰度 + param_8478.MaxBright = param.MaxBright = 200; + param_8478.LutPath = param.LutPath = LUT300GRAYPATH; + param_8478.TextLutPath = param.TextLutPath = TEXTLUT300GRAYPATH; + param_8478.Flat_BwPath = param.Flat_BwPath = LUT300_GRAY_BLACKPATH; + param_8478.Flat_WhitePath = param.Flat_WhitePath = LUT300_GRAY_WHITEPATH; + to_json(t_j, param); + to_json(t_j_8478, param_8478); + js.push_back(t_j); + js_8478.push_back(t_j_8478); + + // 彩色 200 dpi + param_8478.MaxBright = param.MaxBright = 200; + param_8478.ColorMode = param.ColorMode = 1; // 彩色 + param_8478.DpiMode = param.DpiMode = 1; // 200 dpi + param_8478.LutPath = param.LutPath = LUT200COLORPATH; + param_8478.TextLutPath = param.TextLutPath = TEXTLUT200COLORPATH; + param_8478.Flat_BwPath = param.Flat_BwPath = LUT200_COLOR_BLACKPATH; + param_8478.Flat_WhitePath = param.Flat_WhitePath = LUT200_COLOR_WHITEPATH; + for (size_t i = 0; i < 9; i++) + { + if (i < 6) + { + if (i < 3) + param.ExposureB[i] = param.ExposureF[i] = 650; // 1500 + param.GainF[i] = param.GainB[i] = 170; + param.OffsetF[i] = param.OffsetB[i] = 125; + } + if (i < 3) + param_8478.ExposureB[i] = param_8478.ExposureF[i] = 200; // 1500 + param_8478.GainF_R[i] = param_8478.GainB_R[i] = param_8478.GainF_G[i] = param_8478.GainB_G[i] = + param_8478.GainF_B[i] = param_8478.GainB_B[i] = 80; + param_8478.OffsetF_R[i] = param_8478.OffsetB_R[i] = param_8478.OffsetF_G[i] = param_8478.OffsetB_G[i] = + param_8478.OffsetF_B[i] = param_8478.OffsetB_B[i] = 180; + } + to_json(t_j, param); + to_json(t_j_8478, param_8478); + js.push_back(t_j); + js_8478.push_back(t_j_8478); + + // 灰度 200dpi + param_8478.MaxBright = param.MaxBright = 200; + param_8478.ColorMode = param.ColorMode = 0; // 灰度 + param_8478.LutPath = param.LutPath = LUT200GRAYPATH; + param_8478.TextLutPath = param.TextLutPath = TEXTLUT200GRAYPATH; + param_8478.Flat_BwPath = param.Flat_BwPath = LUT200_GRAY_BLACKPATH; + param_8478.Flat_WhitePath = param.Flat_WhitePath = LUT200_GRAY_WHITEPATH; + to_json(t_j, param); + to_json(t_j_8478, param_8478); + js.push_back(t_j); + js_8478.push_back(t_j_8478); + + // 彩色 600 dpi + param_8478.MaxBright = param.MaxBright = 200; + param_8478.ColorMode = param.ColorMode = 1; // 彩色 + param_8478.DpiMode = param.DpiMode = 0x03; // 200 dpi + param_8478.LutPath = param.LutPath = LUT600COLORPATH; + param_8478.TextLutPath = param.TextLutPath = TEXTLUT600COLORPATH; + param_8478.Flat_BwPath = param.Flat_BwPath = LUT600_COLOR_BLACKPATH; + param_8478.Flat_WhitePath = param.Flat_WhitePath = LUT600_COLOR_WHITEPATH; + param_8478.Sp = 9000; + param.Sp = 3000; + for (size_t i = 0; i < 9; i++) + { + if (i < 6) + { + if (i < 3) + param.ExposureB[i] = param.ExposureF[i] = 1350; // 1500 + param.GainF[i] = param.GainB[i] = 170; + param.OffsetF[i] = param.OffsetB[i] = 125; + } + if (i < 3) + param_8478.ExposureB[i] = param_8478.ExposureF[i] = 200; // 1500 + param_8478.GainF_R[i] = param_8478.GainB_R[i] = param_8478.GainF_G[i] = param_8478.GainB_G[i] = + param_8478.GainF_B[i] = param_8478.GainB_B[i] = 80; + param_8478.OffsetF_R[i] = param_8478.OffsetB_R[i] = param_8478.OffsetF_G[i] = param_8478.OffsetB_G[i] = + param_8478.OffsetF_B[i] = param_8478.OffsetB_B[i] = 180; + } + to_json(t_j, param); + to_json(t_j_8478, param_8478); + js.push_back(t_j); + js_8478.push_back(t_j_8478); + + // 灰度 600dpi + param_8478.MaxBright = param.MaxBright = 200; + param_8478.ColorMode = param.ColorMode = 0; // 灰度 + param_8478.LutPath = param.LutPath = LUT600GRAYPATH; + param_8478.TextLutPath = param.TextLutPath = TEXTLUT600GRAYPATH; + param_8478.Flat_BwPath = param.Flat_BwPath = LUT600_GRAY_BLACKPATH; + param_8478.Flat_WhitePath = param.Flat_WhitePath = LUT600_GRAY_WHITEPATH; + to_json(t_j, param); + to_json(t_j_8478, param_8478); + js.push_back(t_j); + js_8478.push_back(t_j_8478); + + // 慢速摩尔纹 彩色 + param_8478.MaxBright = param.MaxBright = 200; + param_8478.ColorMode = param.ColorMode = 1; // 彩色 + param_8478.DpiMode = param.DpiMode = 0x10; // 200 dpi + param_8478.LutPath = param.LutPath = LUTslow_moireCOLORPATH; + param_8478.TextLutPath = param.TextLutPath = TEXTLUTslow_moireCOLORPATH; + param_8478.Flat_BwPath = param.Flat_BwPath = LUTslow_moire_COLOR_BLACKPATH; + param_8478.Flat_WhitePath = param.Flat_WhitePath = LUTslow_moire_COLOR_WHITEPATH; +#ifdef G100 + param_8478.Sp = 4680; + param.Sp = 875; +#else + param_8478.Sp = 4680; + param.Sp = 878; +#endif + for (size_t i = 0; i < 9; i++) + { + if (i < 6) + { + if (i < 3) + param.ExposureB[i] = param.ExposureF[i] = 650; // 1500 + param.GainF[i] = param.GainB[i] = 170; + param.OffsetF[i] = param.OffsetB[i] = 125; + } + if (i < 3) + param_8478.ExposureB[i] = param_8478.ExposureF[i] = 200; // 1500 + param_8478.GainF_R[i] = param_8478.GainB_R[i] = param_8478.GainF_G[i] = param_8478.GainB_G[i] = + param_8478.GainF_B[i] = param_8478.GainB_B[i] = 80; + param_8478.OffsetF_R[i] = param_8478.OffsetB_R[i] = param_8478.OffsetF_G[i] = param_8478.OffsetB_G[i] = + param_8478.OffsetF_B[i] = param_8478.OffsetB_B[i] = 180; + } + to_json(t_j, param); + to_json(t_j_8478, param_8478); + js.push_back(t_j); + js_8478.push_back(t_j_8478); + + // 慢速摩尔纹 灰度 + param_8478.MaxBright = param.MaxBright = 200; + param_8478.ColorMode = param.ColorMode = 0; // 灰度 + param_8478.LutPath = param.LutPath = LUTslow_moireGRAYPATH; + param_8478.TextLutPath = param.TextLutPath = TEXTLUTslow_moireGRAYPATH; + param_8478.Flat_BwPath = param.Flat_BwPath = LUTslow_moire_GRAY_BLACKPATH; + param_8478.Flat_WhitePath = param.Flat_WhitePath = LUTslow_moire_GRAY_WHITEPATH; +#ifdef G100 + param_8478.Sp = 4680; + param.Sp = 2626; +#else + param_8478.Sp = 4680; + param.Sp = 2637; +#endif + to_json(t_j, param); + to_json(t_j_8478, param_8478); + js.push_back(t_j); + js_8478.push_back(t_j_8478); + + // 慢速摩尔纹 300dpi 彩色 + param_8478.MaxBright = 200; + param_8478.ColorMode = 1; // 彩色 + param_8478.DpiMode = 0x11; // 200 dpi + param_8478.LutPath = LUTslow_moire_300_COLORPATH; + param_8478.TextLutPath = TEXTLUTslow_moire_300_COLORPATH; + param_8478.Flat_BwPath = LUTslow_moire_300_COLOR_BLACKPATH; + param_8478.Flat_WhitePath = LUTslow_moire_300_COLOR_WHITEPATH; +#ifdef G100 + param_8478.Sp = 6460; +#else + param_8478.Sp = 6460; +#endif + for (size_t i = 0; i < 9; i++) + { + if (i < 3) + param_8478.ExposureB[i] = param_8478.ExposureF[i] = 200; // 1500 + param_8478.GainF_R[i] = param_8478.GainB_R[i] = param_8478.GainF_G[i] = param_8478.GainB_G[i] = + param_8478.GainF_B[i] = param_8478.GainB_B[i] = 80; + param_8478.OffsetF_R[i] = param_8478.OffsetB_R[i] = param_8478.OffsetF_G[i] = param_8478.OffsetB_G[i] = + param_8478.OffsetF_B[i] = param_8478.OffsetB_B[i] = 180; + } + to_json(t_j_8478, param_8478); + js_8478.push_back(t_j_8478); + + // 慢速摩尔纹 300dpi 灰度 + param_8478.MaxBright = 200; + param_8478.ColorMode = 0; // 灰度 + param_8478.LutPath = LUTslow_moire_300_GRAYPATH; + param_8478.TextLutPath = TEXTLUTslow_moire_300_GRAYPATH; + param_8478.Flat_BwPath = LUTslow_moire_300_GRAY_BLACKPATH; + param_8478.Flat_WhitePath = LUTslow_moire_300_GRAY_WHITEPATH; +#ifdef G100 + param_8478.Sp = 6460; +#else + param_8478.Sp = 6460; +#endif + to_json(t_j_8478, param_8478); + js_8478.push_back(t_j_8478); + + + // 长文稿 200dpi 彩色 + param_8478.MaxBright = 200; + param_8478.ColorMode = 1; // 彩色 + param_8478.DpiMode = 0x20; // 200 dpi + param_8478.LutPath = LUTLong_Manuscript_200_COLORPATH;; + param_8478.TextLutPath = TEXTLUTLong_Manuscript_200_COLORPATH; + param_8478.Flat_BwPath = LUTLong_Manuscript_200_COLOR_BLACKPATH; + param_8478.Flat_WhitePath = LUTLong_Manuscript_200_COLOR_WHITEPATH; +#ifdef G100 + param_8478.Sp = 6460; +#else + param_8478.Sp = 30627; +#endif + for (size_t i = 0; i < 9; i++) + { + if (i < 3) + param_8478.ExposureB[i] = param_8478.ExposureF[i] = 200; // 1500 + param_8478.GainF_R[i] = param_8478.GainB_R[i] = param_8478.GainF_G[i] = param_8478.GainB_G[i] = + param_8478.GainF_B[i] = param_8478.GainB_B[i] = 80; + param_8478.OffsetF_R[i] = param_8478.OffsetB_R[i] = param_8478.OffsetF_G[i] = param_8478.OffsetB_G[i] = + param_8478.OffsetF_B[i] = param_8478.OffsetB_B[i] = 180; + } + to_json(t_j_8478, param_8478); + js_8478.push_back(t_j_8478); + + // 长文稿 200dpi 灰度 + param_8478.MaxBright = 200; + param_8478.ColorMode = 0; // 灰度 + param_8478.LutPath = LUTLong_Manuscript_200_GRAYPATH;; + param_8478.TextLutPath = TEXTLUTLong_Manuscript_200_GRAYPATH; + param_8478.Flat_BwPath = LUTLong_Manuscript_200_GRAY_BLACKPATH; + param_8478.Flat_WhitePath = LUTLong_Manuscript_200_GRAY_WHITEPATH; +#ifdef G100 + param_8478.Sp = 6460; +#else + param_8478.Sp = 30627; +#endif + to_json(t_j_8478, param_8478); + js_8478.push_back(t_j_8478); + + + + // 长文稿 300dpi 彩色 + param_8478.MaxBright = 200; + param_8478.ColorMode = 1; // 彩色 + param_8478.DpiMode = 0x21; // 200 dpi + param_8478.LutPath = LUTLong_Manuscript_300_COLORPATH;; + param_8478.TextLutPath = TEXTLUTLong_Manuscript_300_COLORPATH; + param_8478.Flat_BwPath = LUTLong_Manuscript_300_COLOR_BLACKPATH; + param_8478.Flat_WhitePath = LUTLong_Manuscript_300_COLOR_WHITEPATH; +#ifdef G100 + param_8478.Sp = 6460; +#else + param_8478.Sp = 20436; +#endif + for (size_t i = 0; i < 9; i++) + { + if (i < 3) + param_8478.ExposureB[i] = param_8478.ExposureF[i] = 200; // 1500 + param_8478.GainF_R[i] = param_8478.GainB_R[i] = param_8478.GainF_G[i] = param_8478.GainB_G[i] = + param_8478.GainF_B[i] = param_8478.GainB_B[i] = 80; + param_8478.OffsetF_R[i] = param_8478.OffsetB_R[i] = param_8478.OffsetF_G[i] = param_8478.OffsetB_G[i] = + param_8478.OffsetF_B[i] = param_8478.OffsetB_B[i] = 180; + } + to_json(t_j_8478, param_8478); + js_8478.push_back(t_j_8478); + + // 长文稿 300dpi 灰度 + param_8478.MaxBright = 200; + param_8478.ColorMode = 0; // 灰度 + param_8478.LutPath = LUTLong_Manuscript_300_GRAYPATH;; + param_8478.TextLutPath = TEXTLUTLong_Manuscript_300_GRAYPATH; + param_8478.Flat_BwPath = LUTLong_Manuscript_300_GRAY_BLACKPATH; + param_8478.Flat_WhitePath = LUTLong_Manuscript_300_GRAY_WHITEPATH; +#ifdef G100 + param_8478.Sp = 6460; +#else + param_8478.Sp = 20436; +#endif + to_json(t_j_8478, param_8478); + js_8478.push_back(t_j_8478); + } + + struct stat buff; + if (stat(JSONPATH, &buff) != 0) // 存在 + { + std::ofstream ofs(JSONPATH); + ofs << std::setw(4) << js << std::endl; + ofs.close(); + } + if (stat(JSONPATH_8478, &buff) != 0) // 存在 + { + std::ofstream ofs(JSONPATH_8478); + ofs << std::setw(4) << js_8478 << std::endl; + ofs.close(); + } + if (stat(JSONPATH_8458_COLOR_LVDS, &buff) != 0) // 存在 + { + std::ofstream ofs(JSONPATH_8458_COLOR_LVDS); + ofs << std::setw(4) << js << std::endl; + ofs.close(); + } + if (stat(JSONPATH_8478_HL_LVDS, &buff) != 0) // 存在 + { + std::ofstream ofs(JSONPATH_8478_HL_LVDS); + ofs << std::setw(4) << js_8478 << std::endl; + ofs.close(); + } +} + +void CorrectParam::to_json(json &j, FPGAConfigParam ¶m) +{ + j = json{{"ExposureF", param.ExposureF}, + {"GainF", param.GainF}, + {"OffsetF", param.OffsetF}, + {"ExposureB", param.ExposureB}, + {"GainB", param.GainB}, + {"OffsetB", param.OffsetB}, + {"DpiMode", param.DpiMode}, + {"ColorMode", param.ColorMode}, + {"MaxBright", param.MaxBright}, + {"MaxExp", param.MaxExp}, + {"Sp", param.Sp}, + {"HRatio", param.HRatio}, + {"VRatio", param.VRatio}, + {"LutPath", param.LutPath}, + {"TextLutPath", param.TextLutPath}, + {"FlatBlackPath", param.Flat_BwPath}, + {"FlatWhitePath", param.Flat_WhitePath}}; +} + +void CorrectParam::from_json(json &j, FPGAConfigParam ¶m) +{ + j.at("ExposureF").get_to(param.ExposureF); + j.at("GainF").get_to(param.GainF); + j.at("OffsetF").get_to(param.OffsetF); + j.at("ExposureB").get_to(param.ExposureB); + j.at("GainB").get_to(param.GainB); + j.at("OffsetB").get_to(param.OffsetB); + j.at("DpiMode").get_to(param.DpiMode); + j.at("ColorMode").get_to(param.ColorMode); + j.at("MaxBright").get_to(param.MaxBright); + j.at("MaxExp").get_to(param.MaxExp); + j.at("Sp").get_to(param.Sp); + j.at("HRatio").get_to(param.HRatio); + j.at("VRatio").get_to(param.VRatio); + j.at("LutPath").get_to(param.LutPath); + j.at("TextLutPath").get_to(param.TextLutPath); + j.at("FlatBlackPath").get_to(param.Flat_BwPath); + j.at("FlatWhitePath").get_to(param.Flat_WhitePath); +} + +std::vector CorrectParam::GetCorrectParams_8478() +{ + std::ifstream i(JSONPATH_8478); + json j; + i >> j; + i.close(); + std::vector vct_param; + for (json::iterator it = j.begin(); it != j.end(); ++it) + { + auto tmv = it.value(); + FPGAConfigParam_8478 param; + from_json(tmv, param); + vct_param.push_back(param); + } + return vct_param; +} + +std::vector CorrectParam::GetCorrectParams_8478_HL_Lvds() +{ + std::ifstream i(JSONPATH_8478_HL_LVDS); + json j; + i >> j; + i.close(); + std::vector vct_param; + for (json::iterator it = j.begin(); it != j.end(); ++it) + { + auto tmv = it.value(); + FPGAConfigParam_8478 param; + from_json(tmv, param); + vct_param.push_back(param); + } + return vct_param; +} + + +void CorrectParam::to_json(json &j, FPGAConfigParam_8478 ¶m) +{ + j = json{{"ExposureF", param.ExposureF}, + {"GainF_R", param.GainF_R}, + {"OffsetF_R", param.OffsetF_R}, + {"GainF_G", param.GainF_G}, + {"OffsetF_G", param.OffsetF_G}, + {"GainF_B", param.GainF_B}, + {"OffsetF_B", param.OffsetF_B}, + {"ExposureB", param.ExposureB}, + {"GainB_R", param.GainB_R}, + {"OffsetB_R", param.OffsetB_R}, + {"GainB_G", param.GainB_G}, + {"OffsetB_G", param.OffsetB_G}, + {"GainB_B", param.GainB_B}, + {"OffsetB_B", param.OffsetB_B}, + {"DpiMode", param.DpiMode}, + {"ColorMode", param.ColorMode}, + {"MaxBright", param.MaxBright}, + {"MaxExp", param.MaxExp}, + {"Sp", param.Sp}, + {"HRatio", param.HRatio}, + {"VRatio", param.VRatio}, + {"LutPath", param.LutPath}, + {"TextLutPath", param.TextLutPath}, + {"FlatBlackPath", param.Flat_BwPath}, + {"FlatWhitePath", param.Flat_WhitePath}}; +} + +void CorrectParam::from_json(json &j, FPGAConfigParam_8478 ¶m) +{ + j.at("ExposureF").get_to(param.ExposureF); + j.at("GainF_R").get_to(param.GainF_R); + j.at("OffsetF_R").get_to(param.OffsetF_R); + j.at("GainF_G").get_to(param.GainF_G); + j.at("OffsetF_G").get_to(param.OffsetF_G); + j.at("GainF_B").get_to(param.GainF_B); + j.at("OffsetF_B").get_to(param.OffsetF_B); + j.at("ExposureB").get_to(param.ExposureB); + j.at("GainB_R").get_to(param.GainB_R); + j.at("OffsetB_R").get_to(param.OffsetB_R); + j.at("GainB_G").get_to(param.GainB_G); + j.at("OffsetB_G").get_to(param.OffsetB_G); + j.at("GainB_B").get_to(param.GainB_B); + j.at("OffsetB_B").get_to(param.OffsetB_B); + j.at("DpiMode").get_to(param.DpiMode); + j.at("ColorMode").get_to(param.ColorMode); + j.at("MaxBright").get_to(param.MaxBright); + j.at("MaxExp").get_to(param.MaxExp); + j.at("Sp").get_to(param.Sp); + j.at("HRatio").get_to(param.HRatio); + j.at("VRatio").get_to(param.VRatio); + j.at("LutPath").get_to(param.LutPath); + j.at("TextLutPath").get_to(param.TextLutPath); + j.at("FlatBlackPath").get_to(param.Flat_BwPath); + j.at("FlatWhitePath").get_to(param.Flat_WhitePath); +} + +void CorrectParam::SaveCorrectParam(FPGAConfigParam_8478 &parms) +{ + std::lock_guard lc(m_lock); + auto filejson = GetCorrectParams_8478(); + for (size_t i = 0; i < filejson.size(); i++) + { + if ((filejson[i].ColorMode == parms.ColorMode) && + (filejson[i].DpiMode == parms.DpiMode)) + { + memcpy(filejson[i].ExposureB, parms.ExposureB, sizeof(parms.ExposureB)); + memcpy(filejson[i].ExposureF, parms.ExposureF, sizeof(parms.ExposureF)); + memcpy(filejson[i].GainB_R, parms.GainB_R, sizeof(parms.GainB_R)); + memcpy(filejson[i].GainF_R, parms.GainF_R, sizeof(parms.GainF_R)); + memcpy(filejson[i].OffsetB_R, parms.OffsetB_R, sizeof(parms.OffsetB_R)); + memcpy(filejson[i].OffsetF_R, parms.OffsetF_R, sizeof(parms.OffsetF_R)); + + memcpy(filejson[i].GainB_G, parms.GainB_G, sizeof(parms.GainB_G)); + memcpy(filejson[i].GainF_G, parms.GainF_G, sizeof(parms.GainF_G)); + memcpy(filejson[i].OffsetB_G, parms.OffsetB_G, sizeof(parms.OffsetB_G)); + memcpy(filejson[i].OffsetF_G, parms.OffsetF_G, sizeof(parms.OffsetF_G)); + + memcpy(filejson[i].GainB_B, parms.GainB_B, sizeof(parms.GainB_B)); + memcpy(filejson[i].GainF_B, parms.GainF_B, sizeof(parms.GainF_B)); + memcpy(filejson[i].OffsetB_B, parms.OffsetB_B, sizeof(parms.OffsetB_B)); + memcpy(filejson[i].OffsetF_B, parms.OffsetF_B, sizeof(parms.OffsetF_B)); + filejson[i].LutPath = parms.LutPath; + filejson[i].TextLutPath = parms.TextLutPath; + filejson[i].Flat_BwPath = parms.Flat_BwPath; + filejson[i].Flat_WhitePath = parms.Flat_WhitePath; + filejson[i].Sp = parms.Sp; + filejson[i].HRatio = parms.HRatio; + filejson[i].VRatio = parms.VRatio; + break; + } + } + json j = json::array(); + for (size_t i = 0; i < filejson.size(); i++) + { + json t_j; + to_json(t_j, filejson[i]); + j.push_back(t_j); + } + ofstream ofs(JSONPATH_8478); + ofs << std::setw(4) << j << std::endl; + ofs.close(); +} + +FPGAConfigParam_8478 CorrectParam::GetFpgaparam_8478(int dpi, int mode) +{ + std::lock_guard lc(m_lock); + FPGAConfigParam_8478 param; + auto filejson = GetCorrectParams_8478(); + for (size_t i = 0; i < filejson.size(); i++) + { + if ((filejson[i].ColorMode == mode) && + (filejson[i].DpiMode == dpi)) + { + param = filejson[i]; + break; + } + } + return param; +} + +FPGAConfigParam_8478 CorrectParam::GetFpgaparam_8478_HL_Lvds(int dpi, int mode) +{ + std::lock_guard lc(m_lock); + FPGAConfigParam_8478 param; + auto filejson = GetCorrectParams_8478_HL_Lvds(); + for (size_t i = 0; i < filejson.size(); i++) + { + if ((filejson[i].ColorMode == mode) && + (filejson[i].DpiMode == dpi)) + { + param = filejson[i]; + break; + } + } + return param; +} + + +void CorrectParam::set_sp(int dpi, int mode,uint32_t sp) +{ + auto param = GetFpgaparam(dpi,mode); + param.Sp = sp; + SaveCorrectParam(param); +} +void CorrectParam::set_sp_8478(int dpi, int mode,uint32_t sp) +{ + auto param = GetFpgaparam_8478(dpi,mode); + param.Sp = sp; + SaveCorrectParam(param); +} + +void CorrectParam::set_sp_8458_color_lvds(int dpi,int mode,uint32_t sp) +{ + auto param = GetFpgaparam_8458_color_Lvds(dpi,mode); + param.Sp = sp; + SaveCorrectParam(param); +} + +void CorrectParam::set_sp_8748_HL_lvds(int dpi,int mode,uint32_t sp) +{ + auto param = GetFpgaparam_8478_HL_Lvds(dpi,mode); + param.Sp = sp; + SaveCorrectParam(param); +} + + +CorrectParam m_static_correctparam; \ No newline at end of file diff --git a/capimage/CorrectParam.h b/capimage/CorrectParam.h new file mode 100644 index 0000000..be00dda --- /dev/null +++ b/capimage/CorrectParam.h @@ -0,0 +1,51 @@ +#pragma once +#include "json.hpp" +#include +#include +#include "CameraParam.h" +#include + +using json = nlohmann::json; + +class CorrectParam +{ +public: + CorrectParam(/* args */); + ~CorrectParam(); + + + FPGAConfigParam GetFpgaparam(int dpi, int mode); + FPGAConfigParam GetFpgaparam_8458_color_Lvds(int dpi, int mode); + void SaveCorrectParam(FPGAConfigParam &parms); + + FPGAConfigParam_8478 GetFpgaparam_8478(int dpi, int mode); + FPGAConfigParam_8478 GetFpgaparam_8478_HL_Lvds(int dpi, int mode); + void SaveCorrectParam(FPGAConfigParam_8478 &parms); + + void set_sp(int dpi, int mode,uint32_t sp); + void set_sp_8478(int dpi, int mode,uint32_t sp); + void set_sp_8458_color_lvds(int dpi,int mode,uint32_t sp); + void set_sp_8748_HL_lvds(int dpi,int mode,uint32_t sp); + +private: + void initdefaultpapram(); + std::vector GetCorrectParams(); + std::vector GetCorrectParams_8458_Color_Lvds(); + void to_json(json &j, FPGAConfigParam ¶m); + void from_json(json &j, FPGAConfigParam ¶m); + + + std::vector GetCorrectParams_8478(); + std::vector GetCorrectParams_8478_HL_Lvds(); + void to_json(json &j, FPGAConfigParam_8478 ¶m); + void from_json(json &j, FPGAConfigParam_8478 ¶m); + + std::mutex m_lock; +}; + + +extern CorrectParam m_static_correctparam; +static CorrectParam& Get_Static_CorrectParam() +{ + return m_static_correctparam; +} \ No newline at end of file diff --git a/capimage/FpgaComm.cpp b/capimage/FpgaComm.cpp new file mode 100644 index 0000000..084e66b --- /dev/null +++ b/capimage/FpgaComm.cpp @@ -0,0 +1,495 @@ +// +// Created by Nick on 2019/4/7. +// +#include "FpgaComm.h" +#include +#include "uartregsaccess.h" +#include "config.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() +{ + m_regsAccess.reset(new UartRegsAccess(FPGA_UART, 921600, 0x03, 0x83)); + // update(0); + + // Reg(AledR).sample = 256; + // WR_Reg(AledR); +} + +void FpgaComm::regsAccess_reset(bool enable) +{ + if (enable) + { + if (!m_regsAccess.get()) + m_regsAccess.reset(new UartRegsAccess(FPGA_UART, 921600, 0x03, 0x83)); + return; + } + if (m_regsAccess.get()) + m_regsAccess.reset(); +} + +bool FpgaComm::read(unsigned int addr, unsigned int &val) +{ + if (m_regsAccess.get()) + return m_regsAccess->read(addr, val); + return false; +} + +bool FpgaComm::write(unsigned int addr, unsigned int val) +{ + if (m_regsAccess.get()) + return m_regsAccess->write(addr, val); + return false; +} + +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() +{ + ReadReg(cmd); + 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(int times) +{ + std::uint32_t tmp_reg = 0; + for (int i = 0; i < 22; i++) + { + read(i, tmp_reg); + printf("times[%d] reg[%d] = 0x%08x \n", times, i, tmp_reg); + } +} + +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); +} + +void FpgaComm::setEnTestCol(bool en) +{ + Reg(AledR).en_test_color = en ? 1 : 0; + WR_Reg(AledR); +} + +void FpgaComm::setEnTestBit(bool en) +{ + Reg(AledR).en_test = en ? 1 : 0; + WR_Reg(AledR); +} + +void FpgaComm::setVsp(unsigned int Aside, unsigned int BSide) +{ + CISVSP vsp; + vsp.bits.ASide_VSP = Aside; + vsp.bits.BSide_VSP = BSide; + vsp.bits.reserved = 0; + printf("setVsp A side =%d B side=%d vspint=%08x \n", vsp.bits.ASide_VSP, vsp.bits.BSide_VSP, vsp.value); + m_regsAccess->write(13, vsp.value); +} + +void FpgaComm::setFrame_interval_min(int min) +{ + fpgaParams.FrameInterval.Frame_Interval_min = min; + fpgaParams.FrameInterval.reversed = 0; + WR_Reg(FrameInterval); +} + +int FpgaComm::getFrame_interval_min() +{ + uint32_t value = 0; + fpgaParams.FrameInterval.reversed = 0; + read(0x0c, value); + fpgaParams.FrameInterval = *(CisFrameInterval *)&value; + return fpgaParams.FrameInterval.Frame_Interval_min; +} + +void FpgaComm::setFrame_interval_max(int max) +{ + fpgaParams.FrameInterval.Frame_Interval_max = max; + fpgaParams.FrameInterval.reversed = 0; + WR_Reg(FrameInterval); +} + +int FpgaComm::getFrame_interval_max() +{ + uint32_t value = 0; + fpgaParams.FrameInterval.reversed = 0; + read(0x0c, value); + fpgaParams.FrameInterval = *(CisFrameInterval *)&value; + return fpgaParams.FrameInterval.Frame_Interval_max; +} + +unsigned int FpgaComm::getFrame_counter_val() +{ + uint32_t crt_frame_count = 0; + uint32_t reg8 = 0; + + read(8, reg8); + // write(8,reg8 & 0x8); + // std::this_thread::sleep_for(std::chrono::milliseconds(2)); + write(8, reg8 & 0xfffffff7); // off stop snap + read(8, reg8); + // std::this_thread::sleep_for(std::chrono::milliseconds(2)); + read(0x10, crt_frame_count); + + if (crt_frame_count & 0xffff <= 0) + { + for (int i = 0; i < 3; i++) + { + read(0x10, crt_frame_count); + printf("try %d times read frame count,frame_count = %d \n", i, crt_frame_count); + if (crt_frame_count & 0xffff > 0) + break; + } + } + write(8, reg8 | 0x8); // on reset counter + // std::this_thread::sleep_for(std::chrono::milliseconds(2)); + // printf("TWO height reg[14] = %d reg[16] = %d \n", read(14) & 0xffff,read(16)); + return crt_frame_count & 0xffff; +} + +int FpgaComm::getFrameNum() +{ + return fpgaParams.frame.num; +} + +void FpgaComm::set_cis_type(bool isA3_CIS) +{ + fpgaParams.AledR.cis_type = isA3_CIS ? 1 : 0; +} + +void FpgaComm::set_8478_type(bool is_HL) +{ + ReadReg(cmd); + Reg(cmd).cis_HL = is_HL; + WriteReg(cmd); +} \ No newline at end of file diff --git a/capimage/FpgaComm.h b/capimage/FpgaComm.h new file mode 100644 index 0000000..ea01dbd --- /dev/null +++ b/capimage/FpgaComm.h @@ -0,0 +1,217 @@ +#pragma once +#include +#include +#include "regsaccess.h" + +#ifdef HAS_UV +#define MAX_REGS 0x0e +#else +#define MAX_REGS 0x0e +#endif + +typedef struct Frame_FPGA +{ + unsigned short int height; + unsigned short int num : 16; + +} 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 adc_confif_hz : 4; + unsigned int cis_HL : 1; //true 华菱 8478 lvds + unsigned int reserved : 26; +} 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 en_test_color : 1; + unsigned short int en_test : 1; + unsigned short int cis_type : 1; + unsigned short int reserved : 3; + 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 struct CIS_FRAME_INTERVAL +{ + unsigned short Frame_Interval_min; + unsigned short Frame_Interval_max : 13; + unsigned short reversed : 3; +} CisFrameInterval; + +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 + CisFrameInterval FrameInterval; // 0x0c + CisLedUv UVLed; + unsigned int reversed; // 0x0e + unsigned int fpgaversion; // 0x0f + // unsigned int ConFrameCount;//多帧计数 + }; + unsigned int regs[16]; +} FpgaParams; + +typedef union CIS_VSP +{ + struct + { + unsigned int ASide_VSP : 9; + unsigned int BSide_VSP : 9; + unsigned int reserved : 14; + } bits; + int value; +} CISVSP; + +class FpgaComm : public IRegsAccess +{ +public: + FpgaComm(); + 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 setEnTestCol(bool en); + void setEnTestBit(bool en); + + 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(int times); + void enableJamCheck(bool b); + void resetADC(); + void setVsp(unsigned int Aside, unsigned int BSide); + + void setFrame_interval_min(int min); + int getFrame_interval_min(); + void setFrame_interval_max(int max); + int getFrame_interval_max(); + unsigned int getFrame_counter_val(); + int getFrameNum(); + void set_cis_type(bool isA3_CIS); + void set_8478_type(bool is_HL); + + 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/capimage/GrayLighting.h b/capimage/GrayLighting.h new file mode 100644 index 0000000..45d4a02 --- /dev/null +++ b/capimage/GrayLighting.h @@ -0,0 +1,109 @@ +#pragma once +#include +#include +#include + +std::vector caculate_abcd(std::vector> point) +{ + int MaxElement = point.size() - 1; + // 计算常数f + double f = point[0].second; + // 求解 + int n, m; + + std::vector> a; + + for (int i = 0; i < MaxElement; i++) + { + std::vector b; + b.resize(MaxElement + 1); + a.push_back(b); + } + + for (int i = 0; i < MaxElement; i++) + { + for (int j = 0; j < MaxElement; j++) + a[i][j] = pow(point[i + 1].first, MaxElement - j); + a[i][MaxElement] = point[i + 1].second - f; + } + + int i, j; + n = MaxElement; + + for (j = 0; j < n; j++) + { + double max = 0; + double imax = 0; + for (i = j; i < n; i++) + { + if (imax < fabs(a[i][j])) + { + imax = fabs(a[i][j]); + max = a[i][j]; // 得到各行中所在列最大元素 + m = i; + } + } + if (fabs(a[j][j]) != max) + { + double b = 0; + for (int k = j; k < n + 1; k++) + { + b = a[j][k]; + a[j][k] = a[m][k]; + a[m][k] = b; + } + } + + for (int r = j; r < n + 1; r++) + { + a[j][r] = a[j][r] / max; // 让该行的所在列除以所在列的第一个元素,目的是让首元素为1 + } + + for (i = j + 1; i < n; i++) + { + double c = a[i][j]; + if (c == 0.0) + continue; + for (int s = j; s < n + 1; s++) + { + a[i][s] = a[i][s] - a[j][s] * c; // 前后行数相减,使下一行或者上一行的首元素为0 + } + } + } + for (i = n - 2; i >= 0; i--) + { + for (j = i + 1; j < n; j++) + { + a[i][n] = a[i][n] - a[j][n] * a[i][j]; + } + } + + std::vector result; + for (int k = 0; k < n; k++) + result.push_back(a[k][n]); + result.push_back(f); + return result; +} + +double caculate_value(const std::vector &abcd, double x) +{ + return abcd[0] * x * x * x + abcd[1] * x * x + abcd[2] * x + abcd[3]; +} + +void brightness(cv::Mat &lut, int alpha = 170) +{ + std::vector> pos; + pos.push_back(std::pair(0, 0)); + pos.push_back(std::pair(64, 64)); + pos.push_back(std::pair(alpha, 255)); + pos.push_back(std::pair(255, 255)); + std::vector abcd = caculate_abcd(pos); + + uchar table[256]; + for (int i = 0; i < 256; i++) + table[i] = static_cast(caculate_value(abcd, i)); + + uchar *ptr = lut.data; + for (int i = 0, length = lut.total() * lut.channels(); i < length; i++) + ptr[i] = table[ptr[i]]; +} \ No newline at end of file diff --git a/capimage/ICapturer.h b/capimage/ICapturer.h new file mode 100644 index 0000000..9bb89db --- /dev/null +++ b/capimage/ICapturer.h @@ -0,0 +1,52 @@ +#pragma once +#include +#include +#include +#include +#include "regsaccess.h" +#include "commondef.h" +#include "CorrectParam.h" +#include "opencv2\opencv.hpp" + +class ICapturer +{ +public: + virtual ~ICapturer() {} + virtual void Fpga_regsAccess_reset(bool enable) = 0; + virtual void open() = 0; + virtual void open(HGScanConfig config, FPGAConfigParam fpgaparam) = 0; + virtual void open(HGScanConfig config, FPGAConfigParam_8478 fpgaparam){}; + virtual void snap(frame_data_info info) {} + virtual cv::Size frame_data_size() { return {0, 0}; } + virtual void close() = 0; + virtual void start() = 0; + virtual void stop() = 0; + virtual bool is_runing() = 0; + virtual void snap() = 0; + virtual void stopsnap() = 0; + virtual int getautosizeheight() = 0; + virtual void set_size(int width, int height) = 0; + virtual void *readFrame(int timeout) = 0; + + virtual void set_gain(int ix, int val) = 0; + virtual void set_offset(int ix, int val) = 0; + virtual void set_expo(int ix, int val) = 0; + virtual uint32_t multi_frame_counts() { return 0; } + virtual uint32_t multi_curr_snap_index() { return 0; } + + virtual std::shared_ptr regs() = 0; + virtual void reset() = 0; + virtual int width() = 0; + virtual int height() = 0; + virtual int color() = 0; + virtual void init_autocorrect(int colormode = 0) = 0; + virtual void setcapturecall(std::function callback) = 0; + virtual frame_data_info ReadMultiFrame(int state) { return {0}; } + virtual void single_correct(std::uint32_t mode) = 0; + virtual void set_fpga_vsp(int a, int b) {} + virtual cv::Mat read_one_frame() { return cv::Mat(); } + void set_gscancap(GScanCap cap){ m_gscancap = cap;} + +protected: + GScanCap m_gscancap; +}; \ No newline at end of file diff --git a/capimage/MonoCapturer.cpp b/capimage/MonoCapturer.cpp new file mode 100644 index 0000000..afad9d6 --- /dev/null +++ b/capimage/MonoCapturer.cpp @@ -0,0 +1,1045 @@ +#include "MonoCapturer.h" +#include "config.h" +#include "applog.h" +#include "gvideoisp1.h" +#include "Gpio.h" +#include "DevUtil.h" +#include "FpgaComm.h" +#include "CorrectParam.h" +#include "correct_ultis.h" +#include "stringex.hpp" +#include "filetools.h" +#include "CImageMerge.h" +#include "jsonconfig.h" +#include "ThreadPool.h" +#include "deviceconfig.h" + +using namespace std; +using namespace cv; + +#define LOG_PATH "/usr/local/correct.log" +FileTools ft_log(LOG_PATH); + +static std::string loggername = "MonoCapturer"; +static double radio = 1.0; +static int offsetStep1[12]; +static int expStep1[2][3]; + +static void initStep1() +{ + printf("initStep aaaaaaaaaaa \n"); + for (int i = 0; i < 2; i++) + { + for (int j = 0; j < 3; j++) + { + expStep1[i][j] = 600; + } + } + for (int i = 0; i < 12; i++) + { + offsetStep1[i] = 256; + printf("offsetStep[%d]=%d \n", i, offsetStep1[i]); + } +} + +MonoCapturer::MonoCapturer() : // vdd_cis_3voff_pin(new GpioOut(CIS_3v3_Off)), + // vdd_vis_5ven_pin(new GpioOut(CIS_5v_En)), + reset_pin(new GpioOut(50)), + // image_in_transfer_pin(new Gpio(Image_In_Transfer)), + // initDone_pin(new Gpio(Fpga_InitDone)), + fpgaLoad(new Gpio(70)), + fpga_conf_done(new Gpio(69)), // gpio init 导出 scanservice 仅操作IO + fpga_conf_initn(new Gpio(71)), // gpio init 导出 scanservice 仅操作IO + bcorrecting(false), + m_fpgaversion(0x00090001) +{ + LOG_INIT(); + fpga_conf_done->setDirection(Gpio::in); + fpgaComm.reset(new FpgaComm()); + // fpga_reset(); + // fpgaComm->resetADC(); + fpgaComm->setDelayTime(0X3e8); + // fpgaComm->update(); + video.reset(new VIDEO_CLASS()); + fpgaComm->read(15, m_fpgaversion); +} + +MonoCapturer::~MonoCapturer() +{ + if (video.get()) + video.reset(); + + printf("Exit ~MonoCapturer() \n"); +} + +void MonoCapturer::open() +{ +} + +void MonoCapturer::Fpga_regsAccess_reset(bool enable) +{ + if (fpgaComm.get()) + fpgaComm->regsAccess_reset(enable); +} + +void MonoCapturer::open(HGScanConfig config, FPGAConfigParam fpgaparam) +{ + m_config = config; + m_fpgaparam = fpgaparam; + fpgaComm->update(1); + bool dunnancis = true; + int dpi; + if (dunnancis) + dpi = config.g200params.dpi == 0x02 ? 2 : (config.g200params.dpi == 0x03 ? 3 : 2); + else + dpi = config.g200params.dpi; + + int mode = config.g200params.color; + int channelwidth = dpi == 0x02 ? 1296 : (dpi == 0x03 ? 2592 : 864); + int channels = mode == 0x01 ? 3 : 1; + int width = channelwidth * channels; + float resize = 1.0; + if (fpgaparam.DpiMode == 0x10) + { + if (config.g200params.dpi == 1) + resize = 2.07f; + else if (config.g200params.dpi == 2) + resize = 1.36667f; + } + auto phyHeight = paperHeight[(PaperSize)config.g200params.paper] * resize; + printf("\n ########## phyHeight = %d ", phyHeight); + int pixheight; // = ((int)((phyHeight / 25.4 * (dpi == 0x02 ? 300 : (dpi == 0x03 ? 600 : 200)) + 2) / 3)) * 3 * 2; + if (dunnancis) + { + int tdpi = config.g200params.dpi == 0x02 ? 300 : (config.g200params.dpi == 0x03 ? 600 : 200); + // int tdpi = config.g200params.dpi == 0x02 ? 285 : (config.g200params.dpi == 0x03 ? 570 : 190); + pixheight = ((int)((phyHeight / 25.4 * tdpi + 2) / 3)) * 3 * 2; + } + else + pixheight = ((int)((phyHeight / 25.4 * (config.g200params.dpi == 0x02 ? 300 : (config.g200params.dpi == 0x03 ? 600 : 200)) + 2) / 3) * 3) * 2; + + if (config.g200params.paper == (unsigned int)(PaperSize::G400_AUTO) || pixheight > 16380) // isp sup max height config 16383 + pixheight = 16380; + + int dstheight = pixheight; + + int fpgaheight = mode == 0x1 ? dstheight / 2 * 3 : dstheight / 2; // 彩色配置fpga 高度要为目标图像高度的3倍 + // fpgaparam = GetFpgaparam(config.g200params.dpi, mode);// == 0x02 ? 2 : (config.g200params.dpi == 0x03 ? 3 : 2) + // FPGAConfigParam fpgaparam = GetFpgaparam(dpi, mode); + printf("dpi = %d fpgaparam.sp=%d exp=%d gain=%d offset=%d LUT=%s \n", dpi, fpgaparam.Sp, fpgaparam.ExposureB[0], fpgaparam.GainB[0], fpgaparam.OffsetB[0], fpgaparam.LutPath.c_str()); + // int startsample= cistype.GetCisType()==CISVendor::DUNNAN_CIS_V0?205:262; + int startsample = 205; + uint tmp_vs = 0; + fpgaComm->read(15, tmp_vs); + if (tmp_vs == 0x9000c) + startsample = 201; + else if (tmp_vs >= 0x90002) + startsample = 205; + else + startsample = 208; + // if((fpgaparam.MaxExp > 50) && (fpgaparam.MaxExp < 1000)) + // startsample = fpgaparam.MaxExp; + ModeFpga fpgamod = { + .colorMode = mode, + .dpi = dpi, + .led = 1, + .sample = startsample, // 256+39 + .adcA = 0, + .adcB = 0, + .selftest = 0, + .sp = fpgaparam.Sp}; // 600DPI 0x1450 300DPI 0xe10 + fpgaComm->setRegs(0x01, *((int *)(&fpgamod))); + fpgaComm->setSample(startsample); + if (tmp_vs == 0x9000c) + fpgaComm->setVsp(66, 67); + else if (tmp_vs != 0x9000a) + fpgaComm->setVsp(1, 2); + else + { + fpgaComm->setVsp(40, 120); + } + fpgaComm->enableLed(true); + fpgaComm->setEnTestCol(false); + fpgaComm->setEnTestBit(false); + // fpgaComm->update(2); + configFPGAParam(mode, config.g200params.dpi); + // fpgaComm->update(3); + // fpgaComm->setFrameHeight(12); + // fpgaComm->capture(); + // auto data = video->read_frame(100); + // fpgaComm->enableLed(false); + video->open(width, dstheight); // 300dpi 7344/2 600dpi 7344 + printf("opened video with width = %d height = %d \n", width, dstheight); + fpgaComm->setFrameHeight(12); + for (int i = 0; i < 1; i++) + { + fpgaComm->capture(); // abort first frame + video->read_frame(100); + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + printf("abort first frame \n"); + } + fpgaComm->setFrameHeight(fpgaheight); + printf("fpgaComm set height = %d \n", fpgaheight); + fpgaComm->update(3); + // initLut(fpgaparam.LutPath, config.g200params.color); + init_lutdate(); + // initLut(m_config.g200params.is_textcorrect?m_fpgaparam.LutPath:m_fpgaparam.TextLutPath,m_config.g200params.color); +} + +void MonoCapturer::init_lutdate() +{ + DeviceConfig::Gray_Apply gray_; + gray_.value = Get_static_deviceconfig().GetParam().gray_param; + std::string lutpath = m_config.g200params.is_textcorrect?m_fpgaparam.LutPath:m_fpgaparam.TextLutPath; + if((m_fpgaparam.DpiMode == 1) && (gray_.Param_Setting.en_200_clr == 1 && m_config.g200params.color == true)) + lutpath = "/usr/local/huago/Graylut200clr.bmp"; + else if ((m_fpgaparam.DpiMode == 2) && (gray_.Param_Setting.en_300_clr == 1 && m_config.g200params.color == true)) + lutpath = "/usr/local/huago/Graylut300clr.bmp"; + else if ((m_fpgaparam.DpiMode == 3) && (gray_.Param_Setting.en_600_clr == 1 && m_config.g200params.color == true)) + lutpath = "/usr/local/huago/Graylut600clr.bmp"; + else if ((m_fpgaparam.DpiMode == 16) && (gray_.Param_Setting.en_slow_clr == 1 && m_config.g200params.color == true)) + lutpath = "/usr/local/huago/Graylutslow_moireclr.bmp"; + else if ((m_fpgaparam.DpiMode == 1) && (gray_.Param_Setting.en_200_gray == 1 && m_config.g200params.color == false)) + lutpath = "/usr/local/huago/Graylut200gray.bmp"; + else if ((m_fpgaparam.DpiMode == 2) && (gray_.Param_Setting.en_300_gray == 1 && m_config.g200params.color == false)) + lutpath = "/usr/local/huago/Graylut300gray.bmp"; + else if ((m_fpgaparam.DpiMode == 3) && (gray_.Param_Setting.en_600_gray == 1 && m_config.g200params.color == false)) + lutpath = "/usr/local/huago/Graylut600gray.bmp"; + else if ((m_fpgaparam.DpiMode == 16) && (gray_.Param_Setting.en_slow_gray == 1 && m_config.g200params.color == false)) + lutpath = "/usr/local/huago/Graylutslow_moiregray.bmp"; + initLut(lutpath, m_config.g200params.color); +} + +void MonoCapturer::close() +{ + if (video.get()) + video->close(); + // fpga_reload(); +} + +void MonoCapturer::start() +{ + if (video.get()) + video->start(); +} + +void MonoCapturer::MonoCapturer::stop() +{ + if (video.get()) + video->stop(); +} + +bool MonoCapturer::is_runing() +{ + return false; +} + +void MonoCapturer::snap() +{ + fpgaComm->capture(); +} + +void MonoCapturer::stopsnap() +{ +} + +int MonoCapturer::getautosizeheight() +{ + unsigned int val; + unsigned int reg8 = 0; + + fpgaComm->read(8, reg8); + + fpgaComm->read(14, val); + int regv = val; + val &= 0x0000ffff; + + fpgaComm->write(8, reg8 & 0xfffffff7); + + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + + fpgaComm->read(14, val); + regv = val; + val &= 0x0000ffff; + fpgaComm->read(8, reg8); + + std::cout << string_format("TWO height = %d reg[14] = %d \n", val, regv); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + fpgaComm->write(8, reg8 | 0x8); + + return val; +} +void MonoCapturer::set_size(int width, int height) +{ + if (video.get()) + video->set_size(width, height); +} + +void MonoCapturer::set_sp(int sp) +{ + fpgaComm->setSp(sp); +} + +void *MonoCapturer::readFrame(int timeout) +{ + return video->read_frame(timeout); +} + +void MonoCapturer::set_gain(int ix, int val) +{ + for (int i = 0; i < 6; i++) + { + if (ix) + fpgaComm->setAGain(i, val); + else + fpgaComm->setBGain(i, val); + } +} + +void MonoCapturer::set_offset(int ix, int val) +{ + for (int i = 0; i < 6; i++) + { + if (ix) + fpgaComm->setAOffset(i, val); + else + fpgaComm->setBOffset(i, val); + + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } +} + +void MonoCapturer::set_expo(int ix, int val) +{ + switch (ix) + { + case 0: + fpgaComm->setAExposureR(val); + break; + case 1: + fpgaComm->setAExposureG(val); + break; + case 2: + fpgaComm->setAExposureB(val); + break; + case 3: + fpgaComm->setBExposureR(val); + break; + case 4: + fpgaComm->setBExposureG(val); + break; + case 5: + fpgaComm->setBExposureB(val); + break; + default: + break; + } + std::this_thread::sleep_for(std::chrono::milliseconds(1)); +} + +std::shared_ptr MonoCapturer::regs() +{ + return fpgaComm; +} + +void MonoCapturer::reset() +{ + fpga_reset(); + // fpgaComm->resetADC(); + // fpgaComm->setDelayTime(0X3e8); + // fpgaComm->setRegs(0x00, fpgaComm->getRegs(0x00)); + // fpgaComm->setRegs(0x01, fpgaComm->getRegs(0x01)); +} + +int MonoCapturer::width() +{ + int dpi = fpgaComm->getDpi(); + int channel = 1; + int width = dpi == 0x02 ? 1296 * channel : (dpi == 0x03 ? (2592 * channel) : (864 * channel)); + // printf("get width = %d \n", width); + return width; +} + +int MonoCapturer::height() +{ + return fpgaComm->getFrameHeight(); +} + +int MonoCapturer::color() +{ + return fpgaComm->getColorMode() ? 16 : 0; +} + +void MonoCapturer::init_autocorrect(int colormode) +{ + std::thread t_correctthread = std::thread(&MonoCapturer::correctcolor, this, colormode); + t_correctthread.detach(); +} + +void MonoCapturer::configFPGAParam(int mode, int dpi) +{ + printf("dpi = %d mode = %d \n", dpi, mode); + + fpgaComm->resetADC(); + FPGAConfigParam fpgaparam = GetFpgaparam(dpi, mode); + // int offF[6]={0,0,0,0,0,200}; + // int offB[6]={0,0,0,0,0,0}; + for (int i = 0; i < 6; i++) + { + if (i < 3) + { + set_expo(i, fpgaparam.ExposureF[i]); + printf("fpgaparam.ExposureF[%d] = %d \n", i, fpgaparam.ExposureF[i]); + } + else + { + set_expo(i, fpgaparam.ExposureB[i % 3]); + printf("fpgaparam.ExposureB[%d] = %d \n", i, fpgaparam.ExposureB[i % 3]); + } + + std::this_thread::sleep_for(std::chrono::milliseconds(2)); + fpgaComm->setAOffset(i, fpgaparam.OffsetF[i]); + // fpgaComm->setAOffset(i,offF[i]); + printf("fpgaparam.setAOffset[%d] = %d \n", i, fpgaparam.OffsetF[i]); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + fpgaComm->setBOffset(i, fpgaparam.OffsetB[i]); + // fpgaComm->setBOffset(i, offB[i]); + printf("fpgaparam.OffsetB[%d] = %d \n", i, fpgaparam.OffsetB[i]); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + fpgaComm->setAGain(i, fpgaparam.GainF[i]); + printf("fpgaparam.GainF[%d] = %d \n", i, fpgaparam.GainF[i]); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + fpgaComm->setBGain(i, fpgaparam.GainB[i]); + printf("fpgaparam.GainB[%d] = %d \n", i, fpgaparam.GainB[i]); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + } +} + +void MonoCapturer::openDevice(int dpi, int mode) +{ + // reset_pin->setValue(Gpio::Low); + // std::this_thread::sleep_for(std::chrono::milliseconds(50)); + // reset_pin->setValue(Gpio::High);a + fpgaComm->read(15, m_fpgaversion); + int config_dpi = dpi != 3 ? 2 : dpi; + int channelwidth = config_dpi == 0x02 ? 1296 : (config_dpi == 0x03 ? 2592 : 864); + int channels = mode == 0x01 ? 3 : 1; + int width = channelwidth * channels; + int dstheight = 200; + int fpgaheight = mode == 0x1 ? dstheight / 2 * 3 : dstheight; // 彩色配置fpga 高度要为目标图像高度的3倍 + + FPGAConfigParam fpgaparam = GetFpgaparam(dpi, mode); + printf("fpgaparam.sp=%d exp=%d gain=%d offset=%d LUT=%s", fpgaparam.Sp, fpgaparam.ExposureB[0], fpgaparam.GainB[0], fpgaparam.OffsetB[0], fpgaparam.LutPath.c_str()); + // int startsample= cistype.GetCisType()==CISVendor::DUNNAN_CIS_V0?205:262; + int startsample = 205; + uint tmp_vs = 0; + fpgaComm->read(15, tmp_vs); + if (tmp_vs == 0x9000c) + startsample = 201; + else if (tmp_vs >= 0x90002) + startsample = 205; + else + startsample = 208; + + ModeFpga fpgamod = { + .colorMode = mode, + .dpi = config_dpi, + .led = 1, + .sample = startsample, // 256+39 + .adcA = 0, + .adcB = 0, + .selftest = 0, + .sp = fpgaparam.Sp}; // 600DPI 0x1450 300DPI 0xe10 + fpgaComm->setRegs(0x01, *((int *)(&fpgamod))); + fpgaComm->setSample(startsample); + fpgaComm->enableLed(true); + fpgaComm->setEnTestCol(false); + fpgaComm->setEnTestBit(false); + if (tmp_vs == 0x9000c) + fpgaComm->setVsp(66, 67); + else if (tmp_vs != 0x9000a) + fpgaComm->setVsp(1, 2); + else + { + // ifstream iF("/home/vspF"); + // ifstream iB("/home/vspB"); + // int vspF,vspB; + // iF >> vspF; + // iB >> vspB; + // if(vspF ==0 || vspB == 0) + // { + // vspF = 75; + // vspB = 85; + // } + // printf("!!!!!!!!!!! vspF=%d vspB = %d \n",vspF,vspB); + // fpgaComm->setVsp(vspF,vspB); + fpgaComm->setVsp(40, 120); + } + configFPGAParam(mode, dpi); + + video->open(width, dstheight); // 300dpi 7344/2 600dpi 7344 + printf("opened video with width = %d height = %d \n", width, dstheight); + fpgaComm->setFrameHeight(12); + for (int i = 0; i < 1; i++) + { + fpgaComm->capture(); // abort first frame + video->read_frame(100); + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + printf("abort first frame \n"); + } + fpgaComm->setFrameHeight(fpgaheight); +} + +void MonoCapturer::creatcorrectconfig(int dpi, int mode) +{ + openDevice(dpi, mode); + bool isDone = false; + int i = 1; + initStep1(); + + while (!isDone) // 先暗场 + { + string log = "==============================第" + to_string(i) + "次==============================="; + ft_log.append_log(log); + configFPGAParam(mode, dpi); + ft_log.append_log(log); + fpgaComm->enableLed(false); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + fpgaComm->capture(); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + isDone = saveLutImg(dpi, mode, true); // 0 color_black 1 color_white 2 gray_balck 3 gray_white + i++; + } + i = 1; + isDone = false; + initStep1(); + while (!isDone) // 后明场 + { + configFPGAParam(mode, dpi); + string log = "==============================第" + to_string(i) + "次==============================="; + ft_log.append_log(log); + fpgaComm->enableLed(true); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + fpgaComm->capture(); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + isDone = saveLutImg(dpi, mode, false); + i++; + } + printf("creatcorrectconfig %s \n", (mode == IMAGE_COLOR ? " Color" : " Gray")); + + // creatLUTData(dpi, mode); + video->close(); +} + +static int savelutindex = 0; +bool MonoCapturer::saveLutImg(int dpi, int mode, bool black) +{ + int config_dpi = dpi != 3 ? 2 : dpi; + int offset_indexs[] = {3, 4, 5, 2, 1, 0, 0, 1, 2, 5, 4, 3}; + int channels = mode == IMAGE_COLOR ? 3 : 1; + int height = 100; + int width = config_dpi == 0x02 ? 1296 : (config_dpi == 0x03 ? 2592 : 864); + int orgimgwidth = width * 2 * 3 * channels; + int dstwidth = width * 2 * 3; + bool isNeedSave = true; + string log; + void *data = video->read_frame(10000); + if (data == NULL) + { + isNeedSave = false; + log = "WARNNING WARNNING WARNNING FAILDED TO READ IMAGE DATA !!!!!!!!!!!!!!!!!!!\r\n"; + ft_log.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + return isNeedSave; + } + cv::Mat src(height, orgimgwidth, CV_8UC1, data); + // cv::imwrite(std::to_string(savelutindex++) + ".jpg", src); + CImageMerge t_marge; + cv::Mat mrgmat = t_marge.MergeImage(mode == 0x01, src, dstwidth, height, m_fpgaversion); + mrgmat = mrgmat(cv::Rect(0, 20, mrgmat.cols, mrgmat.rows - 20)); + // cv::imwrite(std::to_string(savelutindex++) + "mrg.jpg", mrgmat); + // return false; + FPGAConfigParam param = GetFpgaparam(dpi, mode); + + if (black) // 暗场 + { + double offValues[12]; + double offValues_min[12]; + std::vector bflags; + for (int n = 0; n < 2; n++) + { + cv::Mat img = mrgmat(cv::Rect(mrgmat.cols * n / 2, 10, mrgmat.cols / 2, mrgmat.rows - 10)).clone(); + int offset_total = 0; + for (int s = 0; s < 6; s++) // + { + int k = n * 6 + s; + int offset_wdth; + if ((k == 5) || (k == 6)) + { + offset_wdth = config_dpi == 0x03 ? 864 : (config_dpi == 0x02 ? 432 : 288); + } + else + { + offset_wdth = config_dpi == 0x03 ? 1296 : (config_dpi == 0x02 ? 648 : 432); + } + + double min, max; + // auto t_mat= img(cv::Rect(offset_total, 10, offset_wdth, img.rows - 10)); + // cv::minMaxLoc(t_mat,&min,&max); + cv::Scalar mean = cv::mean(img(cv::Rect(offset_total, 10, offset_wdth, img.rows - 10))); + if (mode) + { + auto tmp_mat = img(cv::Rect(offset_total, 10, offset_wdth, img.rows - 10)); + auto tmp = *std::min_element(tmp_mat.begin(), + tmp_mat.end(), [](cv::Vec3b a, cv::Vec3b b) -> bool + { return (a[0] + a[1] + a[2]) < (b[0] + b[1] + b[2]); }); + offValues_min[k] = (tmp[0] + tmp[1] + tmp[2]) / 3.0; + } + else + { + auto tmp_mat = img(cv::Rect(offset_total, 10, offset_wdth, img.rows - 10)); + offValues_min[k] = *std::min_element(tmp_mat.begin(), + tmp_mat.end(), [](std::uint8_t a, std::uint8_t b) -> bool + { return a < b; }); + } + + // printf("AAAAAAAAAAAAAAAAAAAAAAAAAAA min = %.2f max= %.2f mean = %0.2f \n",min,max); + offset_total += offset_wdth; + offValues[k] = mean.val[0]; + bflags.push_back(false); + // offValues[k] = min; + } + } + + // std::string clrmode = (mode == 0x01 ? "彩色" : " 灰度"); + // log = "开始" + clrmode + "暗场校正 \n"; + for (int s = 0; s < 2; s++) + { + int offsets[6]; // = (int *)(s == 0 ? ¶m.OffsetF[0] : ¶m.OffsetB[0]); + memcpy(offsets, (s == 0 ? ¶m.OffsetF[0] : ¶m.OffsetB[0]), sizeof(param.OffsetF)); + for (volatile int j = 0; j < 6; j++) + { + int k = s * 6 + j; + // double diff = BLACK_DIFF(offValues[k]); + double diff = 3 - offValues_min[k]; + if (offValues[k] > 25) + { + diff = 25 - offValues[k]; + } + + // double diff = 3-offValues[k]; + double step = radio * diff; + int preStep = offsetStep1[k]; + printf("offsetStep1[%d]=%d \n", k, offsetStep1[k]); + if (step * preStep < 0) + { + step = 0 - preStep / 2; + } + else + { + radio = 1; + } + + if (step < 1 && step > 0) + step = 1; + if (step < 0 && step > -1) + step = -1; + + // FMT_STEP(step); + bool isMinStep = abs(step) == 1 && step == offsetStep1[k]; + bool isOutBounds = offsets[j] >= 255 && step > 0; + isOutBounds |= offsets[j] <= 0 && step < 0; + log += " 暗场校正 :" + std::to_string(k) + ";diff:" + std::to_string(diff) + ";light:" + std::to_string(offValues[k]) + ";offset:" + std::to_string(offsets[j]) + ";step:" + std::to_string(step) + "\r\n"; + if (isOutBounds) + log += " 第" + std::to_string(k) + "条带暗场校正异常,暗场值无法降低 \r\n"; + else if (abs(step) > 1 || isMinStep) + { + offsetStep1[k] = (int)(step); + offsets[offset_indexs[k]] += step; + log += "offsetStep1" + std::to_string(k) + " = " + std::to_string(offsetStep1[k]) + ", offset_indexs" + std::to_string(k) + " =" + std::to_string(offset_indexs[k]) + "\r\n"; + + if (offsets[offset_indexs[k]] < 1) + offsets[offset_indexs[k]] = 1; + if (offsets[offset_indexs[k]] > 255) + offsets[offset_indexs[k]] = 255; + // isNeedSave = false; + bflags[k] = false; + } + else + { + bflags[k] = true; + printf("channel[%d] black correct done\n", k); + } + + log += (s == 0 ? "彩色正面" : "彩色背面"); + log += "偏移值:" + std::to_string(offsets[0]) + "," + std::to_string(offsets[1]) + "," + std::to_string(offsets[2]) + "," + std::to_string(offsets[3]) + "," + std::to_string(offsets[4]) + "," + std::to_string(offsets[5]) + "\r\n"; + // log += (s == 0 ? "彩色正面暗场校正完成 \r\n" : "彩色背面暗场校正完成 \r\n"); + ft_log.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + log = ""; + } + auto siez = sizeof(param.OffsetF); + memcpy((s == 0 ? ¶m.OffsetF[0] : ¶m.OffsetB[0]), offsets, sizeof(param.OffsetF)); + } + + for (int i = 0; i < bflags.size(); i++) + { + if (!bflags[i]) + isNeedSave = false; + } + + if (isNeedSave) + { + printf("Save LUT image path :%s \n", param.Flat_BwPath.c_str()); + log = "暗场校正完成 \r\n"; + if (m_captureCallback) + m_captureCallback(mode, log); + // log =""; + imwrite(param.Flat_BwPath, mrgmat); + } + } + else // 明场 + { + if (mode == IMAGE_COLOR) + { + double values[2][3]; + + cv::Scalar a = mean(mrgmat(Rect(0, 0, mrgmat.cols / 2, mrgmat.rows))); + cv::Scalar b = mean(mrgmat(Rect(mrgmat.cols / 2, 0, mrgmat.cols / 2, mrgmat.rows))); + for (int j = 0; j < 3; j++) + { + values[0][j] = a.val[2 - j]; + values[1][j] = b.val[2 - j]; + } + + log = "开始彩色明场校正 \r\n"; + if (m_captureCallback) + m_captureCallback(mode, log); + double coefficient[3] = {1.2, 0.6, 1.2}; + for (int s = 0; s < 2; s++) + { + int exposures[3]; // = (int *)(s == 0 ? param.ExposureF : param.ExposureB); + memcpy(exposures, (s == 0 ? ¶m.ExposureF[0] : ¶m.ExposureB[0]), sizeof(param.ExposureB)); + for (int x = 0; x < 3; x++) + { + int k = (3 * s + x); + int diff = LIGHT_DIFF(param.MaxBright, *((double *)values + k)); + if(x == 0) + diff = LIGHT_DIFF(175, *((double *)values + k)); + //int diff = LIGHT_DIFF(param.MaxBright,((values[s][0]*coefficient[0]+values[s][1]*coefficient[1]+values[s][2]*coefficient[2])/3.0)); + log += " 明场:" + std::to_string(k) + ";diff:" + std::to_string(diff) + "\r\n"; + if (abs(diff) > 30) + radio = 2; + else + radio = 1; + double step = diff * radio; + // double step = diff / coefficient[x]; + int preStep = *((int *)expStep + k); + if (step * preStep < 0) + { + step = 0 - preStep / 2; + } + if (step < 1 && step > 0) + step = 1; + if (step < 0 && step > -1) + step = -1; + + bool isMinStep = abs(step) == 1 && step == *((int *)expStep + k); + bool isOutBounds = exposures[x] >= (param.Sp - 5) && step > 0; + isOutBounds |= exposures[x] <= 0 && step < 0; + if (isOutBounds) + log += " 第" + to_string(x) + "个明场校正异常 \r\n"; + else if (abs(diff) >= 1 || isMinStep) + { + *((int *)expStep + k) = (int)(step); + exposures[x] += step; + if (exposures[x] > (param.Sp - 5)) + { + exposures[x] = (param.Sp - 5); + } + if (exposures[x] < 0) + exposures[x] = 0; + isNeedSave = false; + } + log += " 曝光值:" + to_string(exposures[x]) + "\r\n"; + log += " 调整步长:" + to_string(*((int *)expStep + k)) + "\r\n"; + } + memcpy((s == 0 ? ¶m.ExposureF[0] : ¶m.ExposureB[0]), exposures, sizeof(param.ExposureB)); + } + ft_log.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + + if (isNeedSave) + { + log = "彩色明场校正完成\r\n"; + if (m_captureCallback) + m_captureCallback(mode, log); + // log =""; + // imwrite("/home/linaro/"+to_string(dpi)+"color.jpg", mrgmat); + imwrite(param.Flat_WhitePath, mrgmat); + } + } + else + { + double values[2]; + values[0] = cv::mean(mrgmat(cv::Rect(0, 0, mrgmat.cols / 2, mrgmat.rows))).val[0]; + values[1] = cv::mean(mrgmat(cv::Rect(mrgmat.cols / 2, 0, mrgmat.cols / 2, mrgmat.rows))).val[0]; + log = "-----开始灰色明场校正-----\r\n"; + log += " 灰色扫描灰度明场均值:" + to_string(values[0]) + "," + to_string(values[1]) + "\r\n"; + if (m_captureCallback) + m_captureCallback(mode, log); + for (int s = 0; s < 2; s++) + { + int *exposures = (int *)(s == 0 ? param.ExposureF : param.ExposureB); + int diff = LIGHT_DIFF(param.MaxBright, values[s]); + if (abs(diff) > 30) + radio = 2; + else + radio = 1; + double step = diff * radio; + log += " 明场:" + to_string(s) + ";diff:" + to_string(diff) + "\r\n"; + int preStep = expStep[s][0]; + if (step * preStep < 0) + { + step = 0 - preStep / 2; + } + else + { + radio = 1; + } + if (step < 1 && step > 0) + step = 1; + if (step < 0 && step > -1) + step = -1; + + int exp = *(exposures + 1); + // std::string ss1(string_format("exp[%d] = %d step = %.3f \r\n", s, exp, step)); + // log += ss1; + bool isMinStep = abs(step) == 1 && step == expStep[s][0]; + bool isOutBounds = exp >= (param.Sp - 5) && step > 0; + isOutBounds |= exp <= 0 && step < 0; + if (isOutBounds) + log += " 第" + to_string(s) + "个明场校正异常 \r\n"; + else if (abs(diff) > 1 || isMinStep) + { + exp += step; + if (exp < 0) + exp = 0; + if (exp > (param.Sp - 5)) + exp = (param.Sp - 5); + + // float coffe[3] = {0.8, 1, 1}; // 0.2, 1,0.51 + float coffe[3] = {1, 1, 1}; + for (int k = 0; k < 3; k++) + { + *(exposures + k) = (int)(exp * coffe[k]); + expStep[s][k] = (int)(step); + std::string exps(string_format("expStep[%d][%d] = %.3f\r\n", s, k, step)); + log += exps; + std::string ss(string_format("exposures[%d] = %0.3f \r\n", k, exposures[k])); + log += ss; + } + isNeedSave = false; + } + } + ft_log.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + if (isNeedSave) + { + printf("Save LUT image path :%s \n", param.Flat_WhitePath.c_str()); + log = "灰度明场校正完成\r\n"; + if (m_captureCallback) + m_captureCallback(mode, log); + log = ""; + imwrite(param.Flat_WhitePath, mrgmat); + } + } + } + SaveFpgaparam(param); + printf("exit Save_lut \n"); + return isNeedSave; +} + +void MonoCapturer::correctcolor(int correctmode) +{ + auto _start = std::chrono::steady_clock::now(); + ThreadPool pool(2); + std::queue> fu_correct; + std::string loginfo = "Start Correctcolor 200DPI COLOR \r\n"; + if ((correctmode == 0) || (correctmode == 2)) + { + if (m_captureCallback) + m_captureCallback(0x01, loginfo); + creatcorrectconfig(0x01, IMAGE_COLOR); + auto param = GetFpgaparam(0x01, IMAGE_COLOR); + fu_correct.emplace(pool.enqueue([param]() + {creatLUTData(0x01,IMAGE_COLOR,param);creatLUTData_gray(0x01,IMAGE_COLOR,param); })); + loginfo = "-----------200DPI COLOR Correct Done----------- \r\n\r\n "; + if (m_captureCallback) + m_captureCallback(0x01, loginfo); + } + if ((correctmode == 0) || (correctmode == 1)) + { + loginfo = "Start Correctcolor 200DPI GRAY \r\n"; + if (m_captureCallback) + m_captureCallback(0x01, loginfo); + creatcorrectconfig(0x01, IMAGE_GRAY); + auto param = GetFpgaparam(0x01, IMAGE_GRAY); + fu_correct.emplace(pool.enqueue([param]() + {creatLUTData(0x01,IMAGE_GRAY,param);creatLUTData_gray(0x01,IMAGE_GRAY,param); })); + loginfo = "-----------200DPI Gray Correct Done----------- \r\n\r\n "; + if (m_captureCallback) + m_captureCallback(0x02, loginfo); + } + if ((correctmode == 0) || (correctmode == 4)) + { + loginfo = "Start Correctcolor 300DPI COLOR \r\n"; + if (m_captureCallback) + m_captureCallback(0x01, loginfo); + creatcorrectconfig(0x02, IMAGE_COLOR); + auto param = GetFpgaparam(0x02, IMAGE_COLOR); + fu_correct.emplace(pool.enqueue([param]() + {creatLUTData(0x02,IMAGE_COLOR,param);creatLUTData_gray(0x02,IMAGE_COLOR,param); })); + loginfo = "-----------300DPI COLOR Correct Done----------- \r\n\r\n "; + if (m_captureCallback) + m_captureCallback(0x02, loginfo); + } + if ((correctmode == 0) || (correctmode == 3)) + { + loginfo = "Start Correctcolor 300DPI GRAY \r\n"; + if (m_captureCallback) + m_captureCallback(0x01, loginfo); + creatcorrectconfig(0x02, IMAGE_GRAY); + auto param = GetFpgaparam(0x02, IMAGE_GRAY); + fu_correct.emplace(pool.enqueue([param]() + {creatLUTData(0x02,IMAGE_GRAY,param);creatLUTData_gray(0x02,IMAGE_GRAY,param); })); + loginfo = "-----------300DPI Gray Correct Done----------- \r\n\r\n "; + if (m_captureCallback) + m_captureCallback(0x03, loginfo); + } + if ((correctmode == 0) || (correctmode == 6)) + { + loginfo = "Start Correctcolor 600DPI COLOR \r\n"; + if (m_captureCallback) + m_captureCallback(0x01, loginfo); + creatcorrectconfig(0x03, IMAGE_COLOR); + auto param = GetFpgaparam(0x03, IMAGE_COLOR); + fu_correct.emplace(pool.enqueue([param]() + {creatLUTData(0x03,IMAGE_COLOR,param);creatLUTData_gray(0x03,IMAGE_COLOR,param); })); + loginfo = "-----------600DPI COLOR Correct Done----------- \r\n\r\n "; + if (m_captureCallback) + m_captureCallback(0x03, loginfo); + } + if ((correctmode == 0) || (correctmode == 5)) + { + loginfo = "Start Correctcolor 600DPI GRAY \r\n"; + if (m_captureCallback) + m_captureCallback(0x01, loginfo); + creatcorrectconfig(0x03, IMAGE_GRAY); + auto param = GetFpgaparam(0x03, IMAGE_GRAY); + fu_correct.emplace(pool.enqueue([param]() + {creatLUTData(0x03,IMAGE_GRAY,param);creatLUTData_gray(0x03,IMAGE_GRAY,param); })); + loginfo = "-----------600DPI Gray Correct Done----------- \r\n\r\n "; + if (m_captureCallback) + m_captureCallback(0x03, loginfo); + } + loginfo = "Start Correctcolor slow moire COLOR \r\n"; + if (m_captureCallback) + m_captureCallback(0x01, loginfo); + creatcorrectconfig(0x10, IMAGE_COLOR); + auto param = GetFpgaparam(0x10, IMAGE_COLOR); + fu_correct.emplace(pool.enqueue([param]() + {creatLUTData(0x10,IMAGE_COLOR,param);creatLUTData_gray(0x10,IMAGE_COLOR,param); })); + loginfo = "-----------slow moire COLOR Correct Done----------- \r\n\r\n "; + if (m_captureCallback) + m_captureCallback(0x10, loginfo); + + loginfo = "Start Correctcolor slow moire GRAY \r\n"; + if (m_captureCallback) + m_captureCallback(0x01, loginfo); + creatcorrectconfig(0x10, IMAGE_GRAY); + param = GetFpgaparam(0x10, IMAGE_GRAY); + fu_correct.emplace(pool.enqueue([param]() + {creatLUTData(0x10,IMAGE_GRAY,param);creatLUTData_gray(0x10,IMAGE_GRAY,param); })); + loginfo = "-----------slow moire Gray Correct Done----------- \r\n\r\n "; + if (m_captureCallback) + m_captureCallback(0x03, loginfo); + + if ((correctmode < 0) || (correctmode > 6)) + { + loginfo = "不支持的校正模式...\r\n"; + if (m_captureCallback) + m_captureCallback(0x03, loginfo); + } + while (fu_correct.size()) + { + fu_correct.front().get(); + fu_correct.pop(); + } + loginfo = "******Correct Done****** " + std::to_string(std::chrono::duration(std::chrono::steady_clock::now() - _start).count()) + "s"; + if (m_captureCallback) + m_captureCallback(0x04, loginfo); +} + +void MonoCapturer::single_correct(std::uint32_t mode) +{ + std::vector sup_correct_dpi{1, 2, 3, 0x10}; + union correct_mode_ + { + struct + { + uint32_t dpi : 16; + uint32_t color_mode : 8; + uint32_t correct_mode : 8; + } param; + uint32_t value; + }; + correct_mode_ tmp; + tmp.value = mode; + if (std::count(sup_correct_dpi.begin(), sup_correct_dpi.end(), tmp.param.dpi) && (tmp.param.color_mode < 2)) + { + auto param = GetFpgaparam(tmp.param.dpi, tmp.param.color_mode); + if (tmp.param.correct_mode == 1) + creatLUTData(tmp.param.dpi, tmp.param.color_mode, param); + else if (tmp.param.correct_mode == 2) + creatLUTData_gray(tmp.param.dpi, tmp.param.color_mode, param); + } +} + +void MonoCapturer::fpga_reset() +{ + reset_pin->setValue(Gpio::Low); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + reset_pin->setValue(Gpio::High); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); +} + +void MonoCapturer::fpga_reload() +{ + // fpga 代码重载 + fpgaLoad->setValue(Gpio::Low); + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + fpga_conf_initn->setValue(Gpio::Low); + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + printf("\n fpga_conf_done value %d", fpga_conf_done->getValue()); + fpgaLoad->setValue(Gpio::High); + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + fpga_conf_initn->setValue(Gpio::High); + // std::this_thread::sleep_for(std::chrono::milliseconds(5)); + printf("\n fpga_conf_done value %d", fpga_conf_done->getValue()); + // while(fpga_conf_done->getValue() == Gpio::GpioLevel::Low) + // std::this_thread::sleep_for(std::chrono::milliseconds(5)); + std::this_thread::sleep_for(std::chrono::seconds(3)); + printf("\n fpga_conf_done value %d", fpga_conf_done->getValue()); + fpgaComm->resetADC(); + fpgaComm->update(0); +} + +void MonoCapturer::set_fpga_vsp(int a, int b) +{ + fpgaComm->setVsp(a, b); +} diff --git a/capimage/MonoCapturer.h b/capimage/MonoCapturer.h new file mode 100644 index 0000000..3f7dc06 --- /dev/null +++ b/capimage/MonoCapturer.h @@ -0,0 +1,74 @@ +#pragma once +#include "ICapturer.h" + +class FpgaComm; +class gVideo; +class Gpio; + +class MonoCapturer : public ICapturer +{ +private: + /* data */ +public: + MonoCapturer(/* args */); + virtual ~MonoCapturer(); + virtual void open(); + virtual void open(HGScanConfig config, FPGAConfigParam fpgaparam); + virtual void close(); + virtual void start(); + virtual void stop(); + virtual bool is_runing(); + virtual void snap(); + virtual void stopsnap(); + virtual int getautosizeheight(); + virtual void set_size(int width, int height); + virtual void set_sp(int sp); + + virtual void *readFrame(int timeout); + + virtual void set_gain(int ix, int val); + virtual void set_offset(int ix, int val); + virtual void set_expo(int ix, int val); + + virtual std::shared_ptr regs(); + virtual void reset(); + virtual int width(); + virtual int height(); + virtual int color(); + virtual void init_autocorrect(int colormode); + virtual void setcapturecall(std::function callback) + { + m_captureCallback = callback; + }; + virtual void Fpga_regsAccess_reset(bool enable); + virtual void single_correct(std::uint32_t mode) override; + virtual void set_fpga_vsp(int a, int b); + +private: + void configFPGAParam(int mode, int dpi); + void openDevice(int dpi, int mode); + void creatcorrectconfig(int dpi, int mode); + bool saveLutImg(int dpi, int mode, bool black); + void correctcolor(int correctmode); + void fpga_reset(); + void fpga_reload(); + void init_lutdate(); + +private: + std::function m_captureCallback; + std::shared_ptr video; + std::shared_ptr vdd_cis_3voff_pin; + std::shared_ptr vdd_vis_5ven_pin; + std::shared_ptr reset_pin; + std::shared_ptr image_in_transfer_pin; + std::shared_ptr initDone_pin; + std::shared_ptr fpgaLoad; + std::shared_ptr fpgaComm; + std::shared_ptr fpga_conf_initn; + std::shared_ptr fpga_conf_done; + bool bcorrecting; + std::thread m_correctthread; + unsigned int m_fpgaversion; + HGScanConfig m_config; + FPGAConfigParam m_fpgaparam; +}; diff --git a/capimage/MultiFrameCapture.cpp b/capimage/MultiFrameCapture.cpp new file mode 100644 index 0000000..e1f4912 --- /dev/null +++ b/capimage/MultiFrameCapture.cpp @@ -0,0 +1,1587 @@ +#include "MonoCapturer.h" +#include "config.h" +#include "applog.h" +#include "gvideoisp1.h" +#include "Gpio.h" +#include "DevUtil.h" +#include "FpgaComm.h" +#include "CorrectParam.h" +#include "correct_ultis.h" +#include "stringex.hpp" +#include "filetools.h" +#include "CImageMerge.h" +#include "jsonconfig.h" +#include "MultiFrameCapture.h" +#include "StopWatch.h" +#include "linux\sched.h" +#include "deviceconfig.h" + +#define LOG_PATH "/usr/local/correct.log" + +const uint32_t WIDTH_8478 = 1224; +FileTools ftm_log(LOG_PATH); + +static std::string loggername = "MultiFrameCapture"; +static double radio = 1.0; +static int offsetStep1[12]; +static int expStep1[2][3]; +static int org_index = 0; +static void initStep1() +{ + printf("initStep aaaaaaaaaaa \n"); + for (int i = 0; i < 2; i++) + { + for (int j = 0; j < 3; j++) + { + expStep1[i][j] = 600; + } + } + for (int i = 0; i < 12; i++) + { + offsetStep1[i] = 256; + printf("offsetStep[%d]=%d \n", i, offsetStep1[i]); + } +} + +MultiFrameCapture::MultiFrameCapture() : reset_pin(new GpioOut(50)), + fpgaLoad(new Gpio(70)), + fpga_conf_done(new Gpio(69)), + fpga_conf_initn(new Gpio(71)), + bcorrecting(false), + snapthread(1) +{ + LOG_INIT(); + fpga_conf_done->setDirection(Gpio::in); + fpgaComm.reset(new FpgaComm()); + pimgdata_info = {0}; + + // fpga_reload(); + // fpga_reset(); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + // fpgaComm->resetADC(); + + // fpgaComm->resetADC(); + // fpgaComm->update(); + video.reset(new VIDEO_CLASS()); + // GetFpgaparam(0x01,0); + set_ADC_config_frequency(12); + init_adc_8478(); + + snapthread.enqueue([]{ + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET(5, &cpuset); + pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); }); +} + +MultiFrameCapture::~MultiFrameCapture() +{ + if (video.get()) + video.reset(); + + printf("Exit ~MultiFrameCapture() \n"); +} + +void MultiFrameCapture::open() +{ +} + +void MultiFrameCapture::open(HGScanConfig config, FPGAConfigParam_8478 fpgaparam) +{ + fpgaComm->update(3); + fpgaComm->set_8478_type(false); + uint32_t reg8 = 0, reg5 = 0, reg12 = 0, reg11 = 0, reg10 = 0, reg2 = 0; + + // fpgaComm->read(2,reg2); + // fpgaComm->write(2,(reg2&0xffffffe1)|0xc); // adc 配置 频率 + + set_ADC_config_frequency(12); + // init_adc_8478(); + + printf(" dpi = %d \n", config.g200params.dpi); + + fpgaComm->read(11, reg11); + fpgaComm->write(11, (reg11 & 0xffffffc0) | 0x12); + + // fpgaComm->write(13,0xdec0000); + fpgaComm->write(13, 0xce40000); // 旗标位 18 -27位 + + // fpgaComm->write(13,0xd680000); + + fpgaComm->set_cis_type(true); + m_config = config; + m_fpgaparam = fpgaparam; + + int dpi = config.g200params.dpi == 0x02 ? 2 : (config.g200params.dpi == 0x03 ? 3 : 1); + int mode = config.g200params.color; + int phyHeight = paperHeight[(PaperSize)config.g200params.paper]; + + if(m_gscancap.papertype == 52 || m_gscancap.papertype == 54) phyHeight = m_gscancap.maxszie_sanp_height; + + int tdpi = config.g200params.dpi == 0x02 ? 300 : (config.g200params.dpi == 0x03 ? 600 : 200); + int pixheight = ((int)((phyHeight / 25.4 * tdpi + 2) / 3)) * 3; + if (fpgaparam.DpiMode == 0x10) + pixheight = pixheight * 185 / 100; + if (fpgaparam.DpiMode == 0x11) + pixheight = pixheight * 130 / 100; + frame_height = 300; + frame_count = ceil((mode == 0x01 ? pixheight * 3 : pixheight) / (float)(frame_height)); // 彩色配置fpga 高度要为目标图像高度的3倍 + if (frame_height * frame_count > FPGA_MAX_HEIGHT_SUP) + frame_count = FPGA_MAX_HEIGHT_SUP / frame_height; + fpgaComm->read(15, m_fpgaversion); + int startsample = 0; + ModeFpga fpgamod = { + .colorMode = mode, + .dpi = m_config.g200params.dpi, + .led = 1, + .sample = startsample, // 256+39 + .adcA = 0, + .adcB = 0, + .selftest = 0, + .sp = fpgaparam.Sp}; // 600DPI 0x1450 300DPI 0xe10 10138 + fpgaComm->setRegs(0x01, *((int *)(&fpgamod))); + fpgaComm->setSample(startsample); + fpgaComm->enableLed(true); + fpgaComm->setEnTestCol(false); + fpgaComm->setEnTestBit(false); + set_LED_PTN_8478(config.g200params.color == false); + set_dpi_mode(config.g200params.dpi == 3); + set_pixel_count_8478(fpgaparam.Sp / 3 / (config.g200params.color ? 3 : 1), config.g200params.color == false); + configFPGAParam(config.g200params.color, config.g200params.dpi); + configFPGAParam_digital_gain(config.g200params.color, config.g200params.dpi); + set_exp_8478_single(fpgaparam.ExposureF[0], fpgaparam.ExposureF[1], fpgaparam.ExposureF[2], fpgaparam.Sp / (config.g200params.color ? 3 : 1), true, config.g200params.color); + set_exp_8478_single(fpgaparam.ExposureB[0], fpgaparam.ExposureB[1], fpgaparam.ExposureB[2], fpgaparam.Sp / (config.g200params.color ? 3 : 1), false, config.g200params.color); + + // set_exp_8478_single(1000,1000,1000,fpgaparam.Sp/(config.g200params.color?3:1),true,config.g200params.color); + // set_exp_8478_single(1000,1000,1000,fpgaparam.Sp/(config.g200params.color?3:1),false,config.g200params.color); + + config.g200params.dpi == 3 ? set_EN_postion(0x41, 0x3a0) : set_EN_postion(0x41, 0x1f0); + + // video->set_buf_count(std::min(frame_count,20u)); + video->set_buf_count(std::min(100u,frame_count)); + uint32_t video_w = (config.g200params.dpi == 0x03 ? WIDTH_8478 * 2 : WIDTH_8478); + if (config.g200params.dpi == 0x01) + video_w = video_w * 2 / 3; + video->open(video_w, frame_height * 2); + fpgaComm->setFrameHeight(frame_height); + printf("fpgaComm set height = %d \n", frame_height); + fpgaComm->read(8, reg8); + + // fpgaComm->write(8,reg8|0x100); //行号 enable + fpgaComm->write(8, reg8 & 0xfffffeff); // 行号 disable + fpgaComm->read(5, reg5); + // fpgaComm->write(5,reg5|0x2000); //测试数据 白+黑 enable + fpgaComm->write(5, reg5 & 0xffffdfff); // 测试数据 白+黑 disable + // fpgaComm->write(5, reg5 | 0x800); // 测试数据 test_en + + fpgaComm->read(12, reg12); + // fpgaComm->write(12,reg5&0xfffff000+0x97e); //帧间隔延迟 >=22.5us + // fpgaComm->write(12,reg5&0xe000e000+0xfa0067e); //帧间隔延迟 >=22.5us + // fpgaComm->write(12,0x04e20400); //0x494e491 0x79de496 范围 0-12 16-28 (16-28 > 0-12) + + fpgaComm->read(10, reg10); + fpgaComm->write(12, 0x00200010); // 58us 300*600 多帧 + + fpgaComm->write(10, 0x0150012a); // 58us 300*600 多帧 + + fpgaComm->setFrameNum(1); + + fpgaComm->capture(); // abort first frame + video->read_frame(1000); + fpgaComm->setFrameNum(frame_count); + + fpgaComm->update(3); + // initLut(fpgaparam.LutPath, config.g200params.color); + // initLut(config.g200params.is_textcorrect?fpgaparam.LutPath:fpgaparam.TextLutPath,config.g200params.color); + // initLut(fpgaparam.TextLutPath, config.g200params.color); + init_lutdate(); + // init_imagedatabuffer(); +} + +void MultiFrameCapture::init_lutdate() +{ + DeviceConfig::Gray_Apply gray_; + gray_.value = Get_static_deviceconfig().GetParam().gray_param; + std::string lutpath = m_config.g200params.is_textcorrect ? m_fpgaparam.LutPath : m_fpgaparam.TextLutPath; + if ((m_fpgaparam.DpiMode == 1) && (gray_.Param_Setting.en_200_clr == 1 && m_config.g200params.color == true)) + lutpath = "/usr/local/huago/Graylut200clr.bmp"; + else if ((m_fpgaparam.DpiMode == 2) && (gray_.Param_Setting.en_300_clr == 1 && m_config.g200params.color == true)) + lutpath = "/usr/local/huago/Graylut300clr.bmp"; + else if ((m_fpgaparam.DpiMode == 3) && (gray_.Param_Setting.en_600_clr == 1 && m_config.g200params.color == true)) + lutpath = "/usr/local/huago/Graylut600clr.bmp"; + else if ((m_fpgaparam.DpiMode == 16) && (gray_.Param_Setting.en_slow_clr == 1 && m_config.g200params.color == true)) + lutpath = "/usr/local/huago/Graylutslow_moireclr.bmp"; + else if ((m_fpgaparam.DpiMode == 17) && (gray_.Param_Setting.en_slow_300_clr == 1 && m_config.g200params.color == true)) + lutpath = "/usr/local/huago/Graylutslow_moire300clr.bmp"; + else if ((m_fpgaparam.DpiMode == 32) && (gray_.Param_Setting.en_long_Manuscript_200_clr == 1 && m_config.g200params.color == true)) + lutpath = "/usr/local/huago/GraylutLong_Manuscript200clr.bmp"; + else if ((m_fpgaparam.DpiMode == 33) && (gray_.Param_Setting.en_long_Manuscript_300_clr == 1 && m_config.g200params.color == true)) + lutpath = "/usr/local/huago/GraylutLong_Manuscript300clr.bmp"; + else if ((m_fpgaparam.DpiMode == 1) && (gray_.Param_Setting.en_200_gray == 1 && m_config.g200params.color == false)) + lutpath = "/usr/local/huago/Graylut200gray.bmp"; + else if ((m_fpgaparam.DpiMode == 2) && (gray_.Param_Setting.en_300_gray == 1 && m_config.g200params.color == false)) + lutpath = "/usr/local/huago/Graylut300gray.bmp"; + else if ((m_fpgaparam.DpiMode == 3) && (gray_.Param_Setting.en_600_gray == 1 && m_config.g200params.color == false)) + lutpath = "/usr/local/huago/Graylut600gray.bmp"; + else if ((m_fpgaparam.DpiMode == 16) && (gray_.Param_Setting.en_slow_gray == 1 && m_config.g200params.color == false)) + lutpath = "/usr/local/huago/Graylutslow_moiregray.bmp"; + else if ((m_fpgaparam.DpiMode == 17) && (gray_.Param_Setting.en_slow_300_gray == 1 && m_config.g200params.color == false)) + lutpath = "/usr/local/huago/Graylutslow_moire300gray.bmp"; + else if ((m_fpgaparam.DpiMode == 32) && (gray_.Param_Setting.en_long_Manuscript_200_gray == 1 && m_config.g200params.color == false)) + lutpath = "/usr/local/huago/GraylutLong_Manuscript200gray.bmp"; + else if ((m_fpgaparam.DpiMode == 33) && (gray_.Param_Setting.en_long_Manuscript_300_gray == 1 && m_config.g200params.color == false)) + lutpath = "/usr/local/huago/GraylutLong_Manuscript300gray.bmp"; + initLut(lutpath, m_config.g200params.color); +} + +void MultiFrameCapture::close() +{ + if (video.get()) + video->close(); + // if(pimgdata_info.pdata) free(pimgdata_info.pdata); + // pimgdata_info.pdata = nullptr; + pimgdata_info.offset = pimgdata_info.frame_count = pimgdata_info.img_h = pimgdata_info.img_w = 0; + printf("pimgdata_ free !!!!!\n"); + + // fpgaComm->resetADC(); + // fpga_reload(); +} + +void MultiFrameCapture::Fpga_regsAccess_reset(bool enable) +{ + if (fpgaComm.get()) + fpgaComm->regsAccess_reset(enable); + if (enable) + { + set_ADC_config_frequency(12); + init_adc_8478(); + } +} + +void MultiFrameCapture::start() +{ + if (video.get()) + video->start(); +} + +void MultiFrameCapture::MultiFrameCapture::stop() +{ + if (video.get()) + video->stop(); +} + +bool MultiFrameCapture::is_runing() +{ + return false; +} + +// static void printlog(std::string str) +// { +// std::ofstream o("/root/log.txt",std::ios::app|std::ios::binary); +// if(o.is_open()) +// { +// o << str <capture(); + printf("snap start !!!!! \n"); + b_stop_snap = false; + pimgdata_info.offset = pimgdata_info.frame_count = + pimgdata_info.img_h = pimgdata_info.img_w = 0; + snap_fu = snapthread.enqueue([this] + { + auto snap_func = [this](int height,int width, int channels, bool last_frame, unsigned int frame_index) + { + StopWatch sw; + void *data = video->read_frame(500); + if (data) + { + update_imgdatainfo(data,height,width); + printf("memcpy date size = %d times = %f index = %d \n",height*width,sw.elapsed_ms(),frame_index); + } + else + { + printf("!!!!!!!!!! error read frame losted, i = %d \n", frame_index); + //printlog("!!!!!!!!!! error read frame losted"); + } + }; + int width = WIDTH_8478*3*2*(m_config.g200params.dpi == 3 ? 2 : 1)*(m_config.g200params.color ? 3 :1); + if(m_config.g200params.dpi == 1) + width = width *2/3; + int height = frame_height/(m_config.g200params.color ? 3 :1); + for (int i = 1; i <= frame_count; i++) + { + curr_frame_snap_index = i; + snap_func(height,width, 0, (i == frame_count), i); + if (b_stop_snap) + { + int snaped_frame_count = fpgaComm->getFrame_counter_val(); + printf("!!!!!!!!!! revsed frame count = %d i = %d \n", snaped_frame_count, i); + if (snaped_frame_count > i && snaped_frame_count > 0) // 正常情况下 snaped_frame_count 一定大于0 + { + int reversed_frame_count = snaped_frame_count - i; + for (int j = 1; j <= reversed_frame_count; j++) + { + curr_frame_snap_index =j+i; + snap_func(height, width,0, ((i + j) == reversed_frame_count), i + j); + } + } + break; // 跳出当前读取多帧循环 + } + } + printf("snap end !!!!! \n"); }); +} + +void MultiFrameCapture::snap(frame_data_info info) +{ + printf("snap start !!!!! \n"); + b_stop_snap = false; + info.offset = info.frame_count = info.img_h = info.img_w = 0; + snap_fu = snapthread.enqueue([this, info]{ + frame_data_info frame_info {0}; + frame_info.pdata = info.pdata; + frame_info.total = info.total; + auto snap_func = [this,&frame_info](int height,int width, int channels, bool last_frame, unsigned int frame_index) + { + StopWatch sw; + void *data = video->read_frame(500); + if (data) + { + update_imgdatainfo(data,frame_info,height,width); + printf("memcpy date size = %d times = %f index = %d \n",height*width,sw.elapsed_ms(),frame_index); + } + else + printf("!!!!!!!!!! error read frame losted, i = %d \n", frame_index); + + }; + int width = WIDTH_8478*3*2*(m_config.g200params.dpi == 3 ? 2 : 1)*(m_config.g200params.color ? 3 :1); + if(m_config.g200params.dpi == 1) + width = width *2/3; + int height = frame_height/(m_config.g200params.color ? 3 :1); + for (int i = 1; i <= frame_count; i++) + { + curr_frame_snap_index = i; + snap_func(height,width, 0, (i == frame_count), i); + if (b_stop_snap) + { + int snaped_frame_count = fpgaComm->getFrame_counter_val(); + printf("!!!!!!!!!! revsed frame count = %d i = %d \n", snaped_frame_count, i); + if (snaped_frame_count > i && snaped_frame_count > 0) // 正常情况下 snaped_frame_count 一定大于0 + { + int reversed_frame_count = snaped_frame_count - i; + for (int j = 1; j <= reversed_frame_count; j++) + { + curr_frame_snap_index = i+j; + snap_func(height, width,0, ((i + j) == reversed_frame_count), i + j); + } + } + break; // 跳出当前读取多帧循环 + } + } + pimgdata_info = frame_info; + printf("snap end !!!!! \n"); }); +} + +cv::Size MultiFrameCapture::frame_data_size() +{ + return {2 * this->width() * (m_config.g200params.color ? 3 : 1), frame_height / (m_config.g200params.color ? 3 : 1) * frame_count}; +} + +void MultiFrameCapture::stopsnap() +{ + b_stop_snap = true; + if(snap_fu.valid()) snap_fu.get(); +} + +int MultiFrameCapture::getautosizeheight() +{ + unsigned int val; + unsigned int reg8 = 0; + + fpgaComm->read(8, reg8); + // std::cout << "1 reg[8]:" << string_format("0x%08x", reg8) << std::endl; + // fpgaComm->update(4); + fpgaComm->read(14, val); + int regv = val; + val &= 0x0000ffff; + // std::cout << string_format("ONE height = %d reg[14] = %d \n", val, regv); + // fpgaComm->update(5); + fpgaComm->write(8, reg8 & 0xfffffff7); + // std::cout << string_format("ONE reg[8] = %d \n", reg8 & 0xfffffff7); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + // fpgaComm->update(6); + fpgaComm->read(14, val); + regv = val; + val &= 0x0000ffff; + fpgaComm->read(8, reg8); + // std::cout << "2 reg[8]:" << string_format("0x%08x", reg8) << std::endl; + std::cout << string_format("TWO height = %d reg[14] = %d \n", val, regv); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + fpgaComm->write(8, reg8 | 0x8); + // fpgaComm->write(8,0x02260008); + // fpgaComm->update(7); + // fpgaComm->read(8, reg8); + // std::cout << "2 reg[8]:" << string_format("0x%08x", reg8) << std::endl; + return val; + + // return fpgaComm->getFrameHeight(); +} +void MultiFrameCapture::set_size(int width, int height) +{ + if (video.get()) + video->set_size(width, height); +} + +void MultiFrameCapture::set_sp(int sp) +{ + fpgaComm->setSp(sp); +} + +void *MultiFrameCapture::readFrame(int timeout) +{ + return video->read_frame(timeout); +} + +cv::Mat MultiFrameCapture::read_one_frame() +{ + fpgaComm->setFrameNum(1); + fpgaComm->capture(); + void *data = video->read_frame(1000); + fpgaComm->setFrameNum(frame_count); + if (data) + { + int width = WIDTH_8478 * 3 * 2 * (m_config.g200params.dpi == 3 ? 2 : 1) * (m_config.g200params.color ? 3 : 1); + if (m_config.g200params.dpi == 1) + width = width * 2 / 3; + int height = frame_height / (m_config.g200params.color ? 3 : 1); + cv::Mat mat(height, width, CV_8UC1, data); + return merge_8478(mat, m_config.g200params.color, 0); + } + else + return cv::Mat(); +} + +frame_data_info MultiFrameCapture::ReadMultiFrame(int state) +{ + printf(" ReadMultiFrame state : %d \n", state); + if (state & 1) + b_stop_snap = true; + if (snap_fu.valid()) + snap_fu.get(); + if ((state & 0x2) || (!pimgdata_info.pdata)) + return {0}; + return pimgdata_info; +} + +void MultiFrameCapture::set_gain(int ix, int val) +{ + for (int i = 0; i < 6; i++) + { + if (ix) + fpgaComm->setAGain(i, val); + else + fpgaComm->setBGain(i, val); + } +} + +void MultiFrameCapture::set_offset(int ix, int val) +{ + for (int i = 0; i < 6; i++) + { + if (ix) + fpgaComm->setAOffset(i, val); + else + fpgaComm->setBOffset(i, val); + + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } +} + +void MultiFrameCapture::set_expo(int ix, int val) +{ + switch (ix) + { + case 0: + fpgaComm->setAExposureR(val); + break; + case 1: + fpgaComm->setAExposureG(val); + break; + case 2: + fpgaComm->setAExposureB(val); + break; + case 3: + fpgaComm->setBExposureR(val); + break; + case 4: + fpgaComm->setBExposureG(val); + break; + case 5: + fpgaComm->setBExposureB(val); + break; + default: + break; + } + std::this_thread::sleep_for(std::chrono::milliseconds(1)); +} + +std::shared_ptr MultiFrameCapture::regs() +{ + return fpgaComm; +} + +void MultiFrameCapture::reset() +{ + fpga_reset(); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + fpgaComm->resetADC(); + // fpgaComm->setDelayTime(0X3e8); + // fpgaComm->setRegs(0x00, fpgaComm->getRegs(0x00)); + // fpgaComm->setRegs(0x01, fpgaComm->getRegs(0x01)); +} + +int MultiFrameCapture::width() +{ + // int dpi = fpgaComm->getDpi(); + // int channel = 1; + // int width = dpi == 0x02 ? 1296 * channel : (dpi == 0x03 ? (2592 * channel) : (864 * channel)); + // printf("get width = %d \n", width); + // return width; + uint32_t width = WIDTH_8478 * 3 * (m_config.g200params.dpi == 3 ? 2 : 1); + return m_config.g200params.dpi == 1 ? (width * 2 / 3) : width; +} + +int MultiFrameCapture::height() +{ + return fpgaComm->getFrameHeight(); +} + +int MultiFrameCapture::color() +{ + return fpgaComm->getColorMode() ? 16 : 0; +} + +void MultiFrameCapture::init_autocorrect(int colormode) +{ + std::thread t_correctthread = std::thread(&MultiFrameCapture::correctcolor, this, colormode); + t_correctthread.detach(); + // if(t_correctthread.joinable()) + // t_correctthread.join(); +} + +void MultiFrameCapture::configFPGAParam(int mode, int dpi) +{ + printf("dpi = %d mode = %d \n", dpi, mode); + FPGAConfigParam_8478 fpgaparam = Get_Static_CorrectParam().GetFpgaparam_8478(dpi, mode); + for (int i = 0; i < 9; i++) + { + set_digital_offset_8478(i, fpgaparam.OffsetF_R[i], fpgaparam.OffsetB_R[i], 0); + set_digital_offset_8478(i, fpgaparam.OffsetF_G[i], fpgaparam.OffsetB_G[i], 1); + set_digital_offset_8478(i, fpgaparam.OffsetF_B[i], fpgaparam.OffsetB_B[i], 2); + printf("\n OffsetF_R[%d] = %d OffsetF_G[%d] = %d OffsetF_B[%d] = %d ", i, fpgaparam.OffsetF_R[i], + i, fpgaparam.OffsetF_G[i], i, fpgaparam.OffsetF_B[i]); + printf("\n OffsetB_R[%d] = %d OffsetB_G[%d] = %d OffsetB_B[%d] = %d ", i, fpgaparam.OffsetB_R[i], + i, fpgaparam.OffsetB_G[i], i, fpgaparam.OffsetB_B[i]); + } +} + +void MultiFrameCapture::configFPGAParam_digital_gain(int mode, int dpi) +{ + FPGAConfigParam_8478 fpgaparam = Get_Static_CorrectParam().GetFpgaparam_8478(dpi, mode); + for (int i = 0; i < 9; i++) + { + set_digital_gain_8478(i, fpgaparam.GainF_R[i], fpgaparam.GainB_R[i], 0); + set_digital_gain_8478(i, fpgaparam.GainF_G[i], fpgaparam.GainB_G[i], 1); + set_digital_gain_8478(i, fpgaparam.GainF_B[i], fpgaparam.GainB_B[i], 2); + printf("\n GainF_R[%d] = %d GainF_G[%d] = %d GainF_B[%d] = %d ", i, fpgaparam.GainF_R[i], + i, fpgaparam.GainF_G[i], i, fpgaparam.GainF_B[i]); + printf("\n GainB_R[%d] = %d GainB_G[%d] = %d GainB_B[%d] = %d ", i, fpgaparam.GainB_R[i], + i, fpgaparam.GainB_G[i], i, fpgaparam.GainB_B[i]); + } +} + +void MultiFrameCapture::openDevice(int dpi, int mode) +{ + FPGAConfigParam_8478 fpgaparam = Get_Static_CorrectParam().GetFpgaparam_8478(dpi, mode); + + if (dpi == 0x10 || dpi == 0x20) + dpi = 1; + if (dpi == 0x11 || dpi == 0x21) + dpi = 2; + int channelwidth = dpi == 0x02 ? WIDTH_8478 : (dpi == 0x03 ? WIDTH_8478 * 2 : WIDTH_8478 * 2 / 3); + int channels = mode == 0x01 ? 3 : 1; + int width = channelwidth * channels; + fpgaComm->set_8478_type(false); + set_ADC_config_frequency(12); + init_adc_8478(); + uint32_t reg11 = 0, reg8 = 0, reg5 = 0, reg10 = 0, reg12 = 0; + fpgaComm->read(11, reg11); + fpgaComm->write(11, (reg11 & 0xffffffc0) | 0x12); + + // fpgaComm->write(13,0xdec0000); + fpgaComm->write(13, 0xce40000); // 旗标位 18 -27位 + + // fpgaComm->write(13,0xd680000); + + video->set_buf_count(10); + fpgaComm->set_cis_type(true); + + set_LED_PTN_8478(mode == false); + set_dpi_mode(dpi == 3); + dpi == 3 ? set_EN_postion(0x41, 0x3a0) : set_EN_postion(0x41, 0x1f0); + set_pixel_count_8478(fpgaparam.Sp / 3 / (mode ? 3 : 1), mode == false); + + frame_height = 300; + frame_count = 1; // 最后一帧丢帧,多采集一帧防止图像数据缺失 + fpgaComm->read(15, m_fpgaversion); + int startsample = 0; + ModeFpga fpgamod = { + .colorMode = mode, + .dpi = dpi, + .led = 1, + .sample = startsample, // 256+39 + .adcA = 0, + .adcB = 0, + .selftest = 0, + .sp = fpgaparam.Sp}; // 600DPI 0x1450 300DPI 0xe10 10138 + fpgaComm->setRegs(0x01, *((int *)(&fpgamod))); + fpgaComm->setSample(startsample); + fpgaComm->enableLed(true); + fpgaComm->setEnTestCol(false); + fpgaComm->setEnTestBit(false); + uint32_t video_w = dpi == 0x03 ? WIDTH_8478 * 2 : (dpi == 1 ? WIDTH_8478 * 2 / 3 : WIDTH_8478); + video->open(video_w, frame_height * 2); + fpgaComm->setFrameNum(frame_count); + fpgaComm->setFrameHeight(frame_height); + printf("fpgaComm set height = %d \n", frame_height); + fpgaComm->read(8, reg8); + // fpgaComm->write(8,reg8|0x100); //行号 enable + fpgaComm->write(8, reg8 & 0xfffffeff); // 行号 disable + fpgaComm->read(5, reg5); + // fpgaComm->write(5,reg5|0x2000); //测试数据 白+黑 enable + fpgaComm->write(5, reg5 & 0xffffdfff); // 测试数据 白+黑 disable + fpgaComm->read(12, reg12); + fpgaComm->read(10, reg10); + // if(dpi == 3){ + // fpgaComm->write(10,0x03b0037a); //120 us 600*600 多帧 + // fpgaComm->write(12,0x02000100); //120 us 600*600 多帧 + // } + // else + { + fpgaComm->write(12, 0x00200010); // 58us 300*600 多帧 + fpgaComm->write(10, 0x0150012a); // 58us 300*600 多帧 + } + configFPGAParam(mode, dpi); + configFPGAParam_digital_gain(mode,dpi); + fpgaComm->update(3); + fpgaComm->capture(); // abort first frame + for (int i = 0; i < frame_count; i++) + video->read_frame(500); +} + +void MultiFrameCapture::creatcorrectconfig(int dpi, int mode) +{ + printf(" opendevice"); + openDevice(dpi, mode); + printf(" opendevice end "); + bool isDone = false; + int i = 1; + initStep1(); + set_led_off(); + while (!isDone) // 先暗场 + { + std::string log = "==============================第" + std::to_string(i) + "次==============================="; + ftm_log.append_log(log); + configFPGAParam(mode, dpi); + configFPGAParam_digital_gain(mode,dpi); + ftm_log.append_log(log); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + fpgaComm->capture(); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + isDone = saveLutImg(dpi, mode, true); // 0 color_black 1 color_white 2 gray_balck 3 gray_white + i++; + } + i = 1; + isDone = false; + + initStep1(); + while (!isDone) // 后明场 + { + FPGAConfigParam_8478 fpgaparam = Get_Static_CorrectParam().GetFpgaparam_8478(dpi, mode); + set_exp_8478_single(fpgaparam.ExposureF[0], fpgaparam.ExposureF[1], fpgaparam.ExposureF[2], fpgaparam.Sp / (mode ? 3 : 1), true, mode); + set_exp_8478_single(fpgaparam.ExposureB[0], fpgaparam.ExposureB[1], fpgaparam.ExposureB[2], fpgaparam.Sp / (mode ? 3 : 1), false, mode); + std::string log = "==============================第" + std::to_string(i) + "次==============================="; + ftm_log.append_log(log); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + fpgaComm->capture(); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + isDone = saveLutImg(dpi, mode, false); + i++; + } + printf("creatcorrectconfig %s \n", (mode == IMAGE_COLOR ? " Color" : " Gray")); + // creatLUTData(dpi, mode); + video->close(); +} + +static int savelutindex = 0; +bool MultiFrameCapture::saveLutImg(int dpi, int mode, bool black) +{ + FPGAConfigParam_8478 param = Get_Static_CorrectParam().GetFpgaparam_8478(dpi, mode); + if (dpi == 0x10 || dpi == 0x20) + dpi = 1; + if (dpi == 0x11 || dpi == 0x21) + dpi = 2; + int offset_indexs[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8}; + int width = WIDTH_8478 * 3 * 2 * (dpi == 3 ? 2 : 1) * (mode ? 3 : 1); + if (dpi == 1) + width = width * 2 / 3; + int height = frame_height / (mode ? 3 : 1); + + bool isNeedSave = true; + std::string log; + void *data = video->read_frame(10000); + if (data == NULL) + { + isNeedSave = false; + log = "WARNNING WARNNING WARNNING FAILDED TO READ IMAGE DATA !!!!!!!!!!!!!!!!!!!\r\n"; + ftm_log.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + return isNeedSave; + } + cv::Mat src(height, width, CV_8UC1, data); + // cv::imwrite(std::to_string(savelutindex++) + ".jpg", src); + + CImageMerge t_marge; + // cv::Mat mrgmat = t_marge.MergeImage(mode == 0x01, src, dstwidth, height,m_fpgaversion); + cv::Mat mrgmat = merge_8478(src, mode, 0); + mrgmat = mrgmat(cv::Rect(0, 10, mrgmat.cols, mrgmat.rows - 20)); + // cv::imwrite("correct.bmp",mrgmat); + // return false; + + if (black) // 暗场 + { + double offValues_R[18]{0}; + double offValues_G[18]{0}; + double offValues_B[18]{0}; + std::vector bflags(2 * 9 * (mode ? 3 : 1), false); + for (volatile int n = 0; n < 2; n++) + { + cv::Mat img = mrgmat(cv::Rect(mrgmat.cols * n / 2, 10, mrgmat.cols / 2, mrgmat.rows - 10)).clone(); + int offset_total = 0; + for (volatile int s = 0; s < 9; s++) // + { + int k = n * 9 + s; + int offset_wdth; + if ((k == 8) || (k == 17)) + offset_wdth = dpi == 0x03 ? 432 : (dpi == 0x02 ? 216 : 144); + else + offset_wdth = dpi == 0x03 ? 864 : (dpi == 0x02 ? 432 : 288); + cv::Scalar mean = cv::mean(img(cv::Rect(offset_total, 10, offset_wdth, img.rows - 10))); + + if (mode) + { + offValues_R[k] = mean.val[0]; + offValues_G[k] = mean.val[1]; + offValues_B[k] = mean.val[2]; + + // auto tmp_mat = img(cv::Rect(offset_total, 10, offset_wdth, img.rows - 10)); + // offValues_R[k] = (*std::min_element(tmp_mat.begin(),tmp_mat.end(), + // [](cv::Vec3b a, cv::Vec3b b) -> bool{ return a[0] < b[0]; }))[0]; + // offValues_G[k] = (*std::min_element(tmp_mat.begin(),tmp_mat.end(), + // [](cv::Vec3b a, cv::Vec3b b) -> bool{ return a[1] < b[1]; }))[1]; + // offValues_B[k] = (*std::min_element(tmp_mat.begin(),tmp_mat.end(), + // [](cv::Vec3b a, cv::Vec3b b) -> bool{ return a[2] < b[2]; }))[2]; + printf("\noffValues[%d] R = %f G = %f B= %f", k, offValues_R[k], offValues_G[k], offValues_B[k]); + } + else{ + offValues_R[k] = offValues_G[k] = offValues_B[k] = mean.val[0]; + // auto tmp_mat = img(cv::Rect(offset_total, 10, offset_wdth, img.rows - 10)); + // offValues_R[k] = offValues_G[k] = offValues_B[k] = *std::min_element(tmp_mat.begin(), + // tmp_mat.end(), [](std::uint8_t a, std::uint8_t b) -> bool{ return a < b; }); + printf("\noffValues[%d] = %f", k, offValues_R[k]); + } + + offset_total += offset_wdth; + } + + } + + // std::string clrmode = (mode == 0x01 ? "彩色" : " 灰度"); + // log = "开始" + clrmode + "暗场校正 \n"; + for (volatile int s = 0; s < 2; s++) + { + int offsets_R[9]{0}, offsets_G[9]{0}, offsets_B[9]{0}; // = (int *)(s == 0 ? ¶m.OffsetF[0] : ¶m.OffsetB[0]); + memcpy(offsets_R, (s == 0 ? ¶m.OffsetF_R[0] : ¶m.OffsetB_R[0]), sizeof(param.OffsetF_R)); + memcpy(offsets_G, (s == 0 ? ¶m.OffsetF_G[0] : ¶m.OffsetB_G[0]), sizeof(param.OffsetF_G)); + memcpy(offsets_B, (s == 0 ? ¶m.OffsetF_B[0] : ¶m.OffsetB_B[0]), sizeof(param.OffsetF_B)); + if (mode == IMAGE_GRAY) + { + for (volatile int j = 0; j < 9; j++) + { + int k = s * 9 + j; + double diff = BLACK_DIFF(offValues_R[k]); + //double diff = 3 - offValues_R[k]; + double step = radio * diff; + int preStep = offsetStep1[k]; + if (step < 1 && step > 0) + step = 1; + if (step < 0 && step > -1) + step = -1; + + // FMT_STEP(step); + bool isMinStep = abs(step) == 1 && step == offsetStep1[k]; + bool isOutBounds = offsets_R[j] >= 512 && step > 0; + isOutBounds |= offsets_R[j] <= 0 && step < 0; + log += " 暗场校正 :" + std::to_string(k) + ";diff:" + std::to_string(diff) + ";light:" + std::to_string(offValues_R[k]) + ";offset:" + std::to_string(offsets_R[j]) + ";step:" + std::to_string(step) + "\r\n"; + if (isOutBounds) + log += " 第" + std::to_string(k) + "条带暗场校正异常,暗场值无法降低 \r\n"; + //else if (abs(step) > 1 || isMinStep) + else if (abs(step) > 1) + { + offsetStep1[k] = (int)(step); + offsets_R[offset_indexs[k]] += step; + log += "offsetStep1" + std::to_string(k) + " = " + std::to_string(offsetStep1[k]) + ", offset_indexs" + std::to_string(k) + " =" + std::to_string(offset_indexs[k]) + "\r\n"; + + if (offsets_R[offset_indexs[k]] < 1) + offsets_R[offset_indexs[k]] = 1; + if (offsets_R[offset_indexs[k]] > 512) + offsets_R[offset_indexs[k]] = 512; + // isNeedSave = false; + bflags[k] = false; + } + else + { + bflags[k] = true; + // printf("channel[%d] black correct done\n",k); + } + + log += (s == 0 ? "彩色正面" : "彩色背面"); + log += "偏移值:" + std::to_string(offsets_R[0]) + "," + std::to_string(offsets_R[1]) + "," + std::to_string(offsets_R[2]) + "," + + std::to_string(offsets_R[3]) + "," + std::to_string(offsets_R[4]) + "," + std::to_string(offsets_R[5]) + "," + std::to_string(offsets_R[6]) + + "," + std::to_string(offsets_R[7]) + "," + std::to_string(offsets_R[8]) + "\r\n"; + // printf("\n%s",log.c_str()); + // log += (s == 0 ? "彩色正面暗场校正完成 \r\n" : "彩色背面暗场校正完成 \r\n"); + ftm_log.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + log = ""; + } + memcpy(offsets_G, offsets_R, sizeof(offsets_R)); + memcpy(offsets_B, offsets_R, sizeof(offsets_R)); + } + else + { + double offValues[18]{0}; + int offsets[9]{0}; + for (int color = 0; color < 3; color++) + { + memcpy(offValues, color == 0 ? offValues_R : (color == 1 ? offValues_G : offValues_B), sizeof(offValues)); + memcpy(offsets, color == 0 ? offsets_R : (color == 1 ? offsets_G : offsets_B), sizeof(offsets)); + for (volatile int j = 0; j < 9; j++) + { + int k = s * 9 + j; + double diff = BLACK_DIFF(offValues[k]); + // double diff = 3 - offValues[k]; + double step = radio * diff; + int preStep = offsetStep1[k]; + if (step < 1 && step > 0) + step = 1; + if (step < 0 && step > -1) + step = -1; + + // FMT_STEP(step); + bool isMinStep = abs(step) == 1 && step == offsetStep1[k]; + bool isOutBounds = offsets[j] >= 512 && step > 0; + isOutBounds |= offsets[j] <= 0 && step < 0; + log += " 暗场校正 :" + std::to_string(k) + ";diff:" + std::to_string(diff) + ";light:" + std::to_string(offValues[k]) + ";offset:" + std::to_string(offsets[j]) + ";step:" + std::to_string(step) + "\r\n"; + if (isOutBounds) + log += " 第" + std::to_string(k) + "条带暗场校正异常,暗场值无法降低 \r\n"; + //else if (abs(step) > 1 || isMinStep) + else if (abs(step) > 1) + { + offsetStep1[k] = (int)(step); + offsets[offset_indexs[k]] += step; + log += "offsetStep1" + std::to_string(k) + " = " + std::to_string(offsetStep1[k]) + ", offset_indexs" + std::to_string(k) + " =" + std::to_string(offset_indexs[k]) + "\r\n"; + + if (offsets[offset_indexs[k]] < 1) + offsets[offset_indexs[k]] = 1; + if (offsets[offset_indexs[k]] > 512) + offsets[offset_indexs[k]] = 512; + // isNeedSave = false; + bflags[18 * color + k] = false; + } + else + { + bflags[18 * color + k] = true; + // printf("channel[%d] black correct done\n",k); + } + log += (s == 0 ? "彩色正面" : "彩色背面"); + log += "偏移值:" + std::to_string(offsets[0]) + "," + std::to_string(offsets[1]) + "," + std::to_string(offsets[2]) + "," + + std::to_string(offsets[3]) + "," + std::to_string(offsets[4]) + "," + std::to_string(offsets[5]) + "," + std::to_string(offsets[6]) + + "," + std::to_string(offsets[7]) + "," + std::to_string(offsets[7]) + "\r\n"; + // log += (s == 0 ? "彩色正面暗场校正完成 \r\n" : "彩色背面暗场校正完成 \r\n"); + // printf("\n%s",log.c_str()); + ftm_log.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + log = ""; + } + memcpy(color == 0 ? offValues_R : (color == 1 ? offValues_G : offValues_B), offValues, sizeof(offValues)); + memcpy(color == 0 ? offsets_R : (color == 1 ? offsets_G : offsets_B), offsets, sizeof(offsets)); + } + } + memcpy((s == 0 ? ¶m.OffsetF_R[0] : ¶m.OffsetB_R[0]), offsets_R, sizeof(param.OffsetF_R)); + memcpy((s == 0 ? ¶m.OffsetF_G[0] : ¶m.OffsetB_G[0]), offsets_G, sizeof(param.OffsetF_G)); + memcpy((s == 0 ? ¶m.OffsetF_B[0] : ¶m.OffsetB_B[0]), offsets_B, sizeof(param.OffsetF_B)); + } + + for (int i = 0; i < bflags.size(); i++) + { + if (!bflags[i]) + isNeedSave = false; + printf(" b_flags [%d] = %s ",i,bflags[i]?"true":"false"); + } + + if (isNeedSave) + { + printf("Save LUT image path :%s \n", param.Flat_BwPath.c_str()); + log = "暗场校正完成 \r\n"; + if (m_captureCallback) + m_captureCallback(mode, log); + // log =""; + imwrite(param.Flat_BwPath, mrgmat); + } + } + else // 明场 + { + radio = 1.0; + if (mode == IMAGE_COLOR) + { + double values[2][3]; + + cv::Scalar a = cv::mean(mrgmat(cv::Rect(0, 0, mrgmat.cols / 2, mrgmat.rows))); + cv::Scalar b = cv::mean(mrgmat(cv::Rect(mrgmat.cols / 2, 0, mrgmat.cols / 2, mrgmat.rows))); + for (int j = 0; j < 3; j++) + { + values[0][j] = a.val[2 - j]; + values[1][j] = b.val[2 - j]; + } + printf("\n mean F_R = %f F_G = %f F_B = %f B_R = %f B_G = %f B_B = %f ", values[0][0], values[0][1], values[0][2], + values[1][0], values[1][1], values[1][2]); + + log = "开始彩色明场校正 \r\n"; + if (m_captureCallback) + m_captureCallback(mode, log); + for (int s = 0; s < 2; s++) + { + int exposures[3]; // = (int *)(s == 0 ? param.ExposureF : param.ExposureB); + memcpy(exposures, (s == 0 ? ¶m.ExposureF[0] : ¶m.ExposureB[0]), sizeof(param.ExposureB)); + for (int x = 0; x < 3; x++) + { + int k = (3 * s + x); + int diff = LIGHT_DIFF(param.MaxBright, *((double *)values + k)); + // if(x == 2) diff = LIGHT_DIFF(param.MaxBright*9/10, *((double *)values + k)); + log += " 明场:" + std::to_string(k) + ";diff:" + std::to_string(diff) + "\r\n"; + // if(abs(diff) > 30) + // radio = 2; + // else + // radio = 1; + double step = diff * radio; + int preStep = *((int *)expStep + k); + if (step * preStep < 0) + { + step = 0 - preStep / 2; + } + if (step < 1 && step > 0) + step = 1; + if (step < 0 && step > -1) + step = -1; + + bool isMinStep = abs(step) == 1 && step == *((int *)expStep + k); + bool isOutBounds = exposures[x] >= (param.Sp / 3 / (mode ? 3 : 1) - 15) && step > 0; + isOutBounds |= exposures[x] <= 0 && step < 0; + if (isOutBounds) + log += " 第" + std::to_string(x) + "个明场校正异常 \r\n"; + else if (abs(diff) >= 1 || isMinStep) + { + *((int *)expStep + k) = (int)(step); + exposures[x] += step; + if (exposures[x] > (param.Sp / 3 / (mode ? 3 : 1) - 15)) + { + exposures[x] = (param.Sp / 3 / (mode ? 3 : 1) - 15); + } + if (exposures[x] <= 0) + exposures[x] = 1; + isNeedSave = false; + } + log += " 曝光值:" + std::to_string(exposures[x]) + "\r\n"; + log += " 调整步长:" + std::to_string(*((int *)expStep + k)) + "\r\n"; + } + memcpy((s == 0 ? ¶m.ExposureF[0] : ¶m.ExposureB[0]), exposures, sizeof(param.ExposureB)); + } + printf("\n%s", log.c_str()); + ftm_log.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + + if (isNeedSave) + { + log = "彩色明场校正完成\r\n"; + if (m_captureCallback) + m_captureCallback(mode, log); + // log =""; + imwrite(param.Flat_WhitePath, mrgmat); + } + } + else + { + double values[2]; + values[0] = cv::mean(mrgmat(cv::Rect(0, 0, mrgmat.cols / 2, mrgmat.rows))).val[0]; + values[1] = cv::mean(mrgmat(cv::Rect(mrgmat.cols / 2, 0, mrgmat.cols / 2, mrgmat.rows))).val[0]; + log = "-----开始灰色明场校正-----\r\n"; + log += " 灰色扫描灰度明场均值:" + std::to_string(values[0]) + "," + std::to_string(values[1]) + "\r\n"; + if (m_captureCallback) + m_captureCallback(mode, log); + for (int s = 0; s < 2; s++) + { + int *exposures = (int *)(s == 0 ? param.ExposureF : param.ExposureB); + int diff = LIGHT_DIFF(param.MaxBright, values[s]); + // if(abs(diff) > 30) + // radio = 2; + // else + // radio = 1; + double step = diff * radio; + log += " 明场:" + std::to_string(s) + ";diff:" + std::to_string(diff) + "\r\n"; + int preStep = expStep[s][0]; + if (step * preStep < 0) + { + step = 0 - preStep / 2; + } + else + { + radio = 1; + } + if (step < 1 && step > 0) + step = 1; + if (step < 0 && step > -1) + step = -1; + + int exp = *(exposures + 1); + // std::string ss1(string_format("exp[%d] = %d step = %.3f \r\n", s, exp, step)); + // log += ss1; + bool isMinStep = abs(step) == 1 && step == expStep[s][0]; + bool isOutBounds = exp >= (param.Sp / 3 / (mode ? 3 : 1) - 15) && step > 0; + isOutBounds |= exp <= 0 && step < 0; + if (isOutBounds) + log += " 第" + std::to_string(s) + "个明场校正异常 \r\n"; + else if (abs(diff) > 1 || isMinStep) + { + exp += step; + if (exp < 0) + exp = 0; + if (exp > (param.Sp / 3 / (mode ? 3 : 1) - 15)) + exp = param.Sp / 3 / (mode ? 3 : 1) - 15; + + float coffe[3] = {1, 1, 1}; // 0.2, 1,0.51 + for (int k = 0; k < 3; k++) + { + *(exposures + k) = (int)(exp * coffe[k]); + expStep[s][k] = (int)(step); + std::string exps(string_format("expStep[%d][%d] = %.3f\r\n", s, k, step)); + log += exps; + std::string ss(string_format("exposures[%d] = %0.3f \r\n", k, exposures[k])); + log += ss; + } + + isNeedSave = false; + } + } + printf("\n%s", log.c_str()); + ftm_log.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + if (isNeedSave) + { + printf("Save LUT image path :%s \n", param.Flat_WhitePath.c_str()); + log = "灰度明场校正完成\r\n"; + if (m_captureCallback) + m_captureCallback(mode, log); + log = ""; + imwrite(param.Flat_WhitePath, mrgmat); + } + } + } + Get_Static_CorrectParam().SaveCorrectParam(param); + printf("exit Save_lut \n"); + return isNeedSave; +} + +void MultiFrameCapture::correctcolor(int correctmode) +{ + + printf(" correctcolor start mode = %d \n", correctmode); + auto _start = std::chrono::steady_clock::now(); + std::map> mode = {{1, {1, 0}}, {2, {1, 1}}, { 3, {2 ,0}},{ 4,{ 2,1}},{ 5,{ 3,0}},{ 6,{ 3,1}},{ 7,{16,0}}, + {8, {16, 1}},{9, {17,0}}, {10, {17,1}},{11,{32,1}},{12,{32,0}},{13,{33,1}},{14,{33,0}}}; + ThreadPool pool(2); + std::queue> fu_correct; + std::string loginfo = "Start Correctcolor \r\n"; + if (m_captureCallback) + m_captureCallback(0x01, loginfo); + if (correctmode != 0) + { + creatcorrectconfig(mode[correctmode].first, mode[correctmode].second); + auto param = Get_Static_CorrectParam().GetFpgaparam_8478(mode[correctmode].first, mode[correctmode].second); + fu_correct.emplace(pool.enqueue([param](int dpi, int color) + { creatLUTData(dpi, color, param); }, + mode[correctmode].first, mode[correctmode].second)); + } + else + { + for (auto node : mode) + { + creatcorrectconfig(node.second.first, node.second.second); + auto param = Get_Static_CorrectParam().GetFpgaparam_8478(node.second.first, node.second.second); + fu_correct.emplace(pool.enqueue([param](int dpi, int color) + { creatLUTData(dpi, color, param); }, + node.second.first, node.second.second)); + } + } + + while (fu_correct.size()) + { + fu_correct.front().get(); + fu_correct.pop(); + } + loginfo = "******Correct Done****** time " + std::to_string(std::chrono::duration(std::chrono::steady_clock::now() - _start).count()) + "s"; + if (m_captureCallback) + m_captureCallback(0x04, loginfo); +} + +void MultiFrameCapture::fpga_reset() +{ + reset_pin->setValue(Gpio::Low); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + reset_pin->setValue(Gpio::High); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); +} + +void MultiFrameCapture::fpga_reload() +{ + // fpga 代码重载 + fpgaLoad->setValue(Gpio::Low); + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + fpga_conf_initn->setValue(Gpio::Low); + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + printf("\n fpga_conf_done value %d", fpga_conf_done->getValue()); + fpgaLoad->setValue(Gpio::High); + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + fpga_conf_initn->setValue(Gpio::High); + // std::this_thread::sleep_for(std::chrono::milliseconds(5)); + printf("\n fpga_conf_done value %d", fpga_conf_done->getValue()); + // while(fpga_conf_done->getValue() == Gpio::GpioLevel::Low) + // std::this_thread::sleep_for(std::chrono::milliseconds(5)); + std::this_thread::sleep_for(std::chrono::seconds(3)); + printf("\n fpga_conf_done value %d", fpga_conf_done->getValue()); + fpgaComm->resetADC(); + fpgaComm->update(0); +} + +void MultiFrameCapture::init_imagedatabuffer() +{ + + if (pimgdata_info.pdata) + free(pimgdata_info.pdata); + pimgdata_info.pdata = nullptr; + pimgdata_info.offset = pimgdata_info.frame_count = pimgdata_info.img_h = pimgdata_info.img_w = 0; + if (frame_count != 0) + { + int t_frame_count = fpgaComm->getFrameNum(); + int width = this->width() * (m_config.g200params.color ? 3 : 1); + int height = frame_height * 2; + pimgdata_info.pdata = malloc(height * t_frame_count * width); + pimgdata_info.total = height * t_frame_count; + pimgdata_info.offset = 0; + pimgdata_info.frame_count = 0; + pimgdata_info.img_h = 0; + pimgdata_info.img_w = 0; + printf("pimgdata_info.pdata = %p malloc_size = %d \n", pimgdata_info.pdata, height * t_frame_count * width, t_frame_count, width, height); + } +} + +void MultiFrameCapture::free_imagedatabuffer() +{ + if (pimgdata_info.pdata) + free(pimgdata_info.pdata); + pimgdata_info.pdata = nullptr; + printf("--- free imagedatabuf --- \n"); +} + + +// static void neon_memcpy(volatile void *dst, volatile void *src, int sz) +// { +// if (sz & 63) +// sz = (sz & -64) + 64; +// asm volatile ( +// "NEONCopyPLD: \n" +// " VLDM %[src]!,{d0-d7} \n" +// " VSTM %[dst]!,{d0-d7} \n" +// " SUBS %[sz],%[sz],#0x40 \n" +// " BGT NEONCopyPLD \n" +// : [dst]"+r"(dst), [src]"+r"(src), [sz]"+r"(sz) : : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "cc", "memory"); +// } + +void MultiFrameCapture::update_imgdatainfo(void *itemmat, frame_data_info &info, uint32_t h, uint32_t w) +{ + // StopWatch sw; + if (info.pdata && itemmat) + { + // neon_memcpy(pimgdata_info.pdata + pimgdata_info.offset,itemmat,h*w); + memcpy(info.pdata + info.offset, itemmat, h * w); + info.offset += h * w; + info.frame_count++; + info.img_h += h; + info.img_w = w; + // printf("offset = %d item_total = %d \n", pimgdata_info.offset,pimgdata_info.frame_count); + } + // printf("size = %d frame memcpy time = %fms \n", h*w,sw.elapsed_ms()); +} + +void MultiFrameCapture::update_imgdatainfo(void *itemmat, uint32_t h, uint32_t w) +{ + if (pimgdata_info.pdata && itemmat) + { + memcpy(pimgdata_info.pdata + pimgdata_info.offset, itemmat, h * w); + pimgdata_info.offset += h * w; + pimgdata_info.frame_count++; + pimgdata_info.img_h += h; + pimgdata_info.img_w = w; + } +} + +void MultiFrameCapture::init_adc_8478() +{ + // std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::vector> maps; + for (int bank = 0; bank < 4; bank++) + for (int i = 1; i < 64; i++) + { + // write_adc_8478(bank_change[bank], i, bank_value[i + 64 * bank],bank_value[i + 64 * bank]); + maps.push_back({bank_change[bank], i, bank_value[i + 64 * bank],bank_value[i + 64 * bank]}); + } + write_adc_8478(maps); + // std::this_thread::sleep_for(std::chrono::milliseconds(100)); +} + +void MultiFrameCapture::write_adc_8478(int bank, int addr, int val, bool A_or_B) +{ + uint32_t reg5 = 0; + fpgaComm->read(5, reg5); + fpgaComm->write(5, reg5 | 0xc000); // adc 配置使能打开 + // std::this_thread::sleep_for(std::chrono::milliseconds(1)); + adc_8478_param p_adc{0}; + p_adc.param.r_or_w_h = p_adc.param.r_or_w_l = 0; + p_adc.param.addr_l = 0; + p_adc.param.addr_h = addr; + p_adc.param.val_l = bank; + p_adc.param.val_h = val; + fpgaComm->write(A_or_B ? 4 : 7, p_adc.value); + uint32_t reg1_v; + fpgaComm->read(1, reg1_v); + Mode_FPGA reg1 = *((Mode_FPGA *)®1_v); + A_or_B ? reg1.adcA = 1 : reg1.adcB = 1; + fpgaComm->write(1, *((uint32_t *)®1)); + A_or_B ? reg1.adcA = 0 : reg1.adcB = 0; + fpgaComm->write(1, *((uint32_t *)®1)); + // std::this_thread::sleep_for(std::chrono::microseconds(100)); + fpgaComm->write(5, reg5 & 0xffff3fff); // adc 配置使能关闭 +} + + +void MultiFrameCapture::write_adc_8478(int bank, int addr, int val_A, int val_B) +{ + uint32_t reg5 = 0; + fpgaComm->read(5, reg5); + fpgaComm->write(5, reg5 | 0xc000); // adc 配置使能打开 + // std::this_thread::sleep_for(std::chrono::milliseconds(1)); + adc_8478_param p_adc{0}; + p_adc.param.r_or_w_h = p_adc.param.r_or_w_l = 0; + p_adc.param.addr_l = 0; + p_adc.param.addr_h = addr; + p_adc.param.val_l = bank; + p_adc.param.val_h = val_A; + fpgaComm->write(4, p_adc.value); + p_adc.param.val_h = val_B; + fpgaComm->write(7, p_adc.value); + uint32_t reg1_v; + fpgaComm->read(1, reg1_v); + Mode_FPGA reg1 = *((Mode_FPGA *)®1_v); + reg1.adcA = 1; reg1.adcB = 1; + fpgaComm->write(1, *((uint32_t *)®1)); + reg1.adcA = 0; reg1.adcB = 0; + fpgaComm->write(1, *((uint32_t *)®1)); + // std::this_thread::sleep_for(std::chrono::microseconds(100)); + fpgaComm->write(5, reg5 & 0xffff3fff); // adc 配置使能关闭 +} + +void MultiFrameCapture::write_adc_8478(std::vector> maps) +{ + uint32_t reg5 = 0; + fpgaComm->read(5, reg5); + fpgaComm->write(5, reg5 | 0xc000); // adc 配置使能打开 + // std::this_thread::sleep_for(std::chrono::milliseconds(1)); + adc_8478_param p_adc{0}; + for(auto & node : maps){ + p_adc.param.r_or_w_h = p_adc.param.r_or_w_l = 0; + p_adc.param.addr_l = 0; + p_adc.param.addr_h = std::get<1>(node); + p_adc.param.val_l = std::get<0>(node); + p_adc.param.val_h = std::get<2>(node); + fpgaComm->write(4, p_adc.value); + p_adc.param.val_h = std::get<3>(node); + fpgaComm->write(7, p_adc.value); + uint32_t reg1_v; + fpgaComm->read(1, reg1_v); + Mode_FPGA reg1 = *((Mode_FPGA *)®1_v); + reg1.adcA = 1; reg1.adcB = 1; + fpgaComm->write(1, *((uint32_t *)®1)); + reg1.adcA = 0; reg1.adcB = 0; + fpgaComm->write(1, *((uint32_t *)®1)); + } + // std::this_thread::sleep_for(std::chrono::microseconds(100)); + fpgaComm->write(5, reg5 & 0xffff3fff); // adc 配置使能关闭 +} + +uint32_t MultiFrameCapture::read_adc_8478(int bank, int addr, bool A_or_B) +{ + uint32_t reg5 = 0; + fpgaComm->read(5, reg5); + fpgaComm->write(5, reg5 | 0xc000); // adc 配置使能打开 + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + adc_8478_param p_adc{0}; + p_adc.param.r_or_w_h = 0; + p_adc.param.r_or_w_l = 2; + p_adc.param.addr_l = 0; + p_adc.param.addr_h = addr; + p_adc.param.val_l = bank; + p_adc.param.val_h = 0; + fpgaComm->write(A_or_B ? 4 : 7, p_adc.value); + uint32_t reg1_v; + fpgaComm->read(1, reg1_v); + Mode_FPGA reg1 = *((Mode_FPGA *)®1_v); + A_or_B ? reg1.adcA = 1 : reg1.adcB = 1; + fpgaComm->write(1, *((uint32_t *)®1)); + A_or_B ? reg1.adcA = 0 : reg1.adcB = 0; + fpgaComm->write(1, *((uint32_t *)®1)); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + fpgaComm->write(5, reg5 & 0xffff3fff); // adc 配置使能关闭 + uint32_t read_reg = 0; + fpgaComm->read(3, read_reg); + return read_reg; +} + +void MultiFrameCapture::set_exp_8478_single(int exp_r, int exp_g, int exp_b, int sp, bool A_or_B, bool is_gray) +{ + + int pix_counter = sp / 3 - 10; + // set_pixel_count_8478(pix_counter,is_gray); + int exp_max = pix_counter - 10; + if (exp_r > exp_max) + exp_r = exp_max; + if (exp_g > exp_max) + exp_g = exp_max; + if (exp_b > exp_max) + exp_b = exp_max; + + write_adc_8478(bank_change[1], 0x7, 0, A_or_B); // exp R start + write_adc_8478(bank_change[1], 0x8, 0x35, A_or_B); + write_adc_8478(bank_change[1], 0x9, (exp_r & 0x7f00) / 0x100, A_or_B); // exp R end + write_adc_8478(bank_change[1], 0xa, exp_r & 0xff, A_or_B); + + write_adc_8478(bank_change[1], 0xe, 0, A_or_B); // exp G start + write_adc_8478(bank_change[1], 0xf, 0x35, A_or_B); + write_adc_8478(bank_change[1], 0x10, (exp_g & 0x7f00) / 0x100, A_or_B); // exp G end + write_adc_8478(bank_change[1], 0x11, exp_g & 0xff, A_or_B); + + write_adc_8478(bank_change[1], 0x15, 0, A_or_B); // exp B start + write_adc_8478(bank_change[1], 0x16, 0x35, A_or_B); + write_adc_8478(bank_change[1], 0x17, (exp_b & 0x7f00) / 0x100, A_or_B); // exp B end + write_adc_8478(bank_change[1], 0x18, exp_b & 0xff, A_or_B); +} + +void MultiFrameCapture::set_led_off() +{ + write_adc_8478(bank_change[1], 0x7, 0, 0); // exp R start + write_adc_8478(bank_change[1], 0x8, 0, 0); + write_adc_8478(bank_change[1], 0x9, 0, 0); // exp R end + write_adc_8478(bank_change[1], 0xa, 0, 0); + + write_adc_8478(bank_change[1], 0xe, 0, 0); // exp G start + write_adc_8478(bank_change[1], 0xf, 0, 0); + write_adc_8478(bank_change[1], 0x10, 0, 0); // exp G end + write_adc_8478(bank_change[1], 0x11, 0, 0); + + write_adc_8478(bank_change[1], 0x15, 0, 0); // exp B start + write_adc_8478(bank_change[1], 0x16, 0, 0); + write_adc_8478(bank_change[1], 0x17, 0, 0); // exp B end + write_adc_8478(bank_change[1], 0x18, 0, 0); +} + +void MultiFrameCapture::set_pixel_count_8478(int val, bool is_gray) +{ + + val = val - 10; + //fpgaComm->write(20, ((val & 0xffff) * 0x10000) * 3 + (val & 0xffff) * 3); + fpgaComm->write(19, ((val & 0xffff) * 0x10000) * 3 + (val & 0xffff) * 3); + + write_adc_8478(bank_change[1], 1, (val & 0x7f00) / 0x100, (val & 0x7f00) / 0x100); // count0 -A + write_adc_8478(bank_change[1], 2, val & 0xff, val & 0xff); + if (is_gray) + return; + write_adc_8478(bank_change[1], 3, (val & 0x7f00) / 0x100, (val & 0x7f00) / 0x100); // count1 -A + write_adc_8478(bank_change[1], 4, val & 0xff, val & 0xff); + + write_adc_8478(bank_change[1], 5, (val & 0x7f00) / 0x100, (val & 0x7f00) / 0x100); // count2 -A + write_adc_8478(bank_change[1], 6, val & 0xff, val & 0xff); +} + +void MultiFrameCapture::set_digital_offset_8478(int channel, int val_A, int val_B, int color) +{ + if (channel < 0 || channel > 8) + return; + if (color < 0 || color > 2) + return; + int s_addr = ((color == 0) ? 7 : ((color == 2) ? 1 : 0x1c)); + int bank = color == 0 ? 0 : 3; + val_A = val_A & 0x1ff; val_B = val_B & 0x1ff; + write_adc_8478(bank_change[bank], s_addr + channel * 2, val_A < 255 ? 1 : 0, val_B < 255 ? 1 : 0); + write_adc_8478(bank_change[bank], s_addr + 1 + channel * 2, val_A & 0xff, val_B & 0xff); +} + +void MultiFrameCapture::set_digital_gain_8478(int channel, uint8_t val_A, uint8_t val_B, int color) +{ + if (channel < 0 || channel > 8) + return; + if (color < 0 || color > 2) + return; + int s_addr = ((color == 0) ? 0x19 : ((color == 2) ? 0x13 : 0x2e)); + int bank = color == 0 ? 0 : 3; + write_adc_8478(bank_change[bank], s_addr + channel, val_A, val_B); +} + +void MultiFrameCapture::set_dpi_mode(bool is_600) +{ + if (is_600) + { + write_adc_8478(bank_change[1], 0x38, 0x50, 0x50); + } + else + { + write_adc_8478(bank_change[1], 0x38, 0x30, 0x30); + } +} + +void MultiFrameCapture::set_BOS_postion(uint32_t rise, uint32_t fall) +{ + write_adc_8478(bank_change[2], 0x1, (rise & 0xff00) / 0x100, true); // A面 BOS 起始位置 + write_adc_8478(bank_change[2], 0x2, rise & 0xff, true); + + write_adc_8478(bank_change[2], 0x3, (fall & 0xff00) / 0x100, true); // A面 BOS 结束位置 + write_adc_8478(bank_change[2], 0x4, fall & 0xff, true); + + write_adc_8478(bank_change[2], 0x1, (rise & 0xff00) / 0x100, false); // B面 BOS 起始位置 + write_adc_8478(bank_change[2], 0x2, rise & 0xff, false); + + write_adc_8478(bank_change[2], 0x3, (fall & 0xff00) / 0x100, false); // B面 BOS 结束位置 + write_adc_8478(bank_change[2], 0x4, fall & 0xff, false); +} + +void MultiFrameCapture::set_EN_postion(uint32_t rise, uint32_t fall) +{ + write_adc_8478(bank_change[2], 0xd, (rise & 0xff00) / 0x100, true); // A面 EN 起始位置 + write_adc_8478(bank_change[2], 0xe, rise & 0xff, true); + + write_adc_8478(bank_change[2], 0xf, (fall & 0xff00) / 0x100, true); // A面 EN 结束位置 + write_adc_8478(bank_change[2], 0x10, fall & 0xff, true); + + write_adc_8478(bank_change[2], 0xd, (rise & 0xff00) / 0x100, false); // B面 EN 起始位置 + write_adc_8478(bank_change[2], 0xe, rise & 0xff, false); + + write_adc_8478(bank_change[2], 0xf, (fall & 0xff00) / 0x100, false); // B面 EN 结束位置 + write_adc_8478(bank_change[2], 0x10, fall & 0xff, false); +} + +void MultiFrameCapture::set_7864A_current_ctrl(uint32_t current) +{ + if (current > 6) + return; + write_adc_8478(bank_change[2], 0x1a, current * 0x10 + current, false); + write_adc_8478(bank_change[2], 0x1b, current * 0x10 + current, false); + write_adc_8478(bank_change[2], 0x1c, current * 0x10 + current, false); + + write_adc_8478(bank_change[2], 0x1a, current * 0x10 + current, true); + write_adc_8478(bank_change[2], 0x1b, current * 0x10 + current, true); + write_adc_8478(bank_change[2], 0x1c, current * 0x10 + current, true); +} + +void MultiFrameCapture::set_LED_PTN_8478(bool is_bw) +{ + if (is_bw) + { + write_adc_8478(bank_change[0], 0x3d, 0x01, 0x01); + return; + } + write_adc_8478(bank_change[0], 0x3d, 0x11, 0x11); +} + +void MultiFrameCapture::set_ADC_config_frequency(uint32_t freq) +{ + uint32_t reg2 = 0; + fpgaComm->read(2, reg2); + fpgaComm->write(2, (reg2 & 0xffffffe1) | (freq << 1)); // adc 配置 频率 +} + +cv::Mat MultiFrameCapture::merge_8478(cv::Mat src, bool color, uint32_t version) +{ + if (!color) + return src; + cv::Mat dst(src.rows, src.cols / 3, CV_8UC3); + uint32_t width = src.cols / 6; + cv::insertChannel(src(cv::Rect(0, 0, src.cols / 6, src.rows)), dst(cv::Rect(0, 0, dst.cols / 2, dst.rows)), 0); + cv::insertChannel(src(cv::Rect(src.cols / 3, 0, src.cols / 6, src.rows)), dst(cv::Rect(0, 0, dst.cols / 2, dst.rows)), 2); + cv::insertChannel(src(cv::Rect(src.cols / 3 * 2, 0, src.cols / 6, src.rows)), dst(cv::Rect(0, 0, dst.cols / 2, dst.rows)), 1); + cv::insertChannel(src(cv::Rect(src.cols / 6, 0, src.cols / 6, src.rows)), dst(cv::Rect(dst.cols / 2, 0, dst.cols / 2, dst.rows)), 0); + cv::insertChannel(src(cv::Rect(src.cols / 6 * 3, 0, src.cols / 6, src.rows)), dst(cv::Rect(dst.cols / 2, 0, dst.cols / 2, dst.rows)), 2); + cv::insertChannel(src(cv::Rect(src.cols / 6 * 5, 0, src.cols / 6, src.rows)), dst(cv::Rect(dst.cols / 2, 0, dst.cols / 2, dst.rows)), 1); + return dst; +} + +void MultiFrameCapture::single_correct(std::uint32_t mode) +{ + std::vector sup_correct_dpi{1, 2, 3, 0x10, 0x11,0x20,0x21}; + union correct_mode_ + { + struct + { + uint32_t dpi : 16; + uint32_t color_mode : 8; + uint32_t correct_mode : 8; + } param; + uint32_t value; + }; + correct_mode_ tmp; + tmp.value = mode; + if (std::count(sup_correct_dpi.begin(), sup_correct_dpi.end(), tmp.param.dpi) && (tmp.param.color_mode < 2)) + { + auto param = Get_Static_CorrectParam().GetFpgaparam_8478(tmp.param.dpi, tmp.param.color_mode); + if (tmp.param.correct_mode == 1) + creatLUTData(tmp.param.dpi, tmp.param.color_mode, param); + else if (tmp.param.correct_mode == 2) + creatLUTData_gray(tmp.param.dpi, tmp.param.color_mode, param); + } +} \ No newline at end of file diff --git a/capimage/MultiFrameCapture.h b/capimage/MultiFrameCapture.h new file mode 100644 index 0000000..d996169 --- /dev/null +++ b/capimage/MultiFrameCapture.h @@ -0,0 +1,171 @@ +#pragma once +#include "ICapturer.h" +#include "ThreadPool.h" +class FpgaComm; +class gVideo; +class Gpio; + +class MultiFrameCapture : public ICapturer +{ +public: + MultiFrameCapture(); + virtual ~MultiFrameCapture(); + virtual void open(); + virtual void open(HGScanConfig config, FPGAConfigParam fpgaparam){}; + virtual void open(HGScanConfig config, FPGAConfigParam_8478 fpgaparam); + virtual void close(); + virtual void start(); + virtual void stop(); + virtual bool is_runing(); + virtual void snap(); + virtual void snap(frame_data_info info); + virtual cv::Size frame_data_size(); + virtual void stopsnap(); + virtual int getautosizeheight(); + virtual void set_size(int width, int height); + virtual void set_sp(int sp); + + virtual void *readFrame(int timeout); + virtual frame_data_info ReadMultiFrame(int state); + virtual void set_gain(int ix, int val); + virtual void set_offset(int ix, int val); + virtual void set_expo(int ix, int val); + + virtual std::shared_ptr regs(); + virtual void reset(); + virtual int width(); + virtual int height(); + virtual int color(); + virtual void init_autocorrect(int colormode); + virtual void setcapturecall(std::function callback) + { + m_captureCallback = callback; + }; + virtual void Fpga_regsAccess_reset(bool enable); + virtual uint32_t multi_frame_counts() { return frame_count; } + virtual uint32_t multi_curr_snap_index() { return curr_frame_snap_index; } + virtual void single_correct(std::uint32_t mode); + virtual cv::Mat read_one_frame() override; + cv::Mat merge_8478(cv::Mat src, bool color, uint32_t version); + + void init_imagedatabuffer(); + void free_imagedatabuffer(); + void update_imgdatainfo(void *itemmat, frame_data_info &info, uint32_t h, uint32_t w); + void update_imgdatainfo(void *itemmat, uint32_t h, uint32_t w); + +private: + void configFPGAParam(int mode, int dpi); + void configFPGAParam_digital_gain(int mode, int dpi); + void init_lutdate(); + void openDevice(int dpi, int mode); + void creatcorrectconfig(int dpi, int mode); + bool saveLutImg(int dpi, int mode, bool black); + void correctcolor(int correctmode); + void fpga_reset(); + void fpga_reload(); +public: + // 8478 寄存器设置函数 + void set_ADC_config_frequency(uint32_t freq); + void init_adc_8478(); + void write_adc_8478(int bank, int addr, int val, bool A_or_B); + void write_adc_8478(int bank, int addr, int val_A, int val_B); + void write_adc_8478(std::vector> maps); + uint32_t read_adc_8478(int bank, int addr, bool A_or_B); + void set_exp_8478_single(int exp_r, int exp_g, int exp_b, int sp, bool A_or_B, bool is_gray); + void set_led_off(); + void set_pixel_count_8478(int val, bool is_gray); + void set_digital_offset_8478(int channel, int val_A, int val_B, int color); + void set_digital_gain_8478(int channel, uint8_t val_A, uint8_t val_B, int color); + void set_dpi_mode(bool is_600); + void set_BOS_postion(uint32_t rise, uint32_t fall); + void set_EN_postion(uint32_t rise, uint32_t fall); + void set_7864A_current_ctrl(uint32_t current); + void set_LED_PTN_8478(bool is_bw); + +private: + std::function m_captureCallback; + std::shared_ptr video; + std::shared_ptr vdd_cis_3voff_pin; + std::shared_ptr vdd_vis_5ven_pin; + std::shared_ptr reset_pin; + std::shared_ptr image_in_transfer_pin; + std::shared_ptr initDone_pin; + std::shared_ptr fpgaLoad; + std::shared_ptr fpgaComm; + std::shared_ptr fpga_conf_initn; + std::shared_ptr fpga_conf_done; + ThreadPool snapthread; + uint32_t m_fpgaversion; + uint32_t frame_height; + uint32_t frame_count; + uint32_t curr_frame_snap_index; + const int FPGA_MAX_HEIGHT_SUP = 1048576; + frame_data_info pimgdata_info; + std::future snap_fu; + bool bcorrecting; + bool b_stop_snap; + std::thread m_correctthread; + HGScanConfig m_config; + FPGAConfigParam_8478 m_fpgaparam; + + const uint8_t bank_value[256] = + // {0x15,0x78,0x80,0x90,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //bank 0 32us + // 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + // //0x40,0x40,0x40,0x05,0x46,0x23,0x54,0x62,0x35,0x46,0x23,0x00,0x03,0x04,0x05,0x01, //敦南默认值 + // 0x40,0x40,0x80,0x03,0x25,0x46,0x32,0x54,0x63,0x25,0x46,0x00,0x03,0x04,0x05,0x01, + // 0x01,0x00,0x06,0x06,0x03,0x05,0x00,0x14,0x07,0x0B,0x23,0x27,0x00,0x01,0x00,0x00, + + // 0x35,0x02,0x04,0x02,0x04,0x02,0x04,0x00,0x01,0x02,0x00,0x00,0x00,0x01,0x00,0x01, //bank 1 + // 0x02,0x00,0x00,0x00,0x01,0x00,0x01,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00, + // 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + // 0x55,0x00,0x41,0x00,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x01, //bank 2 + // 0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x06,0x00, + // 0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + // 0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //bank 3 + // 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x00, + // 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40, + // 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + + {0x15, 0x78, 0x80, 0x90, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // bank 0 64us + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, + // 0x40,0x40,0x40,0x05,0x46,0x23,0x54,0x62,0x35,0x46,0x23,0x00,0x03,0x04,0x05,0x01, //敦南默认值 + 0x40, 0x40, 0x80, 0x03, 0x25, 0x46, 0x32, 0x54, 0x63, 0x25, 0x46, 0x00, 0x03, 0x04, 0x05, 0x01, + 0x01, 0x00, 0x06, 0x06, 0x03, 0x05, 0x00, 0x14, 0x07, 0x0B, 0x24, 0x28, 0x00, 0x01, 0x00, 0x00, + // 0x01, 0x00, 0x06, 0x06, 0x03, 0x05, 0x00, 0x14, 0x07, 0x0B, 0x25, 0x29, 0x00, 0x01, 0x00, 0x00, + + 0x35, 0x03, 0xdf, 0x03, 0xdf, 0x03, 0xdf, 0x00, 0x01, 0x03, 0xb6, 0x00, 0x00, 0x01, 0x00, 0x01, // bank 1 + 0x03, 0xb6, 0x00, 0x00, 0x01, 0x00, 0x01, 0x03, 0xb6, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x55, 0x00, 0x42, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x03, // bank 2 + 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // bank 3 + 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + //.colorSp_200 = 2606 , .graySp_200= 7818,.colorSp_300 = 2804 ,.graySp_300 = 8412,.colorSp_600 = 3405 ,.graySp_600 = 10215 + + const uint8_t bank_change[4] = {0x15, 0x35, 0x55, 0x75}; + union adc_8478_param + { + struct + { + uint32_t val_l : 8; // 数据位 + uint32_t addr_l : 6; // adc 寄存器地址 + uint32_t r_or_w_l : 2; // 读写标志位 0x11 读 0x01 写 8458 0x10 读 0x00 写 8478 + uint32_t val_h : 8; + uint32_t addr_h : 6; + uint32_t r_or_w_h : 2; + } param; + uint32_t value; + }; +}; diff --git a/capimage/MultiFrameCapture_8458Color.cpp b/capimage/MultiFrameCapture_8458Color.cpp new file mode 100644 index 0000000..d335c74 --- /dev/null +++ b/capimage/MultiFrameCapture_8458Color.cpp @@ -0,0 +1,1331 @@ +#include "MultiFrameCapture_8458Color.h" +#include "config.h" +#include "applog.h" +#include "gvideoisp1.h" +#include "Gpio.h" +#include "DevUtil.h" +#include "FpgaComm.h" +#include "CorrectParam.h" +#include "correct_ultis.h" +#include "stringex.hpp" +#include "filetools.h" +#include "CImageMerge.h" +#include "jsonconfig.h" +#include "StopWatch.h" +#include "linux\sched.h" +#include "deviceconfig.h" + +#define LOG_PATH "/usr/local/correct.log" +FileTools ft_m_log(LOG_PATH); + +static std::string loggername = "MultiFrameCapture_8458Color"; +static double radio = 1.0; +static int offsetStep1[12]; +static int expStep1[2][3]; +static int org_index = 0; +static void initStep1() +{ + printf("initStep aaaaaaaaaaa \n"); + for (int i = 0; i < 2; i++) + { + for (int j = 0; j < 3; j++) + { + expStep1[i][j] = 600; + } + } + for (int i = 0; i < 12; i++) + { + offsetStep1[i] = 256; + printf("offsetStep[%d]=%d \n",i,offsetStep1[i]); + } +} + +MultiFrameCapture_8458Color::MultiFrameCapture_8458Color() : + reset_pin(new GpioOut(50)), + fpgaLoad(new Gpio(70)), + fpga_conf_done(new Gpio(69)), + fpga_conf_initn(new Gpio(71)), + bcorrecting(false), + snapthread(1) +{ + LOG_INIT(); + fpga_conf_done->setDirection(Gpio::in); + fpgaComm.reset(new FpgaComm()); + pimgdata_info = {0}; + + //fpga_reload(); + //fpga_reset(); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + //fpgaComm->resetADC(); + + //fpgaComm->resetADC(); + // fpgaComm->update(); + video.reset(new VIDEO_CLASS()); + set_ADC_config_frequency(12); + init_adc_8458(); + // GetFpgaparam(0x01,0); + snapthread.enqueue([]{ + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET(5, &cpuset); + pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); }); +} + +MultiFrameCapture_8458Color::~MultiFrameCapture_8458Color() +{ + if (video.get()) + video.reset(); + + printf("Exit ~MultiFrameCapture_8458Color() \n"); +} + +void MultiFrameCapture_8458Color::open() +{ +} + +void MultiFrameCapture_8458Color::open(HGScanConfig config,FPGAConfigParam fpgaparam) +{ + // config.g200params.dpi = 3; + uint32_t reg8 =0,reg5 = 0,reg12 =0,reg11 =0, reg10 =0; + set_ADC_config_frequency(12); + init_adc_8458(); + if(config.g200params.dpi == 2) + { + set_exp_8458_double(1315,4100,true); //12214 300dpi 5632 80us 10138 144us 11378 200dpi 56 3942 + set_exp_8458_double(1315,4100,false); + } + else + { + set_exp_8458_single(4315,14855,false); + set_exp_8458_single(4315,14855,true); + } + + printf(" dpi = %d \n",config.g200params.dpi); + + fpgaComm->read(11,reg11); + fpgaComm->write(11,(reg11&0xffffffc0)|0x12); + fpgaComm->write(13,0xdec0000); + + //fpgaComm->write(13,0xd680000); + + video->set_buf_count(10); + fpgaComm->set_cis_type(true); + m_config = config; + m_fpgaparam = fpgaparam; + bool dunnancis = true; + int dpi = config.g200params.dpi == 0x02 ? 2 : (config.g200params.dpi == 0x03 ? 3 : 2); + int mode = config.g200params.color; + auto phyHeight = paperHeight[(PaperSize)config.g200params.paper]; + int pixheight; // = ((int)((phyHeight / 25.4 * (dpi == 0x02 ? 300 : (dpi == 0x03 ? 600 : 200)) + 2) / 3)) * 3 * 2; + int tdpi = config.g200params.dpi == 0x02 ? 300 : (config.g200params.dpi == 0x03 ? 600 : 200); + pixheight = ((int)((phyHeight / 25.4 * tdpi + 2) / 3)) * 3; + + frame_height = 300; + + frame_count = ceil(pixheight / (float)(frame_height)); + // frame_count = 10; // 最后一帧丢帧,多采集一帧防止图像数据缺失 + if (frame_height * frame_count > FPGA_MAX_HEIGHT_SUP) + frame_count = FPGA_MAX_HEIGHT_SUP / frame_height; + + fpgaComm->read(15,m_fpgaversion); + int startsample = 0; + ModeFpga fpgamod = { + .colorMode = mode, + .dpi = m_config.g200params.dpi, + .led = 1, + .sample = startsample, // 256+39 + .adcA = 0, + .adcB = 0, + .selftest = 0, + .sp = config.g200params.dpi == 3 ? 14855 : 12313 }; // 600DPI 0x1450 300DPI 0xe10 10138 + fpgaComm->setRegs(0x01, *((int *)(&fpgamod))); + fpgaComm->setSample(startsample); + fpgaComm->enableLed(true); + fpgaComm->setEnTestCol(false); + fpgaComm->setEnTestBit(false); + + set_dpi_mode(config.g200params.dpi == 3); + video->open(config.g200params.dpi == 0x03 ? 7344 : 3672,frame_height*2); + fpgaComm->setFrameNum(frame_count); + fpgaComm->setFrameHeight(frame_height); + printf("fpgaComm set height = %d \n", frame_height); + fpgaComm->read(8,reg8); + + //fpgaComm->write(8,reg8|0x100); //行号 enable + fpgaComm->write(8,reg8&0xfffffeff); //行号 disable + fpgaComm->read(5,reg5); + //fpgaComm->write(5,reg5|0x2000); //测试数据 白+黑 enable + fpgaComm->write(5,reg5&0xffffdfff); //测试数据 白+黑 disable + fpgaComm->read(12,reg12); + //fpgaComm->write(12,reg5&0xfffff000+0x97e); //帧间隔延迟 >=22.5us + + //fpgaComm->write(12,reg5&0xe000e000+0xfa0067e); //帧间隔延迟 >=22.5us + //fpgaComm->write(12,0x04e20400); //0x494e491 0x79de496 范围 0-12 16-28 (16-28 > 0-12) + + fpgaComm->read(10,reg10); + if(m_config.g200params.dpi == 3){ + fpgaComm->write(10,0x03b0037a); //120 us 600*600 多帧 + fpgaComm->write(12,0x02000100); //120 us 600*600 多帧 + } + else{ + fpgaComm->write(12,0x00200010); //58us 300*600 多帧 + fpgaComm->write(10,0x01b0017a); //58us 300*600 多帧 + + // fpgaComm->write(12,0x03b0037a); //58us 300*600 多帧 + // fpgaComm->write(10,0x05b00500); //58us 300*600 多帧 + } + + + //fpgaComm->write(4,0x77204001); + //fpgaComm->write(7,0x48004041); + + //if(m_config.g200params.dpi == 3) + // fpgaComm->write(10,reg10&0xffff0000+0x3f8); //行间隔 低16位 + // fpgaComm->write(10,reg10&0xffff0000+0x1f8); //行间隔 低16位 + //fpgaComm->write(10,reg10&0xffff+0x4000000); //帧结束计数 高16位 + fpgaComm->write(22,201); + fpgaComm->setFrameNum(1); + fpgaComm->update(3); + fpgaComm->capture(); // abort first frame + video->read_frame(1000); + fpgaComm->setFrameNum(frame_count); + + fpgaComm->update(3); + // initLut(fpgaparam.LutPath, config.g200params.color); + // initLut(config.g200params.is_textcorrect?fpgaparam.LutPath:fpgaparam.TextLutPath,config.g200params.color); + // initLut(fpgaparam.TextLutPath, config.g200params.color); + init_lutdate(); + // init_imagedatabuffer(); +} + +void MultiFrameCapture_8458Color::init_lutdate() +{ + DeviceConfig::Gray_Apply gray_; + gray_.value = Get_static_deviceconfig().GetParam().gray_param; + std::string lutpath = m_config.g200params.is_textcorrect ? m_fpgaparam.LutPath : m_fpgaparam.TextLutPath; + if ((m_fpgaparam.DpiMode == 1) && (gray_.Param_Setting.en_200_clr == 1 && m_config.g200params.color == true)) + lutpath = "/usr/local/huago/Graylut200clr.bmp"; + else if ((m_fpgaparam.DpiMode == 2) && (gray_.Param_Setting.en_300_clr == 1 && m_config.g200params.color == true)) + lutpath = "/usr/local/huago/Graylut300clr.bmp"; + else if ((m_fpgaparam.DpiMode == 3) && (gray_.Param_Setting.en_600_clr == 1 && m_config.g200params.color == true)) + lutpath = "/usr/local/huago/Graylut600clr.bmp"; + else if ((m_fpgaparam.DpiMode == 16) && (gray_.Param_Setting.en_slow_clr == 1 && m_config.g200params.color == true)) + lutpath = "/usr/local/huago/Graylutslow_moireclr.bmp"; + else if ((m_fpgaparam.DpiMode == 17) && (gray_.Param_Setting.en_slow_300_clr == 1 && m_config.g200params.color == true)) + lutpath = "/usr/local/huago/Graylutslow_moire300clr.bmp"; + else if ((m_fpgaparam.DpiMode == 32) && (gray_.Param_Setting.en_long_Manuscript_200_clr == 1 && m_config.g200params.color == true)) + lutpath = "/usr/local/huago/GraylutLong_Manuscript200clr.bmp"; + else if ((m_fpgaparam.DpiMode == 33) && (gray_.Param_Setting.en_long_Manuscript_300_clr == 1 && m_config.g200params.color == true)) + lutpath = "/usr/local/huago/GraylutLong_Manuscript300clr.bmp"; + else if ((m_fpgaparam.DpiMode == 1) && (gray_.Param_Setting.en_200_gray == 1 && m_config.g200params.color == false)) + lutpath = "/usr/local/huago/Graylut200gray.bmp"; + else if ((m_fpgaparam.DpiMode == 2) && (gray_.Param_Setting.en_300_gray == 1 && m_config.g200params.color == false)) + lutpath = "/usr/local/huago/Graylut300gray.bmp"; + else if ((m_fpgaparam.DpiMode == 3) && (gray_.Param_Setting.en_600_gray == 1 && m_config.g200params.color == false)) + lutpath = "/usr/local/huago/Graylut600gray.bmp"; + else if ((m_fpgaparam.DpiMode == 16) && (gray_.Param_Setting.en_slow_gray == 1 && m_config.g200params.color == false)) + lutpath = "/usr/local/huago/Graylutslow_moiregray.bmp"; + else if ((m_fpgaparam.DpiMode == 17) && (gray_.Param_Setting.en_slow_300_gray == 1 && m_config.g200params.color == false)) + lutpath = "/usr/local/huago/Graylutslow_moire300gray.bmp"; + else if ((m_fpgaparam.DpiMode == 32) && (gray_.Param_Setting.en_long_Manuscript_200_gray == 1 && m_config.g200params.color == false)) + lutpath = "/usr/local/huago/GraylutLong_Manuscript200gray.bmp"; + else if ((m_fpgaparam.DpiMode == 33) && (gray_.Param_Setting.en_long_Manuscript_300_gray == 1 && m_config.g200params.color == false)) + lutpath = "/usr/local/huago/GraylutLong_Manuscript300gray.bmp"; + initLut(lutpath, m_config.g200params.color); +} + +void MultiFrameCapture_8458Color::close() +{ + if (video.get()) + video->close(); + // if(pimgdata_info.pdata) free(pimgdata_info.pdata); + // pimgdata_info.pdata = nullptr; + pimgdata_info.offset = pimgdata_info.frame_count = pimgdata_info.img_h = pimgdata_info.img_w = 0; + printf("pimgdata_ free !!!!!\n"); + + // fpgaComm->resetADC(); + // fpga_reload(); +} + +void MultiFrameCapture_8458Color::Fpga_regsAccess_reset(bool enable){ + if(fpgaComm.get()) + fpgaComm->regsAccess_reset(enable); + if (enable) + { + set_ADC_config_frequency(12); + init_adc_8458(); + } +} + +void MultiFrameCapture_8458Color::start() +{ + if (video.get()) + video->start(); +} + +void MultiFrameCapture_8458Color::MultiFrameCapture_8458Color::stop() +{ + if (video.get()) + video->stop(); +} + +bool MultiFrameCapture_8458Color::is_runing() +{ + return false; +} + +// static void printlog(std::string str) +// { +// std::ofstream o("/root/log.txt",std::ios::app|std::ios::binary); +// if(o.is_open()) +// { +// o << str <capture(); + printf("snap start !!!!! \n"); + b_stop_snap = false; + pimgdata_info.offset = pimgdata_info.frame_count = + pimgdata_info.img_h = pimgdata_info.img_w = 0; + snap_fu = snapthread.enqueue([this]{ + auto snap_func = [this](int height,int width, int channels, bool last_frame, unsigned int frame_index) + { + StopWatch sw; + void *data = video->read_frame(500); + if (data) + { + update_imgdatainfo(data,height,width); + printf("memcpy date size = %d times = %f index = %d \n",height*width,sw.elapsed_ms(),frame_index); + } + else + { + printf("!!!!!!!!!! error read frame losted, i = %d \n", frame_index); + //printlog("!!!!!!!!!! error read frame losted"); + } + }; + int width = 3672*3*(m_config.g200params.dpi == 3 ? 2 : 1)*2; + int height = frame_height; + for (int i = 1; i <= frame_count; i++) + { + curr_frame_snap_index = i; + snap_func(height,width, 0, (i == frame_count), i); + if (b_stop_snap) + { + int snaped_frame_count = fpgaComm->getFrame_counter_val(); + printf("!!!!!!!!!! revsed frame count = %d i = %d \n", snaped_frame_count, i); + if (snaped_frame_count > i && snaped_frame_count > 0) // 正常情况下 snaped_frame_count 一定大于0 + { + int reversed_frame_count = snaped_frame_count - i; + for (int j = 1; j <= reversed_frame_count; j++) + { + curr_frame_snap_index =j+i; + snap_func(height, width,0, ((i + j) == reversed_frame_count), i + j); + } + } + break; // 跳出当前读取多帧循环 + } + } + printf("snap end !!!!! \n"); }); +} + +void MultiFrameCapture_8458Color::snap(frame_data_info info) +{ + printf("snap start !!!!! \n"); + b_stop_snap = false; + info.offset = info.frame_count = info.img_h = info.img_w = 0; + snap_fu = snapthread.enqueue([this, info]{ + frame_data_info frame_info {0}; + frame_info.pdata = info.pdata; + frame_info.total = info.total; + auto snap_func = [this,&frame_info](int height,int width, int channels, bool last_frame, unsigned int frame_index) + { + StopWatch sw; + void *data = video->read_frame(500); + if (data) + { + update_imgdatainfo(data,frame_info,height,width); + printf("memcpy date size = %d times = %f index = %d \n",height*width,sw.elapsed_ms(),frame_index); + } + else + printf("!!!!!!!!!! error read frame losted, i = %d \n", frame_index); + + }; + int width = 3672*3*(m_config.g200params.dpi == 3 ? 2 : 1)*2; + int height = frame_height; + for (int i = 1; i <= frame_count; i++) + { + curr_frame_snap_index = i; + snap_func(height,width, 0, (i == frame_count), i); + if (b_stop_snap) + { + int snaped_frame_count = fpgaComm->getFrame_counter_val(); + printf("!!!!!!!!!! revsed frame count = %d i = %d \n", snaped_frame_count, i); + if (snaped_frame_count > i && snaped_frame_count > 0) // 正常情况下 snaped_frame_count 一定大于0 + { + int reversed_frame_count = snaped_frame_count - i; + for (int j = 1; j <= reversed_frame_count; j++) + { + curr_frame_snap_index = i+j; + snap_func(height, width,0, ((i + j) == reversed_frame_count), i + j); + } + } + break; // 跳出当前读取多帧循环 + } + } + pimgdata_info = frame_info; + printf("snap end !!!!! \n"); }); +} + +cv::Size MultiFrameCapture_8458Color::frame_data_size() +{ + return {2 * 3672*3*(m_config.g200params.dpi == 3 ? 2 : 1), frame_height * frame_count}; +} + +void MultiFrameCapture_8458Color::stopsnap() +{ + b_stop_snap = true; + if(snap_fu.valid()) snap_fu.get(); +} + +int MultiFrameCapture_8458Color::getautosizeheight() +{ + unsigned int val; + unsigned int reg8 = 0; + + fpgaComm->read(8, reg8); + // std::cout << "1 reg[8]:" << string_format("0x%08x", reg8) << std::endl; + // fpgaComm->update(4); + fpgaComm->read(14, val); + int regv = val; + val &= 0x0000ffff; + // std::cout << string_format("ONE height = %d reg[14] = %d \n", val, regv); + // fpgaComm->update(5); + fpgaComm->write(8, reg8 & 0xfffffff7); + // std::cout << string_format("ONE reg[8] = %d \n", reg8 & 0xfffffff7); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + // fpgaComm->update(6); + fpgaComm->read(14, val); + regv = val; + val &= 0x0000ffff; + fpgaComm->read(8, reg8); + // std::cout << "2 reg[8]:" << string_format("0x%08x", reg8) << std::endl; + std::cout << string_format("TWO height = %d reg[14] = %d \n", val, regv); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + fpgaComm->write(8, reg8 | 0x8); + // fpgaComm->write(8,0x02260008); + // fpgaComm->update(7); + // fpgaComm->read(8, reg8); + // std::cout << "2 reg[8]:" << string_format("0x%08x", reg8) << std::endl; + return val; + + // return fpgaComm->getFrameHeight(); +} +void MultiFrameCapture_8458Color::set_size(int width, int height) +{ + if (video.get()) + video->set_size(width, height); +} + +void MultiFrameCapture_8458Color::set_sp(int sp) +{ + fpgaComm->setSp(sp); +} + +void *MultiFrameCapture_8458Color::readFrame(int timeout) +{ + return video->read_frame(timeout); +} +cv::Mat MultiFrameCapture_8458Color::read_one_frame() +{ + + return cv::Mat(); +} +frame_data_info MultiFrameCapture_8458Color::ReadMultiFrame(int state) +{ + printf(" ReadMultiFrame state : %d \n", state); + if (state & 1) + b_stop_snap = true; + if (snap_fu.valid()) + snap_fu.get(); + if ((state & 0x2) || (!pimgdata_info.pdata)) + return {0}; + return pimgdata_info; +} + +void MultiFrameCapture_8458Color::set_gain(int ix, int val) +{ + for (int i = 0; i < 6; i++) + { + if (ix) + fpgaComm->setAGain(i, val); + else + fpgaComm->setBGain(i, val); + } +} + +void MultiFrameCapture_8458Color::set_offset(int ix, int val) +{ + for (int i = 0; i < 6; i++) + { + if (ix) + fpgaComm->setAOffset(i, val); + else + fpgaComm->setBOffset(i, val); + + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } +} + +void MultiFrameCapture_8458Color::set_expo(int ix, int val) +{ + switch (ix) + { + case 0: + fpgaComm->setAExposureR(val); + break; + case 1: + fpgaComm->setAExposureG(val); + break; + case 2: + fpgaComm->setAExposureB(val); + break; + case 3: + fpgaComm->setBExposureR(val); + break; + case 4: + fpgaComm->setBExposureG(val); + break; + case 5: + fpgaComm->setBExposureB(val); + break; + default: + break; + } + std::this_thread::sleep_for(std::chrono::milliseconds(1)); +} + +std::shared_ptr MultiFrameCapture_8458Color::regs() +{ + return fpgaComm; +} + +void MultiFrameCapture_8458Color::reset() +{ + fpga_reset(); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + fpgaComm->resetADC(); + // fpgaComm->setDelayTime(0X3e8); + // fpgaComm->setRegs(0x00, fpgaComm->getRegs(0x00)); + // fpgaComm->setRegs(0x01, fpgaComm->getRegs(0x01)); +} + +int MultiFrameCapture_8458Color::width() +{ + // int dpi = fpgaComm->getDpi(); + // int channel = 1; + // int width = dpi == 0x02 ? 1296 * channel : (dpi == 0x03 ? (2592 * channel) : (864 * channel)); + // printf("get width = %d \n", width); + //return width; + return 3672 *(m_config.g200params.dpi == 3 ? 2 : 1); +} + +int MultiFrameCapture_8458Color::height() +{ + return fpgaComm->getFrameHeight(); +} + +int MultiFrameCapture_8458Color::color() +{ + return fpgaComm->getColorMode() ? 16 : 0; +} + +void MultiFrameCapture_8458Color::init_autocorrect(int colormode) +{ + std::thread t_correctthread = std::thread(&MultiFrameCapture_8458Color::correctcolor, this, colormode); + t_correctthread.detach(); +} + +void MultiFrameCapture_8458Color::configFPGAParam(int mode, int dpi) +{ + printf("dpi = %d mode = %d \n", dpi, mode); + //fpgaComm->resetADC(); + FPGAConfigParam fpgaparam = GetFpgaparam(dpi, mode); + // int offF[6]={0,0,0,0,0,200}; + // int offB[6]={0,0,0,0,0,0}; + for (int i = 0; i < 6; i++) + { + if (i < 3) + { + set_expo(i, fpgaparam.ExposureF[i]); + printf("fpgaparam.ExposureF[%d] = %d \n", i, fpgaparam.ExposureF[i]); + } + else + { + set_expo(i, fpgaparam.ExposureB[i % 3]); + printf("fpgaparam.ExposureB[%d] = %d \n", i, fpgaparam.ExposureB[i % 3]); + } + + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + fpgaComm->setAOffset(i, fpgaparam.OffsetF[i]); + // fpgaComm->setAOffset(i,offF[i]); + printf("fpgaparam.setAOffset[%d] = %d \n", i, fpgaparam.OffsetF[i]); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + fpgaComm->setBOffset(i, fpgaparam.OffsetB[i]); + // fpgaComm->setBOffset(i, offB[i]); + printf("fpgaparam.OffsetB[%d] = %d \n", i, fpgaparam.OffsetB[i]); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + fpgaComm->setAGain(i, fpgaparam.GainF[i]); + printf("fpgaparam.GainF[%d] = %d \n", i, fpgaparam.GainF[i]); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + fpgaComm->setBGain(i, fpgaparam.GainB[i]); + printf("fpgaparam.GainB[%d] = %d \n", i, fpgaparam.GainB[i]); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + } +} + +void MultiFrameCapture_8458Color::openDevice(int dpi, int mode) +{ + fpgaComm->set_cis_type(true); + int config_dpi = dpi == 1 ? 2 : dpi; + int channelwidth = config_dpi == 0x02 ? 1296 : (config_dpi == 0x03 ? 2592 : 864); + int channels = mode == 0x01 ? 3 : 1; + int width = channelwidth * channels; + int c_frame_height = mode == 0x01 ? 100 * 3 : 100; + FPGAConfigParam fpgaparam = GetFpgaparam(dpi, mode); + + fpgaComm->read(15,m_fpgaversion); + printf("m_fpgaversion =%d \n",m_fpgaversion); + int startsample = 208; + + + printf("fpgaparam.sp=%d exp=%d gain=%d offset=%d LUT=%s", fpgaparam.Sp, fpgaparam.ExposureB[0], fpgaparam.GainB[0], fpgaparam.OffsetB[0], fpgaparam.LutPath.c_str()); + // int startsample= cistype.GetCisType()==CISVendor::DUNNAN_CIS_V0?205:262; + float v_ratio = *((float*)(&fpgaparam.VRatio)); + fpgaparam.Sp *= v_ratio; + printf("\n openDevice apply sp = %d, v_ratio =%f",fpgaparam.Sp,v_ratio); + ModeFpga fpgamod = { + .colorMode = mode, + .dpi = config_dpi, + .led = 1, + .sample = startsample, // 256+39 + .adcA = 0, + .adcB = 0, + .selftest = 0, + .sp = fpgaparam.Sp}; // 600DPI 0x1450 300DPI 0xe10 + fpgaComm->setRegs(0x01, *((int *)(&fpgamod))); + fpgaComm->setSample(startsample); + fpgaComm->enableLed(true); + fpgaComm->setEnTestCol(false); + fpgaComm->setEnTestBit(false); + set_dpi_mode(dpi == 3); + configFPGAParam(mode, dpi); + fpgaComm->setFrame_interval_max(0x1010); //dpi > 2 ? 7200 : 3600 + fpgaComm->setFrame_interval_min(0xa98); //dpi > 2 ? 900 : 1540 + video->open(width, 100 * 2); // 300dpi 7344/2 600dpi 7344 //FRAME_HEIGHT * 2 + printf("opened video with width = %d height = %d \n", width, c_frame_height); + fpgaComm->setFrameHeight(c_frame_height); + fpgaComm->setFrameNum(1); + for (int i = 0; i < 1; i++) + { + fpgaComm->capture(); // abort first frame + video->read_frame(200); + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + printf("abort first frame \n"); + } +} + +void MultiFrameCapture_8458Color::creatcorrectconfig(int dpi, int mode) +{ + printf(" opendevice"); + openDevice(dpi, mode); + printf(" opendevice end "); + bool isDone = false; + int i = 1; + initStep1(); + while (!isDone) //先暗场 + { + std::string log = "==============================第" + std::to_string(i) + "次==============================="; + ft_m_log.append_log(log); + configFPGAParam(mode, dpi); + ft_m_log.append_log(log); + fpgaComm->enableLed(false); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + fpgaComm->capture(); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + isDone = saveLutImg(dpi, mode, true); // 0 color_black 1 color_white 2 gray_balck 3 gray_white + i++; + } + i = 1; + isDone = false; + initStep1(); + while (!isDone) //后明场 + { + configFPGAParam(mode, dpi); + std::string log = "==============================第" + std::to_string(i) + "次==============================="; + ft_m_log.append_log(log); + fpgaComm->enableLed(true); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + fpgaComm->capture(); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + isDone = saveLutImg(dpi, mode, false); + i++; + } + printf("creatcorrectconfig %s \n", (mode == IMAGE_COLOR ? " Color" : " Gray")); + //creatLUTData(dpi, mode); + video->close(); +} + +static int savelutindex = 0; +bool MultiFrameCapture_8458Color::saveLutImg(int dpi, int mode, bool black) +{ + int config_dpi = dpi == 1 ? 2 : dpi; + int offset_indexs[] = {0, 1, 2, 5, 4, 3, 3, 4, 5, 2, 1, 0}; + int channels = mode == IMAGE_COLOR ? 3 : 1; + int height = 100; + int width = config_dpi == 0x02 ? 1296 : (config_dpi == 0x03 ? 2592 : 864); + int orgimgwidth = width * 2 * 3 * channels; + int dstwidth = width * 2 * 3; + + bool isNeedSave = true; + std::string log; + void *data = video->read_frame(10000); + if (data == NULL) + { + isNeedSave = false; + log = "WARNNING WARNNING WARNNING FAILDED TO READ IMAGE DATA !!!!!!!!!!!!!!!!!!!\r\n"; + ft_m_log.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + return isNeedSave; + } + cv::Mat src(height, orgimgwidth, CV_8UC1, data); + //cv::imwrite(std::to_string(savelutindex++) + ".jpg", src); + + CImageMerge t_marge; + cv::Mat mrgmat = t_marge.MergeImage(mode == 0x01, src, dstwidth, height,m_fpgaversion); + mrgmat = mrgmat(cv::Rect(0,20,mrgmat.cols,mrgmat.rows-20)); + // return false; + FPGAConfigParam param = GetFpgaparam(dpi, mode); + + if (black) //暗场 + { + double offValues[12]; + std::vector bflags; + for (volatile int n = 0; n < 2; n++) + { + cv::Mat img = mrgmat(cv::Rect(mrgmat.cols * n / 2, 10, mrgmat.cols / 2, mrgmat.rows - 10)).clone(); + int offset_total = 0; + for (volatile int s = 0; s < 6; s++) // + { + int k = n * 6 + s; + int offset_wdth; + if ((k == 5) || (k == 6)) + { + offset_wdth = config_dpi == 0x03 ? 864 : (config_dpi == 0x02 ? 432 : 288); + } + else + { + offset_wdth = config_dpi == 0x03 ? 1296 : (config_dpi == 0x02 ? 648 : 432); + } + + double min,max; + //auto t_mat= img(cv::Rect(offset_total, 10, offset_wdth, img.rows - 10)); + //cv::minMaxLoc(t_mat,&min,&max); + cv::Scalar mean = cv::mean(img(cv::Rect(offset_total, 10, offset_wdth, img.rows - 10))); + //printf("AAAAAAAAAAAAAAAAAAAAAAAAAAA min = %.2f max= %.2f mean = %0.2f \n",min,max); + offset_total += offset_wdth; + offValues[k] = mean.val[0]; + printf("\noffValues[%d] = %f",k,mean.val[0]); + bflags.push_back(false); + //offValues[k] = min; + } + } + + // std::string clrmode = (mode == 0x01 ? "彩色" : " 灰度"); + // log = "开始" + clrmode + "暗场校正 \n"; + for (volatile int s = 0; s < 2; s++) + { + int offsets[6]; // = (int *)(s == 0 ? ¶m.OffsetF[0] : ¶m.OffsetB[0]); + memcpy(offsets, (s == 0 ? ¶m.OffsetF[0] : ¶m.OffsetB[0]), sizeof(param.OffsetF)); + for (volatile int j = 0; j < 6; j++) + { + int k = s * 6 + j; + double diff = BLACK_DIFF(offValues[k]); + //double diff = 3-offValues[k]; + double step = radio * diff; + int preStep = offsetStep1[k]; + printf("offsetStep1[%d]=%d \n",k,offsetStep1[k]); + if (step * preStep < 0) + { + step = 0 - preStep / 2; + } + else + { + radio = 1; + } + + if (step < 1 && step > 0) + step = 1; + if (step < 0 && step > -1) + step = -1; + + + // FMT_STEP(step); + bool isMinStep = abs(step) == 1 && step == offsetStep1[k]; + bool isOutBounds = offsets[j] >= 255 && step > 0; + isOutBounds |= offsets[j] <= 0 && step < 0; + log += " 暗场校正 :" + std::to_string(k) + ";diff:" + std::to_string(diff) + ";light:" + std::to_string(offValues[k]) + ";offset:" + std::to_string(offsets[j]) + ";step:" + std::to_string(step) + "\r\n"; + if (isOutBounds) + log += " 第" + std::to_string(k) + "条带暗场校正异常,暗场值无法降低 \r\n"; + else if (abs(step) > 1 || isMinStep) + { + offsetStep1[k] = (int)(step); + offsets[offset_indexs[k]] += step; + log += "offsetStep1" + std::to_string(k) + " = " + std::to_string(offsetStep1[k]) + ", offset_indexs" + std::to_string(k) + " =" + std::to_string(offset_indexs[k]) + "\r\n"; + + if (offsets[offset_indexs[k]] < 1) + offsets[offset_indexs[k]] = 1; + if (offsets[offset_indexs[k]] > 255) + offsets[offset_indexs[k]] = 255; + //isNeedSave = false; + bflags[k] = false; + } + else + { + bflags[k] = true; + printf("channel[%d] black correct done\n",k); + } + + + log += (s == 0 ? "彩色正面" : "彩色背面"); + log += "偏移值:" + std::to_string(offsets[0]) + "," + std::to_string(offsets[1]) + "," + std::to_string(offsets[2]) + "," + std::to_string(offsets[3]) + "," + std::to_string(offsets[4]) + "," + std::to_string(offsets[5]) + "\r\n"; + // log += (s == 0 ? "彩色正面暗场校正完成 \r\n" : "彩色背面暗场校正完成 \r\n"); + ft_m_log.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + log = ""; + } + auto siez = sizeof(param.OffsetF); + memcpy((s == 0 ? ¶m.OffsetF[0] : ¶m.OffsetB[0]), offsets, sizeof(param.OffsetF)); + } + + for(int i = 0;i 30) + radio = 2; + else + radio = 1; + double step = diff * radio; + int preStep = *((int *)expStep + k); + if (step * preStep < 0) + { + step = 0 - preStep / 2; + } + if (step < 1 && step > 0) + step = 1; + if (step < 0 && step > -1) + step = -1; + + bool isMinStep = abs(step) == 1 && step == *((int *)expStep + k); + bool isOutBounds = exposures[x] >= (param.Sp -5) && step > 0; + isOutBounds |= exposures[x] <= 0 && step < 0; + if (isOutBounds) + log += " 第" + std::to_string(x) + "个明场校正异常 \r\n"; + else if (abs(diff) >= 1 || isMinStep) + { + *((int *)expStep + k) = (int)(step); + exposures[x] += step; + if (exposures[x] > (param.Sp -5)) + { + exposures[x] = (param.Sp -5); + } + if (exposures[x] < 0) + exposures[x] = 0; + isNeedSave = false; + } + log += " 曝光值:" + std::to_string(exposures[x]) + "\r\n"; + log += " 调整步长:" + std::to_string(*((int *)expStep + k)) + "\r\n"; + } + memcpy((s == 0 ? ¶m.ExposureF[0] : ¶m.ExposureB[0]), exposures, sizeof(param.ExposureB)); + } + ft_m_log.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + + if (isNeedSave) + { + log = "彩色明场校正完成\r\n"; + if (m_captureCallback) + m_captureCallback(mode, log); + // log =""; + imwrite(param.Flat_WhitePath, mrgmat); + } + } + else + { + double values[2]; + values[0] = cv::mean(mrgmat(cv::Rect(0, 0, mrgmat.cols / 2, mrgmat.rows))).val[0]; + values[1] = cv::mean(mrgmat(cv::Rect(mrgmat.cols / 2, 0, mrgmat.cols / 2, mrgmat.rows))).val[0]; + log = "-----开始灰色明场校正-----\r\n"; + log += " 灰色扫描灰度明场均值:" + std::to_string(values[0]) + "," + std::to_string(values[1]) + "\r\n"; + if (m_captureCallback) + m_captureCallback(mode, log); + for (int s = 0; s < 2; s++) + { + int *exposures = (int *)(s == 0 ? param.ExposureF : param.ExposureB); + int diff = LIGHT_DIFF(param.MaxBright, values[s]); + if(abs(diff) > 30) + radio = 2; + else + radio = 1; + double step = diff * radio; + log += " 明场:" + std::to_string(s) + ";diff:" + std::to_string(diff) + "\r\n"; + int preStep = expStep[s][0]; + if (step * preStep < 0) + { + step = 0 - preStep / 2; + } + else + { + radio = 1; + } + if (step < 1 && step > 0) + step = 1; + if (step < 0 && step > -1) + step = -1; + + int exp = *(exposures + 1); + // std::string ss1(string_format("exp[%d] = %d step = %.3f \r\n", s, exp, step)); + // log += ss1; + bool isMinStep = abs(step) == 1 && step == expStep[s][0]; + bool isOutBounds = exp >= (param.Sp -5) && step > 0; + isOutBounds |= exp <= 0 && step < 0; + if (isOutBounds) + log += " 第" + std::to_string(s) + "个明场校正异常 \r\n"; + else if (abs(diff) > 1 || isMinStep) + { + exp += step; + if (exp < 0) + exp = 0; + if (exp >(param.Sp -5)) + exp = (param.Sp -5); + + float coffe[3] = {1, 1, 1}; // 0.2, 1,0.51 + for (int k = 0; k < 3; k++) + { + *(exposures + k) = (int)(exp * coffe[k]); + expStep[s][k] = (int)(step); + std::string exps(string_format("expStep[%d][%d] = %.3f\r\n", s, k, step)); + log += exps; + std::string ss(string_format("exposures[%d] = %0.3f \r\n", k, exposures[k])); + log += ss; + } + isNeedSave = false; + } + } + ft_m_log.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + if (isNeedSave) + { + printf("Save LUT image path :%s \n", param.Flat_WhitePath.c_str()); + log = "灰度明场校正完成\r\n"; + if (m_captureCallback) + m_captureCallback(mode, log); + log = ""; + imwrite(param.Flat_WhitePath, mrgmat); + } + } + } + SaveFpgaparam(param); + printf("exit Save_lut \n"); + return isNeedSave; +} + +void MultiFrameCapture_8458Color::correctcolor(int correctmode) +{ + printf(" correctcolor start \n"); + auto _start = std::chrono::steady_clock::now(); + ThreadPool pool(2); + std::queue> fu_correct; + std::string loginfo = "Start Correctcolor 200DPI COLOR \r\n"; + // if (m_captureCallback) + // m_captureCallback(0x01, loginfo); + creatcorrectconfig(0x01, IMAGE_COLOR); + auto param = GetFpgaparam(0x01,IMAGE_COLOR); + fu_correct.emplace(pool.enqueue([param](){creatLUTData(0x01,IMAGE_COLOR,param);})); + loginfo = "-----------200DPI COLOR Correct Done----------- \r\n\r\n Start Correctcolor 200DPI GRAY \r\n"; + if (m_captureCallback) + m_captureCallback(0x01, loginfo); + creatcorrectconfig(0x01, IMAGE_GRAY); + param = GetFpgaparam(0x01,IMAGE_GRAY); + fu_correct.emplace(pool.enqueue([param](){creatLUTData(0x01,IMAGE_GRAY,param);})); + loginfo = "-----------200DPI Gray Correct Done----------- \r\n\r\n Start Correctcolor 200DPI COLOR \r\n"; + if (m_captureCallback) + m_captureCallback(0x02, loginfo); + + creatcorrectconfig(0x02, IMAGE_COLOR); + param = GetFpgaparam(0x02,IMAGE_COLOR); + fu_correct.emplace(pool.enqueue([param](){creatLUTData(0x02,IMAGE_COLOR,param);})); + loginfo = "-----------300DPI COLOR Correct Done----------- \r\n\r\n Start Correctcolor 300DPI GRAY \r\n"; + if (m_captureCallback) + m_captureCallback(0x02, loginfo); + creatcorrectconfig(0x02, IMAGE_GRAY); + param = GetFpgaparam(0x02,IMAGE_GRAY); + fu_correct.emplace(pool.enqueue([param](){creatLUTData(0x02,IMAGE_GRAY,param);})); + loginfo = "-----------300DPI Gray Correct Done----------- \r\n\r\n Start Correctcolor 600DPI COLOR \r\n"; + + while(fu_correct.size()) + { + fu_correct.front().get(); + fu_correct.pop(); + } + loginfo = "******Correct Done****** time " + std::to_string(std::chrono::duration(std::chrono::steady_clock::now() - _start).count())+"s"; + if (m_captureCallback) + m_captureCallback(0x03, loginfo); +} + +void MultiFrameCapture_8458Color::fpga_reset() +{ + reset_pin->setValue(Gpio::Low); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + reset_pin->setValue(Gpio::High); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); +} + +void MultiFrameCapture_8458Color::fpga_reload() +{ + // fpga 代码重载 + fpgaLoad->setValue(Gpio::Low); + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + fpga_conf_initn->setValue(Gpio::Low); + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + printf("\n fpga_conf_done value %d",fpga_conf_done->getValue()); + fpgaLoad->setValue(Gpio::High); + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + fpga_conf_initn->setValue(Gpio::High); + //std::this_thread::sleep_for(std::chrono::milliseconds(5)); + printf("\n fpga_conf_done value %d",fpga_conf_done->getValue()); + // while(fpga_conf_done->getValue() == Gpio::GpioLevel::Low) + // std::this_thread::sleep_for(std::chrono::milliseconds(5)); + std::this_thread::sleep_for(std::chrono::seconds(3)); + printf("\n fpga_conf_done value %d",fpga_conf_done->getValue()); + fpgaComm->resetADC(); + fpgaComm->update(0); +} + + +void MultiFrameCapture_8458Color::init_imagedatabuffer() +{ + printf("pimgdata_info.pdata = %p \n", pimgdata_info.pdata); + if (pimgdata_info.pdata) + { + free(pimgdata_info.pdata); + pimgdata_info.pdata = nullptr; + } + if (frame_count != 0) + { + int t_frame_count = fpgaComm->getFrameNum(); + int width = this->width()*(m_config.g200params.color ? 3 : 1); + int height = frame_height*2; + pimgdata_info.pdata = malloc(height * t_frame_count*width ); + pimgdata_info.total = height * t_frame_count; + pimgdata_info.offset = 0; + pimgdata_info.frame_count = 0; + pimgdata_info.img_h = 0; + pimgdata_info.img_w = 0; + printf("pimgdata_info.pdata = %p malloc_size = %d \n", pimgdata_info.pdata, height * t_frame_count*width,t_frame_count,width,height); + } +} + +void MultiFrameCapture_8458Color::free_imagedatabuffer() +{ + if (pimgdata_info.pdata) + { + free(pimgdata_info.pdata); + pimgdata_info.pdata = nullptr; + } + printf("--- free pimgdata_info.pdata --- \n"); +} + +// static void neon_memcpy(volatile void *dst, volatile void *src, int sz) +// { +// if (sz & 63) +// sz = (sz & -64) + 64; +// asm volatile ( +// "NEONCopyPLD: \n" +// " VLDM %[src]!,{d0-d7} \n" +// " VSTM %[dst]!,{d0-d7} \n" +// " SUBS %[sz],%[sz],#0x40 \n" +// " BGT NEONCopyPLD \n" +// : [dst]"+r"(dst), [src]"+r"(src), [sz]"+r"(sz) : : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "cc", "memory"); +// } + +void MultiFrameCapture_8458Color::update_imgdatainfo(void *itemmat, frame_data_info &info, uint32_t h, uint32_t w) +{ + // StopWatch sw; + if (info.pdata && itemmat) + { + // neon_memcpy(pimgdata_info.pdata + pimgdata_info.offset,itemmat,h*w); + memcpy(info.pdata + info.offset, itemmat, h * w); + info.offset += h * w; + info.frame_count++; + info.img_h += h; + info.img_w = w; + // printf("offset = %d item_total = %d \n", pimgdata_info.offset,pimgdata_info.frame_count); + } + // printf("size = %d frame memcpy time = %fms \n", h*w,sw.elapsed_ms()); +} + +void MultiFrameCapture_8458Color::update_imgdatainfo(void *itemmat, uint32_t h, uint32_t w) +{ + if (pimgdata_info.pdata && itemmat) + { + memcpy(pimgdata_info.pdata + pimgdata_info.offset, itemmat, h * w); + pimgdata_info.offset += h * w; + pimgdata_info.frame_count++; + pimgdata_info.img_h += h; + pimgdata_info.img_w = w; + } +} + +void MultiFrameCapture_8458Color::init_adc_8458() +{ + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + for(int i =0;i<192;i++){ + write_adc_8458(bank_change[i/64],i%64,bank_value[i],1); + write_adc_8458(bank_change[i/64],i%64,bank_value[i],0); + } + std::this_thread::sleep_for(std::chrono::milliseconds(100)); +} + +void MultiFrameCapture_8458Color::write_adc_8458(int bank, int addr, int val,bool A_or_B) +{ + uint32_t reg5 = 0; + fpgaComm->read(5,reg5); + fpgaComm->write(5,reg5|0xc000); // adc 配置使能打开 + //std::this_thread::sleep_for(std::chrono::milliseconds(1)); + adc_8458_param p_adc{0}; + p_adc.param.r_or_w_h = p_adc.param.r_or_w_l = 1; + p_adc.param.addr_l = 0; + p_adc.param.addr_h = addr; + p_adc.param.val_l = bank; + p_adc.param.val_h = val; + fpgaComm->write(A_or_B ?4:7,p_adc.value); + uint32_t reg1_v; + fpgaComm->read(1,reg1_v); + Mode_FPGA reg1 = *((Mode_FPGA*)®1_v); + A_or_B ? reg1.adcA = 1 :reg1.adcB = 1 ; + fpgaComm->write(1,*((uint32_t*)®1)); + A_or_B ? reg1.adcA = 0 :reg1.adcB = 0 ; + fpgaComm->write(1,*((uint32_t*)®1)); + //std::this_thread::sleep_for(std::chrono::milliseconds(1)); + fpgaComm->write(5,reg5&0xffff3fff);// adc 配置使能关闭 +} + +uint32_t MultiFrameCapture_8458Color::read_adc_8458(int bank, int addr,bool A_or_B) +{ + uint32_t reg5 = 0; + fpgaComm->read(5,reg5); + fpgaComm->write(5,reg5|0xc000); // adc 配置使能打开 + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + adc_8458_param p_adc{0}; + p_adc.param.r_or_w_h = 1; + p_adc.param.r_or_w_l = 3; + p_adc.param.addr_l = 0; + p_adc.param.addr_h = addr; + p_adc.param.val_l = bank; + p_adc.param.val_h = 0; + fpgaComm->write(A_or_B ?4:7,p_adc.value); + uint32_t reg1_v; + fpgaComm->read(1,reg1_v); + Mode_FPGA reg1 = *((Mode_FPGA*)®1_v); + A_or_B ? reg1.adcA = 1 :reg1.adcB = 1 ; + fpgaComm->write(1,*((uint32_t*)®1)); + A_or_B ? reg1.adcA = 0 :reg1.adcB = 0 ; + fpgaComm->write(1,*((uint32_t*)®1)); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + fpgaComm->write(5,reg5&0xffff3fff);// adc 配置使能关闭 + uint32_t read_reg =0; + fpgaComm->read(3,read_reg); + return read_reg; +} + +void MultiFrameCapture_8458Color::set_dpi_mode(bool is_600) +{ + if(is_600) + { + write_adc_8458(bank_change[2],0x14,0x01,false); + write_adc_8458(bank_change[2],0x14,0x01,true); + write_adc_8458(bank_change[2],0x16,0x01,false); + write_adc_8458(bank_change[2],0x16,0x01,true); + } + else + { + write_adc_8458(bank_change[2],0x14,0x02,false); + write_adc_8458(bank_change[2],0x14,0x02,true); + write_adc_8458(bank_change[2],0x16,0x03,false); + write_adc_8458(bank_change[2],0x16,0x03,true); + } +} + +void MultiFrameCapture_8458Color::set_exp_8458_double(int exp, int sp,bool A_or_B) +{ + int pix_counter = (sp -10) /2; + set_pixel_count_8458(pix_counter); + int exp_max = pix_counter - 80 - 80 - 10; + if((exp * 2) > exp_max) + exp = exp_max / 2; + write_adc_8458(bank_change[1],1,0,A_or_B); + write_adc_8458(bank_change[1],2,80,A_or_B); + write_adc_8458(bank_change[1],3,((exp+80)&0xff00)/0x100,A_or_B); + write_adc_8458(bank_change[1],4,(exp+80)&0xff,A_or_B); + write_adc_8458(bank_change[1],5,((pix_counter/2+80)&0xff00)/0x100,A_or_B); + write_adc_8458(bank_change[1],6,(pix_counter/2+80)&0xff,A_or_B); + write_adc_8458(bank_change[1],7,((pix_counter/2+exp+80)&0xff00)/0x100,A_or_B); + write_adc_8458(bank_change[1],8,(pix_counter/2+exp+80)&0xff,A_or_B); + + +} +void MultiFrameCapture_8458Color::set_led_off() +{ + for(int i =0; i < 2 ;i++){ + write_adc_8458(bank_change[1],1,0,i); //led off + write_adc_8458(bank_change[1],2,0,i); + write_adc_8458(bank_change[1],3,0,i); + write_adc_8458(bank_change[1],4,0,i); + write_adc_8458(bank_change[1],5,0,i); + write_adc_8458(bank_change[1],6,0,i); + write_adc_8458(bank_change[1],7,0,i); + write_adc_8458(bank_change[1],8,0,i); + } +} + + +void MultiFrameCapture_8458Color::set_exp_8458_single(int exp,int sp,bool A_or_B){ + int pix_counter = (sp -10) /2; + set_pixel_count_8458(pix_counter); + int exp_max = pix_counter - 80 - 10; + if(exp > exp_max) + exp = exp_max; + write_adc_8458(bank_change[1],1,0,A_or_B); + write_adc_8458(bank_change[1],2,1,A_or_B); + write_adc_8458(bank_change[1],3,((exp+80)&0xff00)/0x100,A_or_B); + write_adc_8458(bank_change[1],4,(exp+80)&0xff,A_or_B); + write_adc_8458(bank_change[1],5,0,A_or_B); + write_adc_8458(bank_change[1],6,0,A_or_B); + write_adc_8458(bank_change[1],7,0,A_or_B); + write_adc_8458(bank_change[1],8,0,A_or_B); +} + + +void MultiFrameCapture_8458Color::set_pixel_count_8458(int val) +{ + write_adc_8458(bank_change[0],54,(val&0xff00)/0x100,true); + write_adc_8458(bank_change[0],54,(val&0xff00)/0x100,false); + write_adc_8458(bank_change[0],55,val&0xff,true); + write_adc_8458(bank_change[0],55,val&0xff,false); +} + +void MultiFrameCapture_8458Color::set_analog_gain_8458(int r1, int r2, int g1, int g2, int b1, int b2, bool A_or_B) +{ + write_adc_8458(bank_change[0],10,r1*0x10+g1,A_or_B); //max 7 + write_adc_8458(bank_change[0],11,b1*0x10+r2,A_or_B); + write_adc_8458(bank_change[0],12,g2*0x10+b2,A_or_B); +} + +void MultiFrameCapture_8458Color::set_analog_offset_8458(int type,int val,bool A_or_B){ + if(type >=4 && type <= 9) + write_adc_8458(bank_change[0],type,val,A_or_B); //max 32 299mv 8.3mv +} + + +void MultiFrameCapture_8458Color::set_digital_offset_8458(int type,int val, bool A_or_B) +{ + int addr = 13 + type*2; + write_adc_8458(bank_change[0],addr,(val&0x700)/0x100,A_or_B); + write_adc_8458(bank_change[0],addr+1,val&0xff,A_or_B); +} + +void MultiFrameCapture_8458Color::set_digital_gain_8458(int type,int val, bool A_or_B) +{ + int addr = 19 + type*2; + write_adc_8458(bank_change[0],addr,(val&0xff00)/0x100,A_or_B); + write_adc_8458(bank_change[0],addr+1,val&0xff,A_or_B); +} + + +void MultiFrameCapture_8458Color::set_ADC_config_frequency(uint32_t freq) +{ + uint32_t reg2 = 0; + fpgaComm->read(2, reg2); + fpgaComm->write(2, (reg2 & 0xffffffe1) | (freq << 1)); // adc 配置 频率 +} +void MultiFrameCapture_8458Color::single_correct(std::uint32_t mode) +{ + std::vector sup_correct_dpi{1, 2, 3, 0x10, 0x11,0x20,0x21}; + union correct_mode_ + { + struct + { + uint32_t dpi : 16; + uint32_t color_mode : 8; + uint32_t correct_mode : 8; + } param; + uint32_t value; + }; + correct_mode_ tmp; + tmp.value = mode; + if (std::count(sup_correct_dpi.begin(), sup_correct_dpi.end(), tmp.param.dpi) && (tmp.param.color_mode < 2)) + { + auto param = Get_Static_CorrectParam().GetFpgaparam(tmp.param.dpi, tmp.param.color_mode); + if (tmp.param.correct_mode == 1) + creatLUTData(tmp.param.dpi, tmp.param.color_mode, param); + else if (tmp.param.correct_mode == 2) + creatLUTData_gray(tmp.param.dpi, tmp.param.color_mode, param); + } +} \ No newline at end of file diff --git a/capimage/MultiFrameCapture_8458Color.h b/capimage/MultiFrameCapture_8458Color.h new file mode 100644 index 0000000..6cac96a --- /dev/null +++ b/capimage/MultiFrameCapture_8458Color.h @@ -0,0 +1,222 @@ +#pragma once +#include "ICapturer.h" +#include "ThreadPool.h" +class FpgaComm; +class gVideo; +class Gpio; + +class MultiFrameCapture_8458Color : public ICapturer +{ +public: + MultiFrameCapture_8458Color(); + virtual ~MultiFrameCapture_8458Color(); + virtual void open(); + virtual void open(HGScanConfig config,FPGAConfigParam fpgaparam); + virtual void open(HGScanConfig config, FPGAConfigParam_8478 fpgaparam){} + virtual void close(); + virtual void start(); + virtual void stop(); + virtual bool is_runing(); + virtual void snap(); + virtual void snap(frame_data_info info); + virtual cv::Size frame_data_size(); + virtual void stopsnap(); + virtual int getautosizeheight(); + virtual void set_size(int width, int height); + virtual void set_sp(int sp); + + virtual void *readFrame(int timeout); + virtual frame_data_info ReadMultiFrame(int state); + virtual void set_gain(int ix, int val); + virtual void set_offset(int ix, int val); + virtual void set_expo(int ix, int val); + + virtual std::shared_ptr regs(); + virtual void reset(); + virtual int width(); + virtual int height(); + virtual int color(); + virtual void init_autocorrect(int colormode); + virtual void setcapturecall(std::function callback) + { + m_captureCallback = callback; + }; + virtual void Fpga_regsAccess_reset(bool enable); + + virtual uint32_t multi_frame_counts() { return frame_count; } + virtual uint32_t multi_curr_snap_index() { return curr_frame_snap_index; } + virtual void single_correct(std::uint32_t mode); + virtual cv::Mat read_one_frame() override; + + void init_imagedatabuffer(); + void free_imagedatabuffer(); + void update_imgdatainfo(void *itemmat, frame_data_info &info, uint32_t h, uint32_t w); + void update_imgdatainfo(void *itemmat, uint32_t h, uint32_t w); + +private: + void configFPGAParam(int mode, int dpi); + void init_lutdate(); + void openDevice(int dpi, int mode); + void creatcorrectconfig(int dpi, int mode); + bool saveLutImg(int dpi, int mode, bool black); + void correctcolor(int correctmode); + + void fpga_reset(); + void fpga_reload(); + + void init_adc_8458(); + void write_adc_8458(int bank,int addr,int val,bool A_or_B); + uint32_t read_adc_8458(int bank,int addr,bool A_or_B); + void set_exp_8458_double(int exp,int sp,bool A_or_B); + void set_exp_8458_single(int exp,int sp,bool A_or_B); + void set_pixel_count_8458(int val); + void set_analog_gain_8458(int r1,int r2,int g1,int g2,int b1,int b2,bool A_or_B); + void set_analog_offset_8458(int type,int val,bool A_or_B); + void set_digital_offset_8458(int type,int val,bool A_or_B); + void set_digital_gain_8458(int type,int val,bool A_or_B); + void set_ADC_config_frequency(uint32_t freq); + void set_led_off(); + void set_dpi_mode(bool is_600); + +private: + std::function m_captureCallback; + std::shared_ptr video; + std::shared_ptr vdd_cis_3voff_pin; + std::shared_ptr vdd_vis_5ven_pin; + std::shared_ptr reset_pin; + std::shared_ptr image_in_transfer_pin; + std::shared_ptr initDone_pin; + std::shared_ptr fpgaLoad; + std::shared_ptr fpgaComm; + std::shared_ptr fpga_conf_initn; + std::shared_ptr fpga_conf_done; + ThreadPool snapthread; + uint32_t m_fpgaversion; + uint32_t frame_height; + uint32_t frame_count; + uint32_t curr_frame_snap_index; + const int FPGA_MAX_HEIGHT_SUP=1048576; + frame_data_info pimgdata_info; + std::future snap_fu; + bool bcorrecting; + bool b_stop_snap; + std::thread m_correctthread; + HGScanConfig m_config; + FPGAConfigParam m_fpgaparam; + + const uint8_t bank_value_b[192] = + {0x01,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 //300*600 dpi + ,0x44,0x64,0x46,0x00,0x64,0x00,0x64,0x00,0x64,0x00 + ,0xc8,0x00,0x64,0x00,0xc8,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xA1,0x01 + ,0x44,0x43,0x45,0x09,0x02,0x02,0x02,0x00,0x2A,0x14 + ,0x34,0x05,0x00,0x01,0x13,0xc4,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00 + ,0x41,0x00,0x50,0x09,0xe2,0x0a,0x32,0x13,0xc3,0x00 + //,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00 + ,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00 + ,0x02,0x00,0x03,0x02,0x00,0x60,0x00,0x6d,0x00,0x60 + //,0x02,0x00,0x03,0x02,0x00,0x5c,0x00,0x5D,0x00,0x60 + ,0x07,0x8C,0x0A,0x5F,0x00,0x03,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00}; + + + const uint8_t bank_value[192] = + // {0x01,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 //300*300 dpi + // ,0x44,0x64,0x46,0x00,0x64,0x00,0x64,0x00,0x64,0x00 + // ,0xc8,0x00,0x64,0x00,0xc8,0x00,0x00,0x00,0x00,0x00 + // ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xA1,0x01 + // ,0x44,0x43,0x45,0x09,0x02,0x02,0x02,0x00,0x2A,0x14 + // ,0x34,0x05,0x00,0x01,0x13,0xc4,0x00,0x00,0x00,0x00 + // ,0x00,0x00,0x00,0x00 + // ,0x41,0x00,0x50,0x09,0xe2,0x0a,0x32,0x13,0xc3,0x00 + // //,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + // ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + // ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + // ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + // ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + // ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + // ,0x00,0x00,0x00,0x00 + // ,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + // ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00 + // ,0x02,0x00,0x03,0x04,0x00,0x60,0x00,0x6D,0x00,0x60 + // ,0x07,0x8C,0x0A,0x5F,0x00,0x03,0x00,0x00,0x00,0x00 + // ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + // ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + // ,0x00,0x00,0x00,0x00}; + + // {0x01,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 //300*600 dpi + // ,0x44,0x64,0x46,0x00,0x64,0x00,0x64,0x00,0x64,0x00 + // ,0xc8,0x00,0x64,0x00,0xc8,0x00,0x00,0x00,0x00,0x00 + // ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xA1,0x01 + // ,0x44,0x43,0x45,0x09,0x02,0x02,0x02,0x00,0x2A,0x14 + // ,0x34,0x05,0x00,0x01,0x13,0xc4,0x00,0x00,0x00,0x00 + // ,0x00,0x00,0x00,0x00 + // ,0x41,0x00,0x50,0x09,0xe2,0x0a,0x32,0x13,0xc3,0x00 + // //,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + // ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + // ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + // ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + // ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + // ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + // ,0x00,0x00,0x00,0x00 + // ,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + // ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00 + // ,0x02,0x00,0x03,0x02,0x00,0x60,0x00,0x6D,0x00,0x60 + // //,0x02,0x00,0x03,0x02,0x00,0x61,0x00,0x66,0x00,0x60 + // //,0x02,0x00,0x03,0x02,0x00,0x5c,0x00,0x5D,0x00,0x60 + // ,0x07,0x8c,0x0A,0x5F,0x00,0x03,0x00,0x00,0x00,0x00 + // ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + // ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + // ,0x00,0x00,0x00,0x00}; + + + {0x01,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 //600*600 dpi + ,0x44,0x64,0x46,0x00,0x64,0x00,0x64,0x00,0x64,0x00 + ,0xc8,0x00,0x64,0x00,0xc8,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xA1,0x01 + ,0x44,0x43,0x45,0x09,0x02,0x02,0x02,0x00,0x2A,0x14 + ,0x34,0x05,0x00,0x01,0x13,0xc4,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00 + ,0x41,0x00,0x50,0x09,0xe2,0x0a,0x32,0x13,0xc3,0x00 + //,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00 + ,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00 + ,0x01,0x00,0x01,0x02,0x00,0x60,0x00,0x6D,0x00,0x60 + //,0x02,0x00,0x03,0x02,0x00,0x5c,0x00,0x5D,0x00,0x60 + ,0x07,0x8C,0x0A,0x5F,0x00,0x03,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + ,0x00,0x00,0x00,0x00}; + + const uint8_t bank_change[3] = {0x01,0x41,0x81}; + union adc_8458_param + { + struct + { + uint32_t val_l : 8; //数据位 + uint32_t addr_l : 6; //adc 寄存器地址 + uint32_t r_or_w_l :2; //读写标志位 0x11 读 0x01 写 + uint32_t val_h : 8; + uint32_t addr_h : 6; + uint32_t r_or_w_h :2; + }param; + uint32_t value; + }; + +}; diff --git a/capimage/MultiFrameCapture_8478_HL.cpp b/capimage/MultiFrameCapture_8478_HL.cpp new file mode 100644 index 0000000..0d21643 --- /dev/null +++ b/capimage/MultiFrameCapture_8478_HL.cpp @@ -0,0 +1,1550 @@ +#include "MonoCapturer.h" +#include "config.h" +#include "applog.h" +#include "gvideoisp1.h" +#include "Gpio.h" +#include "DevUtil.h" +#include "FpgaComm.h" +#include "CorrectParam.h" +#include "correct_ultis.h" +#include "stringex.hpp" +#include "filetools.h" +#include "CImageMerge.h" +#include "jsonconfig.h" +#include "MultiFrameCapture_8478_HL.h" +#include "StopWatch.h" +#include "linux\sched.h" +#include "deviceconfig.h" + +#define LOG_PATH "/usr/local/correct.log" + +const uint32_t WIDTH_8478 = 1224; +FileTools ftm_cr_log(LOG_PATH); + +static std::string loggername = "MultiFrameCapture_8478_HL"; +static double radio = 1.0; +static int offsetStep1[12]; +static int expStep1[2][3]; +static int org_index = 0; +static void initStep1() +{ + printf("initStep aaaaaaaaaaa \n"); + for (int i = 0; i < 2; i++) + { + for (int j = 0; j < 3; j++) + { + expStep1[i][j] = 600; + } + } + for (int i = 0; i < 12; i++) + { + offsetStep1[i] = 256; + printf("offsetStep[%d]=%d \n", i, offsetStep1[i]); + } +} + +MultiFrameCapture_8478_HL::MultiFrameCapture_8478_HL() : reset_pin(new GpioOut(50)), + fpgaLoad(new Gpio(70)), + fpga_conf_done(new Gpio(69)), + fpga_conf_initn(new Gpio(71)), + bcorrecting(false), + snapthread(1) +{ + LOG_INIT(); + fpga_conf_done->setDirection(Gpio::in); + fpgaComm.reset(new FpgaComm()); + pimgdata_info = {0}; + + // fpga_reload(); + // fpga_reset(); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + // fpgaComm->resetADC(); + + // fpgaComm->resetADC(); + // fpgaComm->update(); + video.reset(new VIDEO_CLASS()); + fpgaComm->update(3); + // GetFpgaparam(0x01,0); + set_ADC_config_frequency(12); + init_adc_8478(); + + snapthread.enqueue([]{ + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET(5, &cpuset); + pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); }); +} + +MultiFrameCapture_8478_HL::~MultiFrameCapture_8478_HL() +{ + if (video.get()) + video.reset(); + + printf("Exit ~MultiFrameCapture_8478_HL() \n"); +} + +void MultiFrameCapture_8478_HL::open() +{ +} + +void MultiFrameCapture_8478_HL::open(HGScanConfig config, FPGAConfigParam_8478 fpgaparam) +{ + fpgaComm->update(3); + uint32_t reg8 = 0, reg5 = 0, reg12 = 0, reg11 = 0, reg10 = 0, reg2 = 0; + fpgaComm->set_8478_type(true); + // fpgaComm->read(2,reg2); + // fpgaComm->write(2,(reg2&0xffffffe1)|0xc); // adc 配置 频率 + + set_ADC_config_frequency(12); + // init_adc_8478(); + + printf(" dpi = %d \n", config.g200params.dpi); + + fpgaComm->read(11, reg11); + fpgaComm->write(11, (reg11 & 0xffffffc0) | 0x12); + + // fpgaComm->write(13,0xdec0000); + fpgaComm->write(13, 0xce40000); // 旗标位 18 -27位 + + // fpgaComm->write(13,0xd680000); + + fpgaComm->set_cis_type(true); + m_config = config; + m_fpgaparam = fpgaparam; + + int dpi = config.g200params.dpi == 0x02 ? 2 : (config.g200params.dpi == 0x03 ? 3 : 1); + int mode = config.g200params.color; + int phyHeight = paperHeight[(PaperSize)config.g200params.paper]; + + if(m_gscancap.papertype == 52 || m_gscancap.papertype == 54) phyHeight = m_gscancap.maxszie_sanp_height; + + int tdpi = config.g200params.dpi == 0x02 ? 300 : (config.g200params.dpi == 0x03 ? 600 : 200); + int pixheight = ((int)((phyHeight / 25.4 * tdpi + 2) / 3)) * 3; + if (fpgaparam.DpiMode == 0x10) + pixheight = pixheight * 180 / 100; + if (fpgaparam.DpiMode == 0x11) + pixheight = pixheight * 130 / 100; + frame_height = 300; + frame_count = ceil((mode == 0x01 ? pixheight * 3 : pixheight) / (float)(frame_height)); // 彩色配置fpga 高度要为目标图像高度的3倍 + if (frame_height * frame_count > FPGA_MAX_HEIGHT_SUP) + frame_count = FPGA_MAX_HEIGHT_SUP / frame_height; + fpgaComm->read(15, m_fpgaversion); + int startsample = 0; + ModeFpga fpgamod = { + .colorMode = mode, + .dpi = m_config.g200params.dpi, + .led = 1, + .sample = startsample, // 256+39 + .adcA = 0, + .adcB = 0, + .selftest = 0, + .sp = fpgaparam.Sp}; // 600DPI 0x1450 300DPI 0xe10 10138 + fpgaComm->setRegs(0x01, *((int *)(&fpgamod))); + fpgaComm->setSample(startsample); + fpgaComm->enableLed(true); + fpgaComm->setEnTestCol(false); + fpgaComm->setEnTestBit(false); + set_LED_PTN_8478(config.g200params.color == false); + set_dpi_mode(config.g200params.dpi); + set_pixel_count_8478(fpgaparam.Sp / 3 / (config.g200params.color ? 3 : 1), config.g200params.color == false); + configFPGAParam(config.g200params.color, config.g200params.dpi); + configFPGAParam_digital_gain(config.g200params.color, config.g200params.dpi); + set_exp_8478_single(fpgaparam.ExposureF[0], fpgaparam.ExposureF[1], fpgaparam.ExposureF[2], fpgaparam.Sp / (config.g200params.color ? 3 : 1), true, config.g200params.color); + set_exp_8478_single(fpgaparam.ExposureB[0], fpgaparam.ExposureB[1], fpgaparam.ExposureB[2], fpgaparam.Sp / (config.g200params.color ? 3 : 1), false, config.g200params.color); + + // set_exp_8478_single(1000,1000,1000,fpgaparam.Sp/(config.g200params.color?3:1),true,config.g200params.color); + // set_exp_8478_single(1000,1000,1000,fpgaparam.Sp/(config.g200params.color?3:1),false,config.g200params.color); + + config.g200params.dpi == 3 ? set_EN_postion(0x54, 0x3a0) : set_EN_postion(0x54, 0x1f0); + + // video->set_buf_count(std::min(frame_count,20u)); + video->set_buf_count(std::min(100u,frame_count)); + uint32_t video_w = (config.g200params.dpi == 0x03 ? WIDTH_8478 * 2 : WIDTH_8478); + if (config.g200params.dpi == 0x01) + video_w = video_w * 2 / 3; + video->open(video_w, frame_height * 2); + fpgaComm->setFrameHeight(frame_height); + printf("fpgaComm set height = %d \n", frame_height); + fpgaComm->read(8, reg8); + + // fpgaComm->write(8,reg8|0x100); //行号 enable + fpgaComm->write(8, reg8 & 0xfffffeff); // 行号 disable + fpgaComm->read(5, reg5); + // fpgaComm->write(5,reg5|0x2000); //测试数据 白+黑 enable + fpgaComm->write(5, reg5 & 0xffffdfff); // 测试数据 白+黑 disable + fpgaComm->read(12, reg12); + // fpgaComm->write(12,reg5&0xfffff000+0x97e); //帧间隔延迟 >=22.5us + // fpgaComm->write(12,reg5&0xe000e000+0xfa0067e); //帧间隔延迟 >=22.5us + // fpgaComm->write(12,0x04e20400); //0x494e491 0x79de496 范围 0-12 16-28 (16-28 > 0-12) + + fpgaComm->read(10, reg10); + fpgaComm->write(12, 0x00200010); // 58us 300*600 多帧 + + fpgaComm->write(10, 0x0150012a); // 58us 300*600 多帧 + + fpgaComm->setFrameNum(1); + + fpgaComm->capture(); // abort first frame + video->read_frame(1000); + fpgaComm->setFrameNum(frame_count); + + fpgaComm->update(3); + // initLut(fpgaparam.LutPath, config.g200params.color); + // initLut(config.g200params.is_textcorrect?fpgaparam.LutPath:fpgaparam.TextLutPath,config.g200params.color); + // initLut(fpgaparam.TextLutPath, config.g200params.color); + init_lutdate(); + // init_imagedatabuffer(); +} + +void MultiFrameCapture_8478_HL::init_lutdate() +{ + DeviceConfig::Gray_Apply gray_; + gray_.value = Get_static_deviceconfig().GetParam().gray_param; + std::string lutpath = m_config.g200params.is_textcorrect ? m_fpgaparam.LutPath : m_fpgaparam.TextLutPath; + if ((m_fpgaparam.DpiMode == 1) && (gray_.Param_Setting.en_200_clr == 1 && m_config.g200params.color == true)) + lutpath = "/usr/local/huago/Graylut200clr.bmp"; + else if ((m_fpgaparam.DpiMode == 2) && (gray_.Param_Setting.en_300_clr == 1 && m_config.g200params.color == true)) + lutpath = "/usr/local/huago/Graylut300clr.bmp"; + else if ((m_fpgaparam.DpiMode == 3) && (gray_.Param_Setting.en_600_clr == 1 && m_config.g200params.color == true)) + lutpath = "/usr/local/huago/Graylut600clr.bmp"; + else if ((m_fpgaparam.DpiMode == 16) && (gray_.Param_Setting.en_slow_clr == 1 && m_config.g200params.color == true)) + lutpath = "/usr/local/huago/Graylutslow_moireclr.bmp"; + else if ((m_fpgaparam.DpiMode == 17) && (gray_.Param_Setting.en_slow_300_clr == 1 && m_config.g200params.color == true)) + lutpath = "/usr/local/huago/Graylutslow_moire300clr.bmp"; + else if ((m_fpgaparam.DpiMode == 32) && (gray_.Param_Setting.en_long_Manuscript_200_clr == 1 && m_config.g200params.color == true)) + lutpath = "/usr/local/huago/GraylutLong_Manuscript200clr.bmp"; + else if ((m_fpgaparam.DpiMode == 33) && (gray_.Param_Setting.en_long_Manuscript_300_clr == 1 && m_config.g200params.color == true)) + lutpath = "/usr/local/huago/GraylutLong_Manuscript300clr.bmp"; + else if ((m_fpgaparam.DpiMode == 1) && (gray_.Param_Setting.en_200_gray == 1 && m_config.g200params.color == false)) + lutpath = "/usr/local/huago/Graylut200gray.bmp"; + else if ((m_fpgaparam.DpiMode == 2) && (gray_.Param_Setting.en_300_gray == 1 && m_config.g200params.color == false)) + lutpath = "/usr/local/huago/Graylut300gray.bmp"; + else if ((m_fpgaparam.DpiMode == 3) && (gray_.Param_Setting.en_600_gray == 1 && m_config.g200params.color == false)) + lutpath = "/usr/local/huago/Graylut600gray.bmp"; + else if ((m_fpgaparam.DpiMode == 16) && (gray_.Param_Setting.en_slow_gray == 1 && m_config.g200params.color == false)) + lutpath = "/usr/local/huago/Graylutslow_moiregray.bmp"; + else if ((m_fpgaparam.DpiMode == 17) && (gray_.Param_Setting.en_slow_300_gray == 1 && m_config.g200params.color == false)) + lutpath = "/usr/local/huago/Graylutslow_moire300gray.bmp"; + else if ((m_fpgaparam.DpiMode == 32) && (gray_.Param_Setting.en_long_Manuscript_200_gray == 1 && m_config.g200params.color == false)) + lutpath = "/usr/local/huago/GraylutLong_Manuscript200gray.bmp"; + else if ((m_fpgaparam.DpiMode == 33) && (gray_.Param_Setting.en_long_Manuscript_300_gray == 1 && m_config.g200params.color == false)) + lutpath = "/usr/local/huago/GraylutLong_Manuscript300gray.bmp"; + initLut(lutpath, m_config.g200params.color); +} + +void MultiFrameCapture_8478_HL::close() +{ + if (video.get()) + video->close(); + // if(pimgdata_info.pdata) free(pimgdata_info.pdata); + // pimgdata_info.pdata = nullptr; + pimgdata_info.offset = pimgdata_info.frame_count = pimgdata_info.img_h = pimgdata_info.img_w = 0; + printf("pimgdata_ free !!!!!\n"); + + // fpgaComm->resetADC(); + // fpga_reload(); +} + +void MultiFrameCapture_8478_HL::Fpga_regsAccess_reset(bool enable) +{ + if (fpgaComm.get()) + fpgaComm->regsAccess_reset(enable); + if (enable) + { + set_ADC_config_frequency(12); + init_adc_8478(); + } +} + +void MultiFrameCapture_8478_HL::start() +{ + if (video.get()) + video->start(); +} + +void MultiFrameCapture_8478_HL::MultiFrameCapture_8478_HL::stop() +{ + if (video.get()) + video->stop(); +} + +bool MultiFrameCapture_8478_HL::is_runing() +{ + return false; +} + +// static void printlog(std::string str) +// { +// std::ofstream o("/root/log.txt",std::ios::app|std::ios::binary); +// if(o.is_open()) +// { +// o << str <capture(); + printf("snap start !!!!! \n"); + b_stop_snap = false; + pimgdata_info.offset = pimgdata_info.frame_count = + pimgdata_info.img_h = pimgdata_info.img_w = 0; + snap_fu = snapthread.enqueue([this] + { + auto snap_func = [this](int height,int width, int channels, bool last_frame, unsigned int frame_index) + { + StopWatch sw; + void *data = video->read_frame(500); + if (data) + { + update_imgdatainfo(data,height,width); + printf("memcpy date size = %d times = %f index = %d \n",height*width,sw.elapsed_ms(),frame_index); + } + else + { + printf("!!!!!!!!!! error read frame losted, i = %d \n", frame_index); + //printlog("!!!!!!!!!! error read frame losted"); + } + }; + int width = WIDTH_8478*3*2*(m_config.g200params.dpi == 3 ? 2 : 1)*(m_config.g200params.color ? 3 :1); + if(m_config.g200params.dpi == 1) + width = width *2/3; + int height = frame_height/(m_config.g200params.color ? 3 :1); + for (int i = 1; i <= frame_count; i++) + { + curr_frame_snap_index = i; + snap_func(height,width, 0, (i == frame_count), i); + if (b_stop_snap) + { + int snaped_frame_count = fpgaComm->getFrame_counter_val(); + printf("!!!!!!!!!! revsed frame count = %d i = %d \n", snaped_frame_count, i); + if (snaped_frame_count > i && snaped_frame_count > 0) // 正常情况下 snaped_frame_count 一定大于0 + { + int reversed_frame_count = snaped_frame_count - i; + for (int j = 1; j <= reversed_frame_count; j++) + { + curr_frame_snap_index =j+i; + snap_func(height, width,0, ((i + j) == reversed_frame_count), i + j); + } + } + break; // 跳出当前读取多帧循环 + } + } + printf("snap end !!!!! \n"); }); +} + +void MultiFrameCapture_8478_HL::snap(frame_data_info info) +{ + printf("snap start !!!!! \n"); + b_stop_snap = false; + info.offset = info.frame_count = info.img_h = info.img_w = 0; + snap_fu = snapthread.enqueue([this, info]{ + frame_data_info frame_info {0}; + frame_info.pdata = info.pdata; + frame_info.total = info.total; + auto snap_func = [this,&frame_info](int height,int width, int channels, bool last_frame, unsigned int frame_index) + { + StopWatch sw; + void *data = video->read_frame(500); + if (data) + { + update_imgdatainfo(data,frame_info,height,width); + printf("memcpy date size = %d times = %f index = %d \n",height*width,sw.elapsed_ms(),frame_index); + } + else + printf("!!!!!!!!!! error read frame losted, i = %d \n", frame_index); + + }; + int width = WIDTH_8478*3*2*(m_config.g200params.dpi == 3 ? 2 : 1)*(m_config.g200params.color ? 3 :1); + if(m_config.g200params.dpi == 1) + width = width *2/3; + int height = frame_height/(m_config.g200params.color ? 3 :1); + for (int i = 1; i <= frame_count; i++) + { + curr_frame_snap_index = i; + snap_func(height,width, 0, (i == frame_count), i); + if (b_stop_snap) + { + int snaped_frame_count = fpgaComm->getFrame_counter_val(); + printf("!!!!!!!!!! revsed frame count = %d i = %d \n", snaped_frame_count, i); + if (snaped_frame_count > i && snaped_frame_count > 0) // 正常情况下 snaped_frame_count 一定大于0 + { + int reversed_frame_count = snaped_frame_count - i; + for (int j = 1; j <= reversed_frame_count; j++) + { + curr_frame_snap_index = i+j; + snap_func(height, width,0, ((i + j) == reversed_frame_count), i + j); + } + } + break; // 跳出当前读取多帧循环 + } + } + pimgdata_info = frame_info; + printf("snap end !!!!! \n"); }); +} + +cv::Size MultiFrameCapture_8478_HL::frame_data_size() +{ + return {2 * this->width() * (m_config.g200params.color ? 3 : 1), frame_height / (m_config.g200params.color ? 3 : 1) * frame_count}; +} + +void MultiFrameCapture_8478_HL::stopsnap() +{ + b_stop_snap = true; + if(snap_fu.valid()) snap_fu.get(); +} + +int MultiFrameCapture_8478_HL::getautosizeheight() +{ + unsigned int val; + unsigned int reg8 = 0; + + fpgaComm->read(8, reg8); + // std::cout << "1 reg[8]:" << string_format("0x%08x", reg8) << std::endl; + // fpgaComm->update(4); + fpgaComm->read(14, val); + int regv = val; + val &= 0x0000ffff; + // std::cout << string_format("ONE height = %d reg[14] = %d \n", val, regv); + // fpgaComm->update(5); + fpgaComm->write(8, reg8 & 0xfffffff7); + // std::cout << string_format("ONE reg[8] = %d \n", reg8 & 0xfffffff7); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + // fpgaComm->update(6); + fpgaComm->read(14, val); + regv = val; + val &= 0x0000ffff; + fpgaComm->read(8, reg8); + // std::cout << "2 reg[8]:" << string_format("0x%08x", reg8) << std::endl; + std::cout << string_format("TWO height = %d reg[14] = %d \n", val, regv); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + fpgaComm->write(8, reg8 | 0x8); + // fpgaComm->write(8,0x02260008); + // fpgaComm->update(7); + // fpgaComm->read(8, reg8); + // std::cout << "2 reg[8]:" << string_format("0x%08x", reg8) << std::endl; + return val; + + // return fpgaComm->getFrameHeight(); +} +void MultiFrameCapture_8478_HL::set_size(int width, int height) +{ + if (video.get()) + video->set_size(width, height); +} + +void MultiFrameCapture_8478_HL::set_sp(int sp) +{ + fpgaComm->setSp(sp); +} + +void *MultiFrameCapture_8478_HL::readFrame(int timeout) +{ + return video->read_frame(timeout); +} + +cv::Mat MultiFrameCapture_8478_HL::read_one_frame() +{ + fpgaComm->setFrameNum(1); + fpgaComm->capture(); + void *data = video->read_frame(1000); + fpgaComm->setFrameNum(frame_count); + if (data) + { + int width = WIDTH_8478 * 3 * 2 * (m_config.g200params.dpi == 3 ? 2 : 1) * (m_config.g200params.color ? 3 : 1); + if (m_config.g200params.dpi == 1) + width = width * 2 / 3; + int height = frame_height / (m_config.g200params.color ? 3 : 1); + cv::Mat mat(height, width, CV_8UC1, data); + return merge_8478(mat, m_config.g200params.color, 0); + } + else + return cv::Mat(); +} + +frame_data_info MultiFrameCapture_8478_HL::ReadMultiFrame(int state) +{ + printf(" ReadMultiFrame state : %d \n", state); + if (state & 1) + b_stop_snap = true; + if (snap_fu.valid()) + snap_fu.get(); + if ((state & 0x2) || (!pimgdata_info.pdata)) + return {0}; + return pimgdata_info; +} + +void MultiFrameCapture_8478_HL::set_gain(int ix, int val) +{ + for (int i = 0; i < 6; i++) + { + if (ix) + fpgaComm->setAGain(i, val); + else + fpgaComm->setBGain(i, val); + } +} + +void MultiFrameCapture_8478_HL::set_offset(int ix, int val) +{ + for (int i = 0; i < 6; i++) + { + if (ix) + fpgaComm->setAOffset(i, val); + else + fpgaComm->setBOffset(i, val); + + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } +} + +void MultiFrameCapture_8478_HL::set_expo(int ix, int val) +{ + switch (ix) + { + case 0: + fpgaComm->setAExposureR(val); + break; + case 1: + fpgaComm->setAExposureG(val); + break; + case 2: + fpgaComm->setAExposureB(val); + break; + case 3: + fpgaComm->setBExposureR(val); + break; + case 4: + fpgaComm->setBExposureG(val); + break; + case 5: + fpgaComm->setBExposureB(val); + break; + default: + break; + } + std::this_thread::sleep_for(std::chrono::milliseconds(1)); +} + +std::shared_ptr MultiFrameCapture_8478_HL::regs() +{ + return fpgaComm; +} + +void MultiFrameCapture_8478_HL::reset() +{ + fpga_reset(); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + fpgaComm->resetADC(); + // fpgaComm->setDelayTime(0X3e8); + // fpgaComm->setRegs(0x00, fpgaComm->getRegs(0x00)); + // fpgaComm->setRegs(0x01, fpgaComm->getRegs(0x01)); +} + +int MultiFrameCapture_8478_HL::width() +{ + // int dpi = fpgaComm->getDpi(); + // int channel = 1; + // int width = dpi == 0x02 ? 1296 * channel : (dpi == 0x03 ? (2592 * channel) : (864 * channel)); + // printf("get width = %d \n", width); + // return width; + uint32_t width = WIDTH_8478 * 3 * (m_config.g200params.dpi == 3 ? 2 : 1); + return m_config.g200params.dpi == 1 ? (width * 2 / 3) : width; +} + +int MultiFrameCapture_8478_HL::height() +{ + return fpgaComm->getFrameHeight(); +} + +int MultiFrameCapture_8478_HL::color() +{ + return fpgaComm->getColorMode() ? 16 : 0; +} + +void MultiFrameCapture_8478_HL::init_autocorrect(int colormode) +{ + std::thread t_correctthread = std::thread(&MultiFrameCapture_8478_HL::correctcolor, this, colormode); + t_correctthread.detach(); + // if(t_correctthread.joinable()) + // t_correctthread.join(); +} + +void MultiFrameCapture_8478_HL::configFPGAParam(int mode, int dpi) +{ + printf("dpi = %d mode = %d \n", dpi, mode); + FPGAConfigParam_8478 fpgaparam = Get_Static_CorrectParam().GetFpgaparam_8478(dpi, mode); + for (int i = 0; i < 9; i++) + { + set_digital_offset_8478(i, fpgaparam.OffsetF_R[i], true, 0); + set_digital_offset_8478(i, fpgaparam.OffsetF_G[i], true, 1); + set_digital_offset_8478(i, fpgaparam.OffsetF_B[i], true, 2); + set_digital_offset_8478(i, fpgaparam.OffsetB_R[i], false, 0); + set_digital_offset_8478(i, fpgaparam.OffsetB_G[i], false, 1); + set_digital_offset_8478(i, fpgaparam.OffsetB_B[i], false, 2); + printf("\n OffsetF_R[%d] = %d OffsetF_G[%d] = %d OffsetF_B[%d] = %d ", i, fpgaparam.OffsetF_R[i], + i, fpgaparam.OffsetF_G[i], i, fpgaparam.OffsetF_B[i]); + printf("\n OffsetB_R[%d] = %d OffsetB_G[%d] = %d OffsetB_B[%d] = %d ", i, fpgaparam.OffsetB_R[i], + i, fpgaparam.OffsetB_G[i], i, fpgaparam.OffsetB_B[i]); + } +} + +void MultiFrameCapture_8478_HL::configFPGAParam_digital_gain(int mode, int dpi) +{ + FPGAConfigParam_8478 fpgaparam = Get_Static_CorrectParam().GetFpgaparam_8478(dpi, mode); + for (int i = 0; i < 9; i++) + { + set_digital_gain_8478(i, fpgaparam.GainF_R[i], true, 0); + set_digital_gain_8478(i, fpgaparam.GainF_G[i], true, 1); + set_digital_gain_8478(i, fpgaparam.GainF_B[i], true, 2); + set_digital_gain_8478(i, fpgaparam.GainB_R[i], false, 0); + set_digital_gain_8478(i, fpgaparam.GainB_G[i], false, 1); + set_digital_gain_8478(i, fpgaparam.GainB_B[i], false, 2); + printf("\n GainF_R[%d] = %d GainF_G[%d] = %d GainF_B[%d] = %d ", i, fpgaparam.GainF_R[i], + i, fpgaparam.GainF_G[i], i, fpgaparam.GainF_B[i]); + printf("\n GainB_R[%d] = %d GainB_G[%d] = %d GainB_B[%d] = %d ", i, fpgaparam.GainB_R[i], + i, fpgaparam.GainB_G[i], i, fpgaparam.GainB_B[i]); + } +} + +void MultiFrameCapture_8478_HL::openDevice(int dpi, int mode) +{ + FPGAConfigParam_8478 fpgaparam = Get_Static_CorrectParam().GetFpgaparam_8478(dpi, mode); + + if (dpi == 0x10 || dpi == 0x20) + dpi = 1; + if (dpi == 0x11 || dpi == 0x21) + dpi = 2; + int channelwidth = dpi == 0x02 ? WIDTH_8478 : (dpi == 0x03 ? WIDTH_8478 * 2 : WIDTH_8478 * 2 / 3); + int channels = mode == 0x01 ? 3 : 1; + int width = channelwidth * channels; + fpgaComm->set_8478_type(true); + set_ADC_config_frequency(12); + init_adc_8478(); + uint32_t reg11 = 0, reg8 = 0, reg5 = 0, reg10 = 0, reg12 = 0; + fpgaComm->read(11, reg11); + fpgaComm->write(11, (reg11 & 0xffffffc0) | 0x12); + + // fpgaComm->write(13,0xdec0000); + fpgaComm->write(13, 0xce40000); // 旗标位 18 -27位 + + // fpgaComm->write(13,0xd680000); + + video->set_buf_count(10); + fpgaComm->set_cis_type(true); + dpi == 3 ? set_EN_postion(0x54, 0x3a0) : set_EN_postion(0x54, 0x1f0); + set_LED_PTN_8478(mode == false); + set_dpi_mode(dpi); + set_pixel_count_8478(fpgaparam.Sp / 3 / (mode ? 3 : 1), mode == false); + + frame_height = 300; + frame_count = 1; // 最后一帧丢帧,多采集一帧防止图像数据缺失 + fpgaComm->read(15, m_fpgaversion); + int startsample = 0; + ModeFpga fpgamod = { + .colorMode = mode, + .dpi = dpi, + .led = 1, + .sample = startsample, // 256+39 + .adcA = 0, + .adcB = 0, + .selftest = 0, + .sp = fpgaparam.Sp}; // 600DPI 0x1450 300DPI 0xe10 10138 + fpgaComm->setRegs(0x01, *((int *)(&fpgamod))); + fpgaComm->setSample(startsample); + fpgaComm->enableLed(true); + fpgaComm->setEnTestCol(false); + fpgaComm->setEnTestBit(false); + uint32_t video_w = dpi == 0x03 ? WIDTH_8478 * 2 : (dpi == 1 ? WIDTH_8478 * 2 / 3 : WIDTH_8478); + video->open(video_w, frame_height * 2); + fpgaComm->setFrameNum(frame_count); + fpgaComm->setFrameHeight(frame_height); + printf("fpgaComm set height = %d \n", frame_height); + fpgaComm->read(8, reg8); + // fpgaComm->write(8,reg8|0x100); //行号 enable + fpgaComm->write(8, reg8 & 0xfffffeff); // 行号 disable + fpgaComm->read(5, reg5); + // fpgaComm->write(5,reg5|0x2000); //测试数据 白+黑 enable + fpgaComm->write(5, reg5 & 0xffffdfff); // 测试数据 白+黑 disable + fpgaComm->read(12, reg12); + fpgaComm->read(10, reg10); + // if(dpi == 3){ + // fpgaComm->write(10,0x03b0037a); //120 us 600*600 多帧 + // fpgaComm->write(12,0x02000100); //120 us 600*600 多帧 + // } + // else + { + fpgaComm->write(12, 0x00200010); // 58us 300*600 多帧 + fpgaComm->write(10, 0x0150012a); // 58us 300*600 多帧 + } + configFPGAParam(mode, dpi); + configFPGAParam_digital_gain(mode,dpi); + fpgaComm->update(3); + fpgaComm->capture(); // abort first frame + for (int i = 0; i < frame_count; i++) + video->read_frame(500); +} + +void MultiFrameCapture_8478_HL::creatcorrectconfig(int dpi, int mode) +{ + printf(" opendevice"); + openDevice(dpi, mode); + printf(" opendevice end "); + bool isDone = false; + int i = 1; + initStep1(); + set_led_off(); + while (!isDone) // 先暗场 + { + std::string log = "==============================第" + std::to_string(i) + "次==============================="; + ftm_cr_log.append_log(log); + configFPGAParam(mode, dpi); + configFPGAParam_digital_gain(mode,dpi); + ftm_cr_log.append_log(log); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + fpgaComm->capture(); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + isDone = saveLutImg(dpi, mode, true); // 0 color_black 1 color_white 2 gray_balck 3 gray_white + i++; + } + i = 1; + isDone = false; + + initStep1(); + while (!isDone) // 后明场 + { + FPGAConfigParam_8478 fpgaparam = Get_Static_CorrectParam().GetFpgaparam_8478(dpi, mode); + set_exp_8478_single(fpgaparam.ExposureF[0], fpgaparam.ExposureF[1], fpgaparam.ExposureF[2], fpgaparam.Sp / (mode ? 3 : 1), true, mode); + set_exp_8478_single(fpgaparam.ExposureB[0], fpgaparam.ExposureB[1], fpgaparam.ExposureB[2], fpgaparam.Sp / (mode ? 3 : 1), false, mode); + std::string log = "==============================第" + std::to_string(i) + "次==============================="; + ftm_cr_log.append_log(log); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + fpgaComm->capture(); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + isDone = saveLutImg(dpi, mode, false); + i++; + } + printf("creatcorrectconfig %s \n", (mode == IMAGE_COLOR ? " Color" : " Gray")); + // creatLUTData(dpi, mode); + video->close(); +} + +static int savelutindex = 0; +bool MultiFrameCapture_8478_HL::saveLutImg(int dpi, int mode, bool black) +{ + FPGAConfigParam_8478 param = Get_Static_CorrectParam().GetFpgaparam_8478(dpi, mode); + if (dpi == 0x10 || dpi == 0x20) + dpi = 1; + if (dpi == 0x11 || dpi == 0x21) + dpi = 2; + int offset_indexs[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8}; + int width = WIDTH_8478 * 3 * 2 * (dpi == 3 ? 2 : 1) * (mode ? 3 : 1); + if (dpi == 1) + width = width * 2 / 3; + int height = frame_height / (mode ? 3 : 1); + + bool isNeedSave = true; + std::string log; + void *data = video->read_frame(10000); + if (data == NULL) + { + isNeedSave = false; + log = "WARNNING WARNNING WARNNING FAILDED TO READ IMAGE DATA !!!!!!!!!!!!!!!!!!!\r\n"; + ftm_cr_log.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + return isNeedSave; + } + cv::Mat src(height, width, CV_8UC1, data); + // cv::imwrite(std::to_string(savelutindex++) + ".jpg", src); + + CImageMerge t_marge; + // cv::Mat mrgmat = t_marge.MergeImage(mode == 0x01, src, dstwidth, height,m_fpgaversion); + cv::Mat mrgmat = merge_8478(src, mode, 0); + mrgmat = mrgmat(cv::Rect(0, 10, mrgmat.cols, mrgmat.rows - 20)); + // cv::imwrite("correct.bmp",mrgmat); + // return false; + + if (black) // 暗场 + { + double offValues_R[18]{0}; + double offValues_G[18]{0}; + double offValues_B[18]{0}; + std::vector bflags(2 * 9 * (mode ? 3 : 1), false); + for (volatile int n = 0; n < 2; n++) + { + cv::Mat img = mrgmat(cv::Rect(mrgmat.cols * n / 2, 10, mrgmat.cols / 2, mrgmat.rows - 10)).clone(); + int offset_total = 0; + for (volatile int s = 0; s < 9; s++) // + { + int k = n * 9 + s; + int offset_wdth; + if ((k == 8) || (k == 17)) + offset_wdth = dpi == 0x03 ? 432 : (dpi == 0x02 ? 216 : 144); + else + offset_wdth = dpi == 0x03 ? 864 : (dpi == 0x02 ? 432 : 288); + cv::Scalar mean = cv::mean(img(cv::Rect(offset_total, 10, offset_wdth, img.rows - 10))); + + if (mode) + { + offValues_R[k] = mean.val[0]; + offValues_G[k] = mean.val[1]; + offValues_B[k] = mean.val[2]; + + // auto tmp_mat = img(cv::Rect(offset_total, 10, offset_wdth, img.rows - 10)); + // offValues_R[k] = (*std::min_element(tmp_mat.begin(),tmp_mat.end(), + // [](cv::Vec3b a, cv::Vec3b b) -> bool{ return a[0] < b[0]; }))[0]; + // offValues_G[k] = (*std::min_element(tmp_mat.begin(),tmp_mat.end(), + // [](cv::Vec3b a, cv::Vec3b b) -> bool{ return a[1] < b[1]; }))[1]; + // offValues_B[k] = (*std::min_element(tmp_mat.begin(),tmp_mat.end(), + // [](cv::Vec3b a, cv::Vec3b b) -> bool{ return a[2] < b[2]; }))[2]; + printf("\noffValues[%d] R = %f G = %f B= %f", k, offValues_R[k], offValues_G[k], offValues_B[k]); + } + else{ + offValues_R[k] = offValues_G[k] = offValues_B[k] = mean.val[0]; + // auto tmp_mat = img(cv::Rect(offset_total, 10, offset_wdth, img.rows - 10)); + // offValues_R[k] = offValues_G[k] = offValues_B[k] = *std::min_element(tmp_mat.begin(), + // tmp_mat.end(), [](std::uint8_t a, std::uint8_t b) -> bool{ return a < b; }); + printf("\noffValues[%d] = %f", k, offValues_R[k]); + } + + offset_total += offset_wdth; + } + + } + + // std::string clrmode = (mode == 0x01 ? "彩色" : " 灰度"); + // log = "开始" + clrmode + "暗场校正 \n"; + for (volatile int s = 0; s < 2; s++) + { + int offsets_R[9]{0}, offsets_G[9]{0}, offsets_B[9]{0}; // = (int *)(s == 0 ? ¶m.OffsetF[0] : ¶m.OffsetB[0]); + memcpy(offsets_R, (s == 0 ? ¶m.OffsetF_R[0] : ¶m.OffsetB_R[0]), sizeof(param.OffsetF_R)); + memcpy(offsets_G, (s == 0 ? ¶m.OffsetF_G[0] : ¶m.OffsetB_G[0]), sizeof(param.OffsetF_G)); + memcpy(offsets_B, (s == 0 ? ¶m.OffsetF_B[0] : ¶m.OffsetB_B[0]), sizeof(param.OffsetF_B)); + if (mode == IMAGE_GRAY) + { + for (volatile int j = 0; j < 9; j++) + { + int k = s * 9 + j; + double diff = BLACK_DIFF(offValues_R[k]); + //double diff = 3 - offValues_R[k]; + double step = radio * diff; + int preStep = offsetStep1[k]; + if (step < 1 && step > 0) + step = 1; + if (step < 0 && step > -1) + step = -1; + + // FMT_STEP(step); + bool isMinStep = abs(step) == 1 && step == offsetStep1[k]; + bool isOutBounds = offsets_R[j] >= 512 && step > 0; + isOutBounds |= offsets_R[j] <= 0 && step < 0; + log += " 暗场校正 :" + std::to_string(k) + ";diff:" + std::to_string(diff) + ";light:" + std::to_string(offValues_R[k]) + ";offset:" + std::to_string(offsets_R[j]) + ";step:" + std::to_string(step) + "\r\n"; + if (isOutBounds) + log += " 第" + std::to_string(k) + "条带暗场校正异常,暗场值无法降低 \r\n"; + //else if (abs(step) > 1 || isMinStep) + else if (abs(step) > 1) + { + offsetStep1[k] = (int)(step); + offsets_R[offset_indexs[k]] += step; + log += "offsetStep1" + std::to_string(k) + " = " + std::to_string(offsetStep1[k]) + ", offset_indexs" + std::to_string(k) + " =" + std::to_string(offset_indexs[k]) + "\r\n"; + + if (offsets_R[offset_indexs[k]] < 1) + offsets_R[offset_indexs[k]] = 1; + if (offsets_R[offset_indexs[k]] > 512) + offsets_R[offset_indexs[k]] = 512; + // isNeedSave = false; + bflags[k] = false; + } + else + { + bflags[k] = true; + // printf("channel[%d] black correct done\n",k); + } + + log += (s == 0 ? "彩色正面" : "彩色背面"); + log += "偏移值:" + std::to_string(offsets_R[0]) + "," + std::to_string(offsets_R[1]) + "," + std::to_string(offsets_R[2]) + "," + + std::to_string(offsets_R[3]) + "," + std::to_string(offsets_R[4]) + "," + std::to_string(offsets_R[5]) + "," + std::to_string(offsets_R[6]) + + "," + std::to_string(offsets_R[7]) + "," + std::to_string(offsets_R[8]) + "\r\n"; + // printf("\n%s",log.c_str()); + // log += (s == 0 ? "彩色正面暗场校正完成 \r\n" : "彩色背面暗场校正完成 \r\n"); + ftm_cr_log.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + log = ""; + } + memcpy(offsets_G, offsets_R, sizeof(offsets_R)); + memcpy(offsets_B, offsets_R, sizeof(offsets_R)); + } + else + { + double offValues[18]{0}; + int offsets[9]{0}; + for (int color = 0; color < 3; color++) + { + memcpy(offValues, color == 0 ? offValues_R : (color == 1 ? offValues_G : offValues_B), sizeof(offValues)); + memcpy(offsets, color == 0 ? offsets_R : (color == 1 ? offsets_G : offsets_B), sizeof(offsets)); + for (volatile int j = 0; j < 9; j++) + { + int k = s * 9 + j; + double diff = BLACK_DIFF(offValues[k]); + // double diff = 3 - offValues[k]; + double step = radio * diff; + int preStep = offsetStep1[k]; + if (step < 1 && step > 0) + step = 1; + if (step < 0 && step > -1) + step = -1; + + // FMT_STEP(step); + bool isMinStep = abs(step) == 1 && step == offsetStep1[k]; + bool isOutBounds = offsets[j] >= 512 && step > 0; + isOutBounds |= offsets[j] <= 0 && step < 0; + log += " 暗场校正 :" + std::to_string(k) + ";diff:" + std::to_string(diff) + ";light:" + std::to_string(offValues[k]) + ";offset:" + std::to_string(offsets[j]) + ";step:" + std::to_string(step) + "\r\n"; + if (isOutBounds) + log += " 第" + std::to_string(k) + "条带暗场校正异常,暗场值无法降低 \r\n"; + //else if (abs(step) > 1 || isMinStep) + else if (abs(step) > 1) + { + offsetStep1[k] = (int)(step); + offsets[offset_indexs[k]] += step; + log += "offsetStep1" + std::to_string(k) + " = " + std::to_string(offsetStep1[k]) + ", offset_indexs" + std::to_string(k) + " =" + std::to_string(offset_indexs[k]) + "\r\n"; + + if (offsets[offset_indexs[k]] < 1) + offsets[offset_indexs[k]] = 1; + if (offsets[offset_indexs[k]] > 512) + offsets[offset_indexs[k]] = 512; + // isNeedSave = false; + bflags[18 * color + k] = false; + } + else + { + bflags[18 * color + k] = true; + // printf("channel[%d] black correct done\n",k); + } + log += (s == 0 ? "彩色正面" : "彩色背面"); + log += "偏移值:" + std::to_string(offsets[0]) + "," + std::to_string(offsets[1]) + "," + std::to_string(offsets[2]) + "," + + std::to_string(offsets[3]) + "," + std::to_string(offsets[4]) + "," + std::to_string(offsets[5]) + "," + std::to_string(offsets[6]) + + "," + std::to_string(offsets[7]) + "," + std::to_string(offsets[7]) + "\r\n"; + // log += (s == 0 ? "彩色正面暗场校正完成 \r\n" : "彩色背面暗场校正完成 \r\n"); + // printf("\n%s",log.c_str()); + ftm_cr_log.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + log = ""; + } + memcpy(color == 0 ? offValues_R : (color == 1 ? offValues_G : offValues_B), offValues, sizeof(offValues)); + memcpy(color == 0 ? offsets_R : (color == 1 ? offsets_G : offsets_B), offsets, sizeof(offsets)); + } + } + memcpy((s == 0 ? ¶m.OffsetF_R[0] : ¶m.OffsetB_R[0]), offsets_R, sizeof(param.OffsetF_R)); + memcpy((s == 0 ? ¶m.OffsetF_G[0] : ¶m.OffsetB_G[0]), offsets_G, sizeof(param.OffsetF_G)); + memcpy((s == 0 ? ¶m.OffsetF_B[0] : ¶m.OffsetB_B[0]), offsets_B, sizeof(param.OffsetF_B)); + } + + for (int i = 0; i < bflags.size(); i++) + { + if (!bflags[i]) + isNeedSave = false; + printf(" b_flags [%d] = %s ",i,bflags[i]?"true":"false"); + } + + if (isNeedSave) + { + printf("Save LUT image path :%s \n", param.Flat_BwPath.c_str()); + log = "暗场校正完成 \r\n"; + if (m_captureCallback) + m_captureCallback(mode, log); + // log =""; + imwrite(param.Flat_BwPath, mrgmat); + } + } + else // 明场 + { + radio = 1.0; + if (mode == IMAGE_COLOR) + { + double values[2][3]; + + cv::Scalar a = cv::mean(mrgmat(cv::Rect(0, 0, mrgmat.cols / 2, mrgmat.rows))); + cv::Scalar b = cv::mean(mrgmat(cv::Rect(mrgmat.cols / 2, 0, mrgmat.cols / 2, mrgmat.rows))); + for (int j = 0; j < 3; j++) + { + values[0][j] = a.val[2 - j]; + values[1][j] = b.val[2 - j]; + } + printf("\n mean F_R = %f F_G = %f F_B = %f B_R = %f B_G = %f B_B = %f ", values[0][0], values[0][1], values[0][2], + values[1][0], values[1][1], values[1][2]); + + log = "开始彩色明场校正 \r\n"; + if (m_captureCallback) + m_captureCallback(mode, log); + for (int s = 0; s < 2; s++) + { + int exposures[3]; // = (int *)(s == 0 ? param.ExposureF : param.ExposureB); + memcpy(exposures, (s == 0 ? ¶m.ExposureF[0] : ¶m.ExposureB[0]), sizeof(param.ExposureB)); + for (int x = 0; x < 3; x++) + { + int k = (3 * s + x); + int diff = LIGHT_DIFF(param.MaxBright, *((double *)values + k)); + log += " 明场:" + std::to_string(k) + ";diff:" + std::to_string(diff) + "\r\n"; + // if(abs(diff) > 30) + // radio = 2; + // else + // radio = 1; + double step = diff * radio; + int preStep = *((int *)expStep + k); + if (step * preStep < 0) + { + step = 0 - preStep / 2; + } + if (step < 1 && step > 0) + step = 1; + if (step < 0 && step > -1) + step = -1; + + bool isMinStep = abs(step) == 1 && step == *((int *)expStep + k); + bool isOutBounds = exposures[x] >= (param.Sp / 3 / (mode ? 3 : 1) - 15) && step > 0; + isOutBounds |= exposures[x] <= 0 && step < 0; + if (isOutBounds) + log += " 第" + std::to_string(x) + "个明场校正异常 \r\n"; + else if (abs(diff) >= 1 || isMinStep) + { + *((int *)expStep + k) = (int)(step); + exposures[x] += step; + if (exposures[x] > (param.Sp / 3 / (mode ? 3 : 1) - 15)) + { + exposures[x] = (param.Sp / 3 / (mode ? 3 : 1) - 15); + } + if (exposures[x] <= 0) + exposures[x] = 1; + isNeedSave = false; + } + log += " 曝光值:" + std::to_string(exposures[x]) + "\r\n"; + log += " 调整步长:" + std::to_string(*((int *)expStep + k)) + "\r\n"; + } + memcpy((s == 0 ? ¶m.ExposureF[0] : ¶m.ExposureB[0]), exposures, sizeof(param.ExposureB)); + } + printf("\n%s", log.c_str()); + ftm_cr_log.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + + if (isNeedSave) + { + log = "彩色明场校正完成\r\n"; + if (m_captureCallback) + m_captureCallback(mode, log); + // log =""; + imwrite(param.Flat_WhitePath, mrgmat); + } + } + else + { + double values[2]; + values[0] = cv::mean(mrgmat(cv::Rect(0, 0, mrgmat.cols / 2, mrgmat.rows))).val[0]; + values[1] = cv::mean(mrgmat(cv::Rect(mrgmat.cols / 2, 0, mrgmat.cols / 2, mrgmat.rows))).val[0]; + log = "-----开始灰色明场校正-----\r\n"; + log += " 灰色扫描灰度明场均值:" + std::to_string(values[0]) + "," + std::to_string(values[1]) + "\r\n"; + if (m_captureCallback) + m_captureCallback(mode, log); + for (int s = 0; s < 2; s++) + { + int *exposures = (int *)(s == 0 ? param.ExposureF : param.ExposureB); + int diff = LIGHT_DIFF(param.MaxBright, values[s]); + // if(abs(diff) > 30) + // radio = 2; + // else + // radio = 1; + double step = diff * radio; + log += " 明场:" + std::to_string(s) + ";diff:" + std::to_string(diff) + "\r\n"; + int preStep = expStep[s][0]; + if (step * preStep < 0) + { + step = 0 - preStep / 2; + } + else + { + radio = 1; + } + if (step < 1 && step > 0) + step = 1; + if (step < 0 && step > -1) + step = -1; + + int exp = *(exposures + 1); + // std::string ss1(string_format("exp[%d] = %d step = %.3f \r\n", s, exp, step)); + // log += ss1; + bool isMinStep = abs(step) == 1 && step == expStep[s][0]; + bool isOutBounds = exp >= (param.Sp / 3 / (mode ? 3 : 1) - 15) && step > 0; + isOutBounds |= exp <= 0 && step < 0; + if (isOutBounds) + log += " 第" + std::to_string(s) + "个明场校正异常 \r\n"; + else if (abs(diff) > 1 || isMinStep) + { + exp += step; + if (exp < 0) + exp = 0; + if (exp > (param.Sp / 3 / (mode ? 3 : 1) - 15)) + exp = param.Sp / 3 / (mode ? 3 : 1) - 15; + + float coffe[3] = {1, 1, 1}; // 0.2, 1,0.51 + for (int k = 0; k < 3; k++) + { + *(exposures + k) = (int)(exp * coffe[k]); + expStep[s][k] = (int)(step); + std::string exps(string_format("expStep[%d][%d] = %.3f\r\n", s, k, step)); + log += exps; + std::string ss(string_format("exposures[%d] = %0.3f \r\n", k, exposures[k])); + log += ss; + } + + isNeedSave = false; + } + } + printf("\n%s", log.c_str()); + ftm_cr_log.append_log(log); + if (m_captureCallback) + m_captureCallback(mode, log); + if (isNeedSave) + { + printf("Save LUT image path :%s \n", param.Flat_WhitePath.c_str()); + log = "灰度明场校正完成\r\n"; + if (m_captureCallback) + m_captureCallback(mode, log); + log = ""; + imwrite(param.Flat_WhitePath, mrgmat); + } + } + } + Get_Static_CorrectParam().SaveCorrectParam(param); + printf("exit Save_lut \n"); + return isNeedSave; +} + +void MultiFrameCapture_8478_HL::correctcolor(int correctmode) +{ + + printf(" correctcolor start mode = %d \n", correctmode); + auto _start = std::chrono::steady_clock::now(); + std::map> mode = {{1, {1, 0}}, {2, {1, 1}}, {3, {2, 0}}, {4, {2, 1}}, {5, {3, 0}}, {6, {3, 1}}, {7, {16, 0}}, {8, {16, 1}}, + {9, {17, 0}}, {10, {17, 1}},{11,{32,1}},{12,{32,0}},{13,{33,1}},{14,{33,0}}}; + ThreadPool pool(2); + std::queue> fu_correct; + std::string loginfo = "Start Correctcolor \r\n"; + if (m_captureCallback) + m_captureCallback(0x01, loginfo); + if (correctmode != 0) + { + creatcorrectconfig(mode[correctmode].first, mode[correctmode].second); + auto param = Get_Static_CorrectParam().GetFpgaparam_8478(mode[correctmode].first, mode[correctmode].second); + fu_correct.emplace(pool.enqueue([param](int dpi, int color) + { creatLUTData(dpi, color, param); }, + mode[correctmode].first, mode[correctmode].second)); + } + else + { + for (auto node : mode) + { + creatcorrectconfig(node.second.first, node.second.second); + auto param = Get_Static_CorrectParam().GetFpgaparam_8478(node.second.first, node.second.second); + fu_correct.emplace(pool.enqueue([param](int dpi, int color) + { creatLUTData(dpi, color, param); }, + node.second.first, node.second.second)); + } + } + + while (fu_correct.size()) + { + fu_correct.front().get(); + fu_correct.pop(); + } + loginfo = "******Correct Done****** time " + std::to_string(std::chrono::duration(std::chrono::steady_clock::now() - _start).count()) + "s"; + if (m_captureCallback) + m_captureCallback(0x04, loginfo); +} + +void MultiFrameCapture_8478_HL::fpga_reset() +{ + reset_pin->setValue(Gpio::Low); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + reset_pin->setValue(Gpio::High); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); +} + +void MultiFrameCapture_8478_HL::fpga_reload() +{ + // fpga 代码重载 + fpgaLoad->setValue(Gpio::Low); + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + fpga_conf_initn->setValue(Gpio::Low); + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + printf("\n fpga_conf_done value %d", fpga_conf_done->getValue()); + fpgaLoad->setValue(Gpio::High); + std::this_thread::sleep_for(std::chrono::milliseconds(15)); + fpga_conf_initn->setValue(Gpio::High); + // std::this_thread::sleep_for(std::chrono::milliseconds(5)); + printf("\n fpga_conf_done value %d", fpga_conf_done->getValue()); + // while(fpga_conf_done->getValue() == Gpio::GpioLevel::Low) + // std::this_thread::sleep_for(std::chrono::milliseconds(5)); + std::this_thread::sleep_for(std::chrono::seconds(3)); + printf("\n fpga_conf_done value %d", fpga_conf_done->getValue()); + fpgaComm->resetADC(); + fpgaComm->update(0); +} + +void MultiFrameCapture_8478_HL::init_imagedatabuffer() +{ + + if (pimgdata_info.pdata) + free(pimgdata_info.pdata); + pimgdata_info.pdata = nullptr; + pimgdata_info.offset = pimgdata_info.frame_count = pimgdata_info.img_h = pimgdata_info.img_w = 0; + if (frame_count != 0) + { + int t_frame_count = fpgaComm->getFrameNum(); + int width = this->width() * (m_config.g200params.color ? 3 : 1); + int height = frame_height * 2; + pimgdata_info.pdata = malloc(height * t_frame_count * width); + pimgdata_info.total = height * t_frame_count; + pimgdata_info.offset = 0; + pimgdata_info.frame_count = 0; + pimgdata_info.img_h = 0; + pimgdata_info.img_w = 0; + printf("pimgdata_info.pdata = %p malloc_size = %d \n", pimgdata_info.pdata, height * t_frame_count * width, t_frame_count, width, height); + } +} + +void MultiFrameCapture_8478_HL::free_imagedatabuffer() +{ + if (pimgdata_info.pdata) + free(pimgdata_info.pdata); + pimgdata_info.pdata = nullptr; + printf("--- free imagedatabuf --- \n"); +} + +// static void neon_memcpy(volatile void *dst, volatile void *src, int sz) +// { +// if (sz & 63) +// sz = (sz & -64) + 64; +// asm volatile ( +// "NEONCopyPLD: \n" +// " VLDM %[src]!,{d0-d7} \n" +// " VSTM %[dst]!,{d0-d7} \n" +// " SUBS %[sz],%[sz],#0x40 \n" +// " BGT NEONCopyPLD \n" +// : [dst]"+r"(dst), [src]"+r"(src), [sz]"+r"(sz) : : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "cc", "memory"); +// } + +void MultiFrameCapture_8478_HL::update_imgdatainfo(void *itemmat, frame_data_info &info, uint32_t h, uint32_t w) +{ + // StopWatch sw; + if (info.pdata && itemmat) + { + // neon_memcpy(pimgdata_info.pdata + pimgdata_info.offset,itemmat,h*w); + memcpy(info.pdata + info.offset, itemmat, h * w); + info.offset += h * w; + info.frame_count++; + info.img_h += h; + info.img_w = w; + // printf("offset = %d item_total = %d \n", pimgdata_info.offset,pimgdata_info.frame_count); + } + // printf("size = %d frame memcpy time = %fms \n", h*w,sw.elapsed_ms()); +} + +void MultiFrameCapture_8478_HL::update_imgdatainfo(void *itemmat, uint32_t h, uint32_t w) +{ + if (pimgdata_info.pdata && itemmat) + { + memcpy(pimgdata_info.pdata + pimgdata_info.offset, itemmat, h * w); + pimgdata_info.offset += h * w; + pimgdata_info.frame_count++; + pimgdata_info.img_h += h; + pimgdata_info.img_w = w; + } +} + +void MultiFrameCapture_8478_HL::init_adc_8478() +{ + // std::this_thread::sleep_for(std::chrono::milliseconds(100)); + for (int bank = 0; bank < 4; bank++) + for (int i = 1; i < 64; i++) + { + write_adc_8478(bank_change[bank], i, bank_value[i + 64 * bank], 1); + write_adc_8478(bank_change[bank], i, bank_value[i + 64 * bank], 0); + } + // std::this_thread::sleep_for(std::chrono::milliseconds(100)); +} + +void MultiFrameCapture_8478_HL::write_adc_8478(int bank, int addr, int val, bool A_or_B) +{ + uint32_t reg5 = 0; + fpgaComm->read(5, reg5); + fpgaComm->write(5, reg5 | 0xc000); // adc 配置使能打开 + // std::this_thread::sleep_for(std::chrono::milliseconds(1)); + adc_8478_param p_adc{0}; + p_adc.param.r_or_w_h = p_adc.param.r_or_w_l = 0; + p_adc.param.addr_l = 0; + p_adc.param.addr_h = addr; + p_adc.param.val_l = bank; + p_adc.param.val_h = val; + fpgaComm->write(A_or_B ? 4 : 7, p_adc.value); + uint32_t reg1_v; + fpgaComm->read(1, reg1_v); + Mode_FPGA reg1 = *((Mode_FPGA *)®1_v); + A_or_B ? reg1.adcA = 1 : reg1.adcB = 1; + fpgaComm->write(1, *((uint32_t *)®1)); + A_or_B ? reg1.adcA = 0 : reg1.adcB = 0; + fpgaComm->write(1, *((uint32_t *)®1)); + // std::this_thread::sleep_for(std::chrono::microseconds(100)); + fpgaComm->write(5, reg5 & 0xffff3fff); // adc 配置使能关闭 +} + +uint32_t MultiFrameCapture_8478_HL::read_adc_8478(int bank, int addr, bool A_or_B) +{ + uint32_t reg5 = 0; + fpgaComm->read(5, reg5); + fpgaComm->write(5, reg5 | 0xc000); // adc 配置使能打开 + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + adc_8478_param p_adc{0}; + p_adc.param.r_or_w_h = 0; + p_adc.param.r_or_w_l = 2; + p_adc.param.addr_l = 0; + p_adc.param.addr_h = addr; + p_adc.param.val_l = bank; + p_adc.param.val_h = 0; + fpgaComm->write(A_or_B ? 4 : 7, p_adc.value); + uint32_t reg1_v; + fpgaComm->read(1, reg1_v); + Mode_FPGA reg1 = *((Mode_FPGA *)®1_v); + A_or_B ? reg1.adcA = 1 : reg1.adcB = 1; + fpgaComm->write(1, *((uint32_t *)®1)); + A_or_B ? reg1.adcA = 0 : reg1.adcB = 0; + fpgaComm->write(1, *((uint32_t *)®1)); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + fpgaComm->write(5, reg5 & 0xffff3fff); // adc 配置使能关闭 + uint32_t read_reg = 0; + fpgaComm->read(3, read_reg); + return read_reg; +} + +void MultiFrameCapture_8478_HL::set_exp_8478_single(int exp_r, int exp_g, int exp_b, int sp, bool A_or_B, bool is_gray) +{ + + int pix_counter = sp / 3 - 10; + // set_pixel_count_8478(pix_counter,is_gray); + int exp_max = pix_counter - 10; + if (exp_r > exp_max) + exp_r = exp_max; + if (exp_g > exp_max) + exp_g = exp_max; + if (exp_b > exp_max) + exp_b = exp_max; + + write_adc_8478(bank_change[1], 0x7, 0, A_or_B); // exp R start + write_adc_8478(bank_change[1], 0x8, 0x35, A_or_B); + write_adc_8478(bank_change[1], 0x9, (exp_r & 0x7f00) / 0x100, A_or_B); // exp R end + write_adc_8478(bank_change[1], 0xa, exp_r & 0xff, A_or_B); + + write_adc_8478(bank_change[1], 0xe, 0, A_or_B); // exp G start + write_adc_8478(bank_change[1], 0xf, 0x35, A_or_B); + write_adc_8478(bank_change[1], 0x10, (exp_g & 0x7f00) / 0x100, A_or_B); // exp G end + write_adc_8478(bank_change[1], 0x11, exp_g & 0xff, A_or_B); + + write_adc_8478(bank_change[1], 0x15, 0, A_or_B); // exp B start + write_adc_8478(bank_change[1], 0x16, 0x35, A_or_B); + write_adc_8478(bank_change[1], 0x17, (exp_b & 0x7f00) / 0x100, A_or_B); // exp B end + write_adc_8478(bank_change[1], 0x18, exp_b & 0xff, A_or_B); +} + +void MultiFrameCapture_8478_HL::set_led_off() +{ + for (int i = 0; i < 2; i++) + { + write_adc_8478(bank_change[1], 0x7, 0, i); // exp R start + write_adc_8478(bank_change[1], 0x8, 0, i); + write_adc_8478(bank_change[1], 0x9, 0, i); // exp R end + write_adc_8478(bank_change[1], 0xa, 0, i); + + write_adc_8478(bank_change[1], 0xe, 0, i); // exp G start + write_adc_8478(bank_change[1], 0xf, 0, i); + write_adc_8478(bank_change[1], 0x10, 0, i); // exp G end + write_adc_8478(bank_change[1], 0x11, 0, i); + + write_adc_8478(bank_change[1], 0x15, 0, i); // exp B start + write_adc_8478(bank_change[1], 0x16, 0, i); + write_adc_8478(bank_change[1], 0x17, 0, i); // exp B end + write_adc_8478(bank_change[1], 0x18, 0, i); + } +} + +void MultiFrameCapture_8478_HL::set_pixel_count_8478(int val, bool is_gray) +{ + + val = val - 10; + //fpgaComm->write(20, ((val & 0xffff) * 0x10000) * 3 + (val & 0xffff) * 3); + fpgaComm->write(19, ((val & 0xffff) * 0x10000) * 3 + (val & 0xffff) * 3); + + write_adc_8478(bank_change[1], 1, (val & 0x7f00) / 0x100, true); // count0 -A + write_adc_8478(bank_change[1], 2, val & 0xff, true); + write_adc_8478(bank_change[1], 1, (val & 0x7f00) / 0x100, false); // count0 -B + write_adc_8478(bank_change[1], 2, val & 0xff, false); + if (is_gray) + return; + + write_adc_8478(bank_change[1], 3, (val & 0x7f00) / 0x100, true); // count1 -A + write_adc_8478(bank_change[1], 4, val & 0xff, true); + write_adc_8478(bank_change[1], 3, (val & 0x7f00) / 0x100, false); // count1 -B + write_adc_8478(bank_change[1], 4, val & 0xff, false); + + write_adc_8478(bank_change[1], 5, (val & 0x7f00) / 0x100, true); // count2 -A + write_adc_8478(bank_change[1], 6, val & 0xff, true); + write_adc_8478(bank_change[1], 5, (val & 0x7f00) / 0x100, false); // count2 -B + write_adc_8478(bank_change[1], 6, val & 0xff, false); +} + +void MultiFrameCapture_8478_HL::set_digital_offset_8478(int channel, int val, bool A_or_B, int color) +{ + if (channel < 0 || channel > 8) + return; + if (color < 0 || color > 2) + return; + int s_addr = ((color == 0) ? 7 : ((color == 2) ? 1 : 0x1c)); + int bank = color == 0 ? 0 : 3; + val = val & 0x1ff; + write_adc_8478(bank_change[bank], s_addr + channel * 2, val < 255 ? 1 : 0, A_or_B); + write_adc_8478(bank_change[bank], s_addr + 1 + channel * 2, val & 0xff, A_or_B); +} + +void MultiFrameCapture_8478_HL::set_digital_gain_8478(int channel, uint8_t val, bool A_or_B, int color) +{ + if (channel < 0 || channel > 8) + return; + if (color < 0 || color > 2) + return; + int s_addr = ((color == 0) ? 0x19 : ((color == 2) ? 0x13 : 0x2e)); + int bank = color == 0 ? 0 : 3; + write_adc_8478(bank_change[bank], s_addr + channel, val, A_or_B); +} + +void MultiFrameCapture_8478_HL::set_dpi_mode(int type) +{ + write_adc_8478(bank_change[1], 0x38, 0x30, true); + write_adc_8478(bank_change[1], 0x38, 0x30, false); + int val = 0; + if(type == 1) val = 3; + if(type == 2) val = 0; + if(type == 3) val = 1; + write_adc_8478(bank_change[0], 0x33, val, true); + write_adc_8478(bank_change[0], 0x33, val, false); +} + +void MultiFrameCapture_8478_HL::set_BOS_postion(uint32_t rise, uint32_t fall) +{ + write_adc_8478(bank_change[2], 0x1, (rise & 0xff00) / 0x100, true); // A面 BOS 起始位置 + write_adc_8478(bank_change[2], 0x2, rise & 0xff, true); + + write_adc_8478(bank_change[2], 0x3, (fall & 0xff00) / 0x100, true); // A面 BOS 结束位置 + write_adc_8478(bank_change[2], 0x4, fall & 0xff, true); + + write_adc_8478(bank_change[2], 0x1, (rise & 0xff00) / 0x100, false); // B面 BOS 起始位置 + write_adc_8478(bank_change[2], 0x2, rise & 0xff, false); + + write_adc_8478(bank_change[2], 0x3, (fall & 0xff00) / 0x100, false); // B面 BOS 结束位置 + write_adc_8478(bank_change[2], 0x4, fall & 0xff, false); +} + +void MultiFrameCapture_8478_HL::set_EN_postion(uint32_t rise, uint32_t fall) +{ + write_adc_8478(bank_change[2], 0xd, (rise & 0xff00) / 0x100, true); // A面 EN 起始位置 + write_adc_8478(bank_change[2], 0xe, rise & 0xff, true); + + write_adc_8478(bank_change[2], 0xf, (fall & 0xff00) / 0x100, true); // A面 EN 结束位置 + write_adc_8478(bank_change[2], 0x10, fall & 0xff, true); + + write_adc_8478(bank_change[2], 0xd, (rise & 0xff00) / 0x100, false); // B面 EN 起始位置 + write_adc_8478(bank_change[2], 0xe, rise & 0xff, false); + + write_adc_8478(bank_change[2], 0xf, (fall & 0xff00) / 0x100, false); // B面 EN 结束位置 + write_adc_8478(bank_change[2], 0x10, fall & 0xff, false); +} + +void MultiFrameCapture_8478_HL::set_7864A_current_ctrl(uint32_t current) +{ + if (current > 6) + return; + write_adc_8478(bank_change[2], 0x1a, current * 0x10 + current, false); + write_adc_8478(bank_change[2], 0x1b, current * 0x10 + current, false); + write_adc_8478(bank_change[2], 0x1c, current * 0x10 + current, false); + + write_adc_8478(bank_change[2], 0x1a, current * 0x10 + current, true); + write_adc_8478(bank_change[2], 0x1b, current * 0x10 + current, true); + write_adc_8478(bank_change[2], 0x1c, current * 0x10 + current, true); +} + +void MultiFrameCapture_8478_HL::set_LED_PTN_8478(bool is_bw) +{ + if (is_bw) + { + write_adc_8478(bank_change[0], 0x3d, 0x01, false); + write_adc_8478(bank_change[0], 0x3d, 0x01, true); + return; + } + write_adc_8478(bank_change[0], 0x3d, 0x11, false); + write_adc_8478(bank_change[0], 0x3d, 0x11, true); +} + +void MultiFrameCapture_8478_HL::set_ADC_config_frequency(uint32_t freq) +{ + uint32_t reg2 = 0; + fpgaComm->read(2, reg2); + fpgaComm->write(2, (reg2 & 0xffffffe1) | (freq << 1)); // adc 配置 频率 +} + +void MultiFrameCapture_8478_HL::set_cis_type_hl(bool is_hl) +{ + uint32_t reg2 = 0; + fpgaComm->read(2, reg2); + fpgaComm->write(2, (reg2 & 0xffffffdf) | (is_hl ? 0x20: 0x0)); // 设置CIS类型 华菱 +} + +cv::Mat MultiFrameCapture_8478_HL::merge_8478(cv::Mat src, bool color, uint32_t version) +{ + if (!color) + return src; + cv::Mat dst(src.rows, src.cols / 3, CV_8UC3); + uint32_t width = src.cols / 6; + cv::insertChannel(src(cv::Rect(0, 0, src.cols / 6, src.rows)), dst(cv::Rect(0, 0, dst.cols / 2, dst.rows)), 0); + cv::insertChannel(src(cv::Rect(src.cols / 3, 0, src.cols / 6, src.rows)), dst(cv::Rect(0, 0, dst.cols / 2, dst.rows)), 2); + cv::insertChannel(src(cv::Rect(src.cols / 3 * 2, 0, src.cols / 6, src.rows)), dst(cv::Rect(0, 0, dst.cols / 2, dst.rows)), 1); + cv::insertChannel(src(cv::Rect(src.cols / 6, 0, src.cols / 6, src.rows)), dst(cv::Rect(dst.cols / 2, 0, dst.cols / 2, dst.rows)), 0); + cv::insertChannel(src(cv::Rect(src.cols / 6 * 3, 0, src.cols / 6, src.rows)), dst(cv::Rect(dst.cols / 2, 0, dst.cols / 2, dst.rows)), 2); + cv::insertChannel(src(cv::Rect(src.cols / 6 * 5, 0, src.cols / 6, src.rows)), dst(cv::Rect(dst.cols / 2, 0, dst.cols / 2, dst.rows)), 1); + return dst; +} + +void MultiFrameCapture_8478_HL::single_correct(std::uint32_t mode) +{ + std::vector sup_correct_dpi{1, 2, 3, 0x10, 0x11,0x20,0x21}; + union correct_mode_ + { + struct + { + uint32_t dpi : 16; + uint32_t color_mode : 8; + uint32_t correct_mode : 8; + } param; + uint32_t value; + }; + correct_mode_ tmp; + tmp.value = mode; + if (std::count(sup_correct_dpi.begin(), sup_correct_dpi.end(), tmp.param.dpi) && (tmp.param.color_mode < 2)) + { + auto param = Get_Static_CorrectParam().GetFpgaparam_8478(tmp.param.dpi, tmp.param.color_mode); + if (tmp.param.correct_mode == 1) + creatLUTData(tmp.param.dpi, tmp.param.color_mode, param); + else if (tmp.param.correct_mode == 2) + creatLUTData_gray(tmp.param.dpi, tmp.param.color_mode, param); + } +} \ No newline at end of file diff --git a/capimage/MultiFrameCapture_8478_HL.h b/capimage/MultiFrameCapture_8478_HL.h new file mode 100644 index 0000000..fc10e8d --- /dev/null +++ b/capimage/MultiFrameCapture_8478_HL.h @@ -0,0 +1,170 @@ +#pragma once +#include "ICapturer.h" +#include "ThreadPool.h" +class FpgaComm; +class gVideo; +class Gpio; + +class MultiFrameCapture_8478_HL : public ICapturer +{ +public: + MultiFrameCapture_8478_HL(); + virtual ~MultiFrameCapture_8478_HL(); + virtual void open(); + virtual void open(HGScanConfig config, FPGAConfigParam fpgaparam){}; + virtual void open(HGScanConfig config, FPGAConfigParam_8478 fpgaparam); + virtual void close(); + virtual void start(); + virtual void stop(); + virtual bool is_runing(); + virtual void snap(); + virtual void snap(frame_data_info info); + virtual cv::Size frame_data_size(); + virtual void stopsnap(); + virtual int getautosizeheight(); + virtual void set_size(int width, int height); + virtual void set_sp(int sp); + + virtual void *readFrame(int timeout); + virtual frame_data_info ReadMultiFrame(int state); + virtual void set_gain(int ix, int val); + virtual void set_offset(int ix, int val); + virtual void set_expo(int ix, int val); + + virtual std::shared_ptr regs(); + virtual void reset(); + virtual int width(); + virtual int height(); + virtual int color(); + virtual void init_autocorrect(int colormode); + virtual void setcapturecall(std::function callback) + { + m_captureCallback = callback; + }; + virtual void Fpga_regsAccess_reset(bool enable); + virtual uint32_t multi_frame_counts() { return frame_count; } + virtual uint32_t multi_curr_snap_index() { return curr_frame_snap_index; } + virtual void single_correct(std::uint32_t mode); + virtual cv::Mat read_one_frame() override; + cv::Mat merge_8478(cv::Mat src, bool color, uint32_t version); + + void init_imagedatabuffer(); + void free_imagedatabuffer(); + void update_imgdatainfo(void *itemmat, frame_data_info &info, uint32_t h, uint32_t w); + void update_imgdatainfo(void *itemmat, uint32_t h, uint32_t w); + +private: + void configFPGAParam(int mode, int dpi); + void configFPGAParam_digital_gain(int mode, int dpi); + void init_lutdate(); + void openDevice(int dpi, int mode); + void creatcorrectconfig(int dpi, int mode); + bool saveLutImg(int dpi, int mode, bool black); + void correctcolor(int correctmode); + void fpga_reset(); + void fpga_reload(); +public: + // 8478 寄存器设置函数 + void set_ADC_config_frequency(uint32_t freq); + void set_cis_type_hl(bool is_hl); + void init_adc_8478(); + void write_adc_8478(int bank, int addr, int val, bool A_or_B); + uint32_t read_adc_8478(int bank, int addr, bool A_or_B); + void set_exp_8478_single(int exp_r, int exp_g, int exp_b, int sp, bool A_or_B, bool is_gray); + void set_led_off(); + void set_pixel_count_8478(int val, bool is_gray); + void set_digital_offset_8478(int channel, int val, bool A_or_B, int color); + void set_digital_gain_8478(int channel, uint8_t val, bool A_or_B, int color); + void set_dpi_mode(int type); + void set_BOS_postion(uint32_t rise, uint32_t fall); + void set_EN_postion(uint32_t rise, uint32_t fall); + void set_7864A_current_ctrl(uint32_t current); + void set_LED_PTN_8478(bool is_bw); + +private: + std::function m_captureCallback; + std::shared_ptr video; + std::shared_ptr vdd_cis_3voff_pin; + std::shared_ptr vdd_vis_5ven_pin; + std::shared_ptr reset_pin; + std::shared_ptr image_in_transfer_pin; + std::shared_ptr initDone_pin; + std::shared_ptr fpgaLoad; + std::shared_ptr fpgaComm; + std::shared_ptr fpga_conf_initn; + std::shared_ptr fpga_conf_done; + ThreadPool snapthread; + uint32_t m_fpgaversion; + uint32_t frame_height; + uint32_t frame_count; + uint32_t curr_frame_snap_index; + const int FPGA_MAX_HEIGHT_SUP = 1048576; + frame_data_info pimgdata_info; + std::future snap_fu; + bool bcorrecting; + bool b_stop_snap; + std::thread m_correctthread; + HGScanConfig m_config; + FPGAConfigParam_8478 m_fpgaparam; + + const uint8_t bank_value[256] = + // {0x15,0x78,0x80,0x90,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //bank 0 32us + // 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + // //0x40,0x40,0x40,0x05,0x46,0x23,0x54,0x62,0x35,0x46,0x23,0x00,0x03,0x04,0x05,0x01, //敦南默认值 + // 0x40,0x40,0x80,0x03,0x25,0x46,0x32,0x54,0x63,0x25,0x46,0x00,0x03,0x04,0x05,0x01, + // 0x01,0x00,0x06,0x06,0x03,0x05,0x00,0x14,0x07,0x0B,0x23,0x27,0x00,0x01,0x00,0x00, + + // 0x35,0x02,0x04,0x02,0x04,0x02,0x04,0x00,0x01,0x02,0x00,0x00,0x00,0x01,0x00,0x01, //bank 1 + // 0x02,0x00,0x00,0x00,0x01,0x00,0x01,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00, + // 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + // 0x55,0x00,0x41,0x00,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x01, //bank 2 + // 0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x06,0x00, + // 0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + // 0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //bank 3 + // 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x00, + // 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40, + // 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + + {0x15, 0x78, 0x80, 0x90, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // bank 0 64us + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, + // 0x40,0x40,0x40,0x05,0x46,0x23,0x54,0x62,0x35,0x46,0x23,0x00,0x03,0x04,0x05,0x01, //敦南默认值 + 0x40, 0x40, 0x80, 0x03, 0x25, 0x46, 0x32, 0x54, 0x63, 0x25, 0x46, 0x00, 0x03, 0x04, 0x05, 0x01, + 0x01, 0x00, 0x06, 0x00, 0x05, 0x03, 0x00, 0x14, 0x07, 0x0B, 0x24, 0x28, 0x00, 0x01, 0x00, 0x00, + // 0x01, 0x00, 0x06, 0x06, 0x03, 0x05, 0x00, 0x14, 0x07, 0x0B, 0x25, 0x29, 0x00, 0x01, 0x00, 0x00, + + 0x35, 0x03, 0xdf, 0x03, 0xdf, 0x03, 0xdf, 0x00, 0x01, 0x03, 0xb6, 0x00, 0x00, 0x01, 0x00, 0x01, // bank 1 + 0x03, 0xb6, 0x00, 0x00, 0x01, 0x00, 0x01, 0x03, 0xb6, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x55, 0x00, 0x54, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x03, // bank 2 + 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // bank 3 + 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + //.colorSp_200 = 2606 , .graySp_200= 7818,.colorSp_300 = 2804 ,.graySp_300 = 8412,.colorSp_600 = 3405 ,.graySp_600 = 10215 + + const uint8_t bank_change[4] = {0x15, 0x35, 0x55, 0x75}; + union adc_8478_param + { + struct + { + uint32_t val_l : 8; // 数据位 + uint32_t addr_l : 6; // adc 寄存器地址 + uint32_t r_or_w_l : 2; // 读写标志位 0x11 读 0x01 写 8458 0x10 读 0x00 写 8478 + uint32_t val_h : 8; + uint32_t addr_h : 6; + uint32_t r_or_w_h : 2; + } param; + uint32_t value; + }; +}; diff --git a/capimage/SysInforTool.cpp b/capimage/SysInforTool.cpp new file mode 100644 index 0000000..1992ad7 --- /dev/null +++ b/capimage/SysInforTool.cpp @@ -0,0 +1,182 @@ +#pragma once +#include "SysInforTool.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int errno; +static void get_system_output(char *cmd, char *output, int size) +{ + FILE *fp = NULL; + fp = popen(cmd, "r"); + if (fp) + { + if (fgets(output, size, fp) != NULL) + { + if (output[strlen(output) - 1] == '\n') + output[strlen(output) - 1] = '\0'; + } + pclose(fp); + } +} + +/*block to kbyte*/ +static unsigned long kscale(unsigned long m_block, unsigned long m_kbyte) +{ + + return ((unsigned long long)m_block * m_kbyte + 1024 / 2) / 1024; +} + +/*convert size to GB MB KB*/ +static void convert_size(float m_size, int *dest) +{ + if ((((m_size / 1024.0) / 1024.0)) >= 1.0) + { + *dest = (int)((m_size / 1024.0) / 1024.0); + } + else if ((m_size / 1024.0) >= 1.0) + { + *dest = (int)(m_size / 1024); + } +} + +SysInforTool::SysInforTool(ScannerSysInfo tinfo) +{ + m_sysinfo = tinfo; +} + +SysInforTool::~SysInforTool() +{ +} + +/*获取文件系统信息*/ +int SysInforTool::get_fileSystem_info(const char *fileSystem_name, struct fileSystem_info *fi) +{ + struct statfs buf; + float fileSystem_total_size = 0; + float fileSystem_free_size = 0; + + if (statfs(fileSystem_name, &buf)) + { + fprintf(stderr, "statfs %s\n", strerror(errno)); + return -1; + } + + switch (buf.f_type) + { + case 0xEF51: + case 0xEF53: + sprintf(fi->fileSystem_format, "EXT"); + break; + + case 0x4d44: + sprintf(fi->fileSystem_format, "FAT"); + break; + + case 0x5346544e: + sprintf(fi->fileSystem_format, "NIFS"); + break; + + default: + sprintf(fi->fileSystem_format, "unknown"); + break; + } + + // bzero(&fi->fileSystem_total_capacity,sizeof(fi->fileSystem_total_capacity)); + // bzero(&fi->fileSystem_free_capacity,sizeof(fi->fileSystem_free_capacity)); + + printf("blocks %ld\n", buf.f_blocks); + printf("bfree %ld\n", buf.f_bfree); + printf("bsize %ld\n", buf.f_bsize); + + fileSystem_total_size = + (float)(kscale(buf.f_blocks, buf.f_bsize)); + fileSystem_free_size = + (float)(kscale(buf.f_bfree, buf.f_bsize)); + + printf("total %f\n", fileSystem_total_size); + printf("free %f\n", fileSystem_free_size); + + fi->fileSystem_total_capacity = fileSystem_total_size; + fi->fileSystem_free_capacity = fileSystem_free_size; + // convert_size(fileSystem_total_size,(int*)(&fi->fileSystem_total_capacity)); + // convert_size(fileSystem_free_size,(int*)(&fi->fileSystem_free_capacity)); + + bzero(fi->fileSystem_permissions, sizeof(fi->fileSystem_permissions)); + sprintf(fi->fileSystem_permissions, "rw"); + + return 0; +} + +std::string SysInforTool::GetSysInfo() +{ + struct sysinfo memInfo; + sysinfo(&memInfo); + m_sysinfo.MemTotal = memInfo.totalram; + fileSystem_info fileinfo; + get_fileSystem_info("/", &fileinfo); + m_sysinfo.DiskTotal = fileinfo.fileSystem_total_capacity; // KB + m_sysinfo.DiskUsed = fileinfo.fileSystem_free_capacity; // KB + + struct utsname t_uname; + if (uname(&t_uname) != 0) + perror("uname doesn't return 0, so there is an error"); + + printf("System Name = %s\n", t_uname.sysname); + printf("Node Name = %s\n", t_uname.nodename); + printf("Version = %s\n", t_uname.version); + printf("Release = %s\n", t_uname.release); + printf("Machine = %s\n", t_uname.machine); + if (strcmp(t_uname.nodename, "linaro-alip") == 0 && strcmp(t_uname.machine, "armv7l") == 0) + { + m_sysinfo.Systype = SysType::Sys_Linux_Debian; + m_sysinfo.CPU = SCPU::CPU_3288; + printf("Machine = %s CPU = %s \n", "Sys_Linux_Debian", "CPU_3288"); + } + else if (strcmp(t_uname.nodename, "linaro-alip") == 0 && strcmp(t_uname.machine, "aarch64") == 0) + { + m_sysinfo.Systype = SysType::Sys_Linux_Debian; + m_sysinfo.CPU = SCPU::CPU_3399; + printf("Machine = %s CPU = %s \n", "Sys_Linux_Debian", "CPU_3399"); + } + m_sysinfo.Cistype = HGCISType::CIS_DUNNAN_MONO_V0; + m_sysinfo.MtType = SMBType::MB_DRV_ANLU; + char output[512]; + get_system_output("uname -a", output, sizeof(output)); + std::string ver(output); + m_sysinfo.KernelVersion = ver; + printf("system version = %s \n", ver.c_str()); + json j; + struct2json(j, m_sysinfo); + std::ofstream o("/usr/local/huago/sysinfo.json"); + o << std::setw(4) << j << std::endl; + o.close(); + return j.dump(); +} + +void SysInforTool::struct2json(json &j, ScannerSysInfo &info) +{ + j["CPU"] = info.CPU; + j["Systype"] = info.Systype; + j["Screentype"] = info.Screentype; + j["MtBoardVersion"] = info.MtBoardVersion; + j["MtType"] = info.MtType; + j["FPGAVersion"] = info.FPGAVersion; + j["Cistype"] = info.Cistype; + j["MaxRes"] = info.ResSup; + j["MemTotal"] = info.MemTotal; + j["DiskTotal"] = info.DiskTotal; + j["DiskUsed"] = info.DiskUsed; + j["KernelVersion"] = info.KernelVersion; + j["Have_EthernPort"] = info.Have_EthernPort; + j["ServiceVersion"] = info.ServiceVersion; + j["UsbProtocol"] = info.UsbProtocol; +} \ No newline at end of file diff --git a/capimage/SysInforTool.h b/capimage/SysInforTool.h new file mode 100644 index 0000000..5874a0d --- /dev/null +++ b/capimage/SysInforTool.h @@ -0,0 +1,28 @@ +#pragma once +#include "scannersysinfo.h" +#include "json.hpp" + +using json = nlohmann::json; + +struct fileSystem_info +{ + char fileSystem_format[8]; + unsigned int fileSystem_total_capacity; + unsigned int fileSystem_free_capacity; + char fileSystem_permissions[3]; +}; + +class SysInforTool +{ +public: + SysInforTool(ScannerSysInfo tinfo); + ~SysInforTool(); + std::string GetSysInfo(); + +private: + int get_fileSystem_info(const char *fileSystem_name, struct fileSystem_info *fi); + void struct2json(json &j, ScannerSysInfo &info); + +private: + ScannerSysInfo m_sysinfo; +}; diff --git a/capimage/correct_ultis.cpp b/capimage/correct_ultis.cpp new file mode 100644 index 0000000..5feb51e --- /dev/null +++ b/capimage/correct_ultis.cpp @@ -0,0 +1,658 @@ +#include +#include +#include +#include +#include "correct_ultis.h" +#include "CorrectParam.h" +#include "commondef.h" +#define USE_NEWFLAT +using namespace cv; + +void initStep() +{ + for (int i = 0; i < 2; i++) + { + for (int j = 0; j < 3; j++) + { + expStep[i][j] = 600; + } + } + for (int i = 0; i < 12; i++) + { + offsetStep[i] = 256; + printf("offsetStep[%d]=%d \n", i, offsetStep[i]); + } +} + +cv::Mat extractRepresentRow2(const cv::Mat &src) +{ + cv::Mat BWbalenceSrc(1, src.cols * src.channels(), CV_8UC1); + + cv::Mat temp_imageBW(src.rows, src.cols * src.channels(), CV_8UC1, src.data); + + for (size_t i = 0; i < BWbalenceSrc.cols; i++) + BWbalenceSrc.at(0, i) = cv::mean(temp_imageBW(cv::Rect(i, 0, 1, temp_imageBW.rows)))[0]; + + return BWbalenceSrc; +} + +cv::Mat loadLUT(const std::string &file) +{ + cv::Mat dataFile = cv::imread(file, cv::IMREAD_ANYCOLOR); + + long total = dataFile.total(); + int step = total / 256; + + int channel = 1; +#ifndef USE_NEWFLAT + if (step == 4896 || step == 7344) + channel = 408; + else if (step == 14688 || step == 22032 || step == 44064) + channel = 432; // 486 +#else + channel = 408; +#endif + cv::Mat lut(step / channel, 256, CV_8UC(channel)); + memcpy(lut.data, dataFile.data, total); + return lut; +} + +void initLut(const std::string lutpath, bool iscolor) +{ + printf("\n-----init lutpath =%s------------", lutpath.c_str()); + lutColorMat.release(); + lutGrayMat.release(); + + if (!lutpath.empty() && (access(lutpath.c_str(), F_OK) == 0)) + { + printf("\n %s", lutpath.c_str()); + if (iscolor) + lutColorMat = loadLUT(lutpath); // 彩色校正值 + else + lutGrayMat = loadLUT(lutpath); // 灰色校正值 + } +} + +void correctColor(cv::Mat &src, int dpi, int mode, bool isText, int is_8478) +{ + cv::Mat lutMat; + std::string path; + if (src.type() == CV_8UC3) + { + if (lutColorMat.empty()) + { + if (is_8478 == 1) + { + FPGAConfigParam_8478 param = Get_Static_CorrectParam().GetFpgaparam_8478(dpi, mode); + path = isText ? param.TextLutPath : param.LutPath; + } + else + { + FPGAConfigParam param = GetFpgaparam(dpi, mode); + path = isText ? param.TextLutPath : param.LutPath; + } + printf("\n %s", path.c_str()); + if (access(path.c_str(), F_OK) != -1) + { + lutColorMat = loadLUT(path); + } + else + { + printf("error error error %s NOT FOUND \n", path.c_str()); + return; + } + } + lutMat = lutColorMat; + } + else + { + if (lutGrayMat.empty()) + { + if (is_8478 == 1) + { + FPGAConfigParam_8478 param = Get_Static_CorrectParam().GetFpgaparam_8478(dpi, mode); + path = isText ? param.TextLutPath : param.LutPath; + } + else + { + FPGAConfigParam param = GetFpgaparam(dpi, mode); + path = isText ? param.TextLutPath : param.LutPath; + } + printf("\n %s", path.c_str()); + if (access(path.c_str(), F_OK) != -1) + { + lutGrayMat = loadLUT(path); + // brightness(lutGrayMat); + } + else + { + printf("error error error %s NOT FOUND", path.c_str()); + return; + } + } + lutMat = lutGrayMat; + } + if (lutMat.empty()) + { + return; + } + + cv::Mat image_temp(src.rows, src.cols * src.channels() / lutMat.channels(), CV_8UC(lutMat.channels()), src.data); + + for (size_t i = 0; i < image_temp.cols; i++) + cv::LUT(image_temp(cv::Rect(i, 0, 1, image_temp.rows)), lutMat(cv::Rect(0, i, 256, 1)), image_temp(cv::Rect(i, 0, 1, image_temp.rows))); +} + +void creatLUTData(int dpi, int mode, FPGAConfigParam param) +{ + printf("eneter creatLUTData \n"); + auto colormode = mode == 1 ? IMREAD_COLOR : IMREAD_GRAYSCALE; + std::string blackPath = param.Flat_BwPath; + std::string whitePath = param.Flat_WhitePath; + std::string lutsavePath = param.LutPath; + cv::Mat lut; + cv::Mat twMat = cv::imread(whitePath, IMREAD_ANYCOLOR); + cv::Mat tbMat = cv::imread(blackPath, IMREAD_ANYCOLOR); + cv::Mat wMat, bMat; + if (mode == 1) + { + wMat = cv::Mat(twMat.rows, twMat.cols * 3, CV_8UC1, twMat.data); + bMat = cv::Mat(twMat.rows, twMat.cols * 3, CV_8UC1, tbMat.data); + } + else + { + wMat = twMat; + bMat = tbMat; + } + + // lut = create_lut(extractRepresentRow2(bMat), extractRepresentRow2(wMat), dpi, mode); // add by liuyong: 刘丁维提供 2019/4/12 + lut = calcLUT(extractRepresentRow2(bMat), extractRepresentRow2(wMat), false); + // Mat dst(bMat.cols * bMat.channels(), 256, CV_8UC1); + // memcpy(dst.data, lut.data, bMat.cols * bMat.channels() * 256); + cv::imwrite(param.LutPath, lut); + system(("cp -f " + param.LutPath + " " + param.LutPath + "-back").c_str()); + lut = calcLUT(extractRepresentRow2(bMat), extractRepresentRow2(wMat), true); + cv::imwrite(param.TextLutPath, lut); + system(("cp -f " + param.TextLutPath + " " + param.TextLutPath + "-back").c_str()); + printf("exit creatLUTData \n"); +} + +void creatLUTData_gray(int dpi, int mode, FPGAConfigParam param) +{ + printf("eneter creatLUTData_gray \n"); + auto colormode = mode == 1 ? IMREAD_COLOR : IMREAD_GRAYSCALE; + std::string blackPath = param.Flat_BwPath; + std::string whitePath = param.Flat_WhitePath; + std::string lutsavePath = param.LutPath; + cv::Mat lut; + cv::Mat twMat = cv::imread(whitePath, IMREAD_ANYCOLOR); + cv::Mat tbMat = cv::imread(blackPath, IMREAD_ANYCOLOR); + cv::Mat tw_dynamic = cv::imread(param.Flat_WhitePath.substr(0, param.Flat_WhitePath.length() - 4) + "_dynamic.bmp"); + cv::Mat wMat, bMat, w_dynamic; + if (twMat.empty() && tbMat.empty()) + return; + if (mode == 1) + { + wMat = cv::Mat(twMat.rows, twMat.cols * 3, CV_8UC1, twMat.data); + bMat = cv::Mat(twMat.rows, twMat.cols * 3, CV_8UC1, tbMat.data); + } + else + { + wMat = twMat; + bMat = tbMat; + } + if (!tw_dynamic.empty()) + { + w_dynamic = mode == 1 ? cv::Mat(tw_dynamic.rows, tw_dynamic.cols * 3, CV_8UC1, tw_dynamic.data) : tw_dynamic; + std::vector w; + w.push_back(colMean(bMat)); + w.push_back(colMean(wMat)); + w.push_back(colMean(w_dynamic)); + lut = calcLUT_gray(w); + } + else + lut = calcLUT_gray(bMat, wMat); + // lut = create_lut(extractRepresentRow2(bMat), extractRepresentRow2(wMat), dpi, mode); // add by liuyong: 刘丁维提供 2019/4/12 + + cv::imwrite(param.LutPath, lut); + // lut = calcLUT_gray(bMat,wMat); + // cv::imwrite(param.TextLutPath, lut); + printf("exit creatLUTData_gray \n"); +} + +void creatLUTData(int dpi, int mode, FPGAConfigParam_8478 param) +{ + FPGAConfigParam tmp_{}; + tmp_.Flat_BwPath = param.Flat_BwPath; + tmp_.Flat_WhitePath = param.Flat_WhitePath; + tmp_.LutPath = param.LutPath; + tmp_.TextLutPath = param.TextLutPath; + creatLUTData(dpi, mode, tmp_); +} + +void creatLUTData_gray(int dpi, int mode, FPGAConfigParam_8478 param) +{ + FPGAConfigParam tmp_{}; + tmp_.Flat_BwPath = param.Flat_BwPath; + tmp_.Flat_WhitePath = param.Flat_WhitePath; + tmp_.LutPath = param.LutPath; + tmp_.TextLutPath = param.TextLutPath; + creatLUTData_gray(dpi, mode, tmp_); +} + +void creatLUTData(int dpi, int mode) +{ + printf("eneter creatLUTData \n"); + auto param = GetFpgaparam(dpi, mode); + auto colormode = mode == 1 ? IMREAD_COLOR : IMREAD_GRAYSCALE; + std::string blackPath = param.Flat_BwPath; + std::string whitePath = param.Flat_WhitePath; + std::string lutsavePath = param.LutPath; + cv::Mat lut; + cv::Mat twMat = cv::imread(whitePath, IMREAD_ANYCOLOR); + cv::Mat tbMat = cv::imread(blackPath, IMREAD_ANYCOLOR); + cv::Mat wMat, bMat; + if (twMat.empty() && tbMat.empty()) + return; + if (mode == 1) + { + wMat = cv::Mat(twMat.rows, twMat.cols * 3, CV_8UC1, twMat.data); + bMat = cv::Mat(twMat.rows, twMat.cols * 3, CV_8UC1, tbMat.data); + } + else + { + wMat = twMat; + bMat = tbMat; + } + + // lut = create_lut(extractRepresentRow2(bMat), extractRepresentRow2(wMat), dpi, mode); // add by liuyong: 刘丁维提供 2019/4/12 + lut = calcLUT(extractRepresentRow2(bMat), extractRepresentRow2(wMat), false); + // Mat dst(bMat.cols * bMat.channels(), 256, CV_8UC1); + // memcpy(dst.data, lut.data, bMat.cols * bMat.channels() * 256); + cv::imwrite(param.LutPath, lut); + lut = calcLUT(extractRepresentRow2(bMat), extractRepresentRow2(wMat), true); + cv::imwrite(param.TextLutPath, lut); + printf("exit creatLUTData \n"); +} + +FPGAConfigParam GetFpgaparam(int dpi, int mode) +{ + FPGAConfigParam param = Get_Static_CorrectParam().GetFpgaparam(dpi, mode); + return param; +} + +void SaveFpgaparam(FPGAConfigParam ¶m) +{ + Get_Static_CorrectParam().SaveCorrectParam(param); +} + +cv::Mat colMean(const cv::Mat &image) +{ + cv::Mat meanMat(1, image.step, CV_8UC1); + cv::Mat tempMat(image.rows, image.step, CV_8UC1, image.data); + for (int i = 0; i < tempMat.step; i++) + meanMat.data[i] = cv::mean(tempMat(cv::Rect(i, 0, 1, tempMat.rows)))[0]; + + return meanMat; +} + +float gamma(float value, float ex) +{ + return cv::pow(value / 255.0f, 1.0f / ex) * 255.0f + 0.5f; +} + +#define GAMMA_EX 1.7f +#define BLACK_OFFSET 5 +void fittingLUT(const std::vector &points, uchar min_value, uchar max_value, uchar *data) +{ + float step = max_value - min_value + 1; + memset(data, min_value, 127); + memset(data + 127, max_value, 129); + int b = points[0]; + int w = points[1]; + int tb = min_value; + int tw = max_value; + + step = cv::max((float)(tw - tb + 1) / (float)(w - b + 1), 0.0f); + float temp; + for (int j = 0, length = (255 - b + 1); j < length; j++) + { + temp = gamma(tb + step * j, GAMMA_EX) - BLACK_OFFSET; + data[j + b] = cv::min(255, cv::max(0, static_cast(temp))); + } +} + +void fittingLUT_gray(const std::vector &points, uchar min_value, uchar max_value, uchar *data) +{ + float step = max_value - min_value + 1; + memset(data, min_value, 127); + memset(data + 127, max_value, 129); + int b = points[0]; + int w = points[1]; + int tb = min_value; + int tw = max_value; + + step = cv::max((float)(tw - tb + 1) / (float)(w - b + 1), 0.0f); + float temp; + for (int j = 0, length = (255 - b + 1); j < length; j++) + { +#if 0 + temp = gamma(tb + step * j, GAMMA_EX) - BLACK_OFFSET; +#else + temp = tb + step * j; +#endif + data[j + b] = cv::min(255, cv::max(0, static_cast(temp))); + } +} + +#define CHANNEL 408 +cv::Mat calcLUT(const cv::Mat &black, const cv::Mat &white, bool isTextCorrection) +{ + std::vector w; + w.push_back(colMean(black)); + w.push_back(colMean(white)); + cv::Mat lut = createLUT(w, isTextCorrection); + + for (size_t i = 0, block = lut.rows / CHANNEL; i < block; i++) + { + cv::Mat lutROI = lut(cv::Rect(0, i * CHANNEL, 256, CHANNEL)); + cv::Mat tran; + cv::transpose(lutROI, tran); + memcpy(lutROI.data, tran.data, tran.total()); + } + return lut; +} + +cv::Mat splitJoint(const cv::Mat &staticMat, const cv::Mat &dynamicsMat) +{ + cv::Mat dst(1, staticMat.cols, staticMat.type()); + + uchar *ptr_dst = dst.data; + uchar *ptr_mat1 = staticMat.data; + uchar *ptr_mat2 = dynamicsMat.data; + + int offset = staticMat.step * 25 / 1000; + cv::Range range1(offset, staticMat.step / 2 - offset); + cv::Range range2(staticMat.step / 2 + offset, staticMat.step - offset); + for (size_t i = 0; i < dst.step; i++) + { + // if (i < range1.start || i > range2.end || (i > range1.end && i < range2.start)) + if (ptr_mat1[i] > ptr_mat2[i] + 50) + ptr_dst[i] = ptr_mat1[i]; + else + ptr_dst[i] = ptr_mat2[i]; + // else + // ptr_dst[i] = ptr_mat2[i]; + } + + return dst; +} + +cv::Mat calcLUT_gray(const cv::Mat &black, const cv::Mat &white) +{ + std::vector w; + w.push_back(colMean(black)); + w.push_back(colMean(white)); + cv::Mat lut = createLUT_gray(w); + + for (size_t i = 0, block = lut.rows / CHANNEL; i < block; i++) + { + cv::Mat lutROI = lut(cv::Rect(0, i * CHANNEL, 256, CHANNEL)); + cv::Mat tran; + cv::transpose(lutROI, tran); + memcpy(lutROI.data, tran.data, tran.total()); + } + return lut; + + // std::vector w; + // w.push_back(colMean(black)); + // w.push_back(colMean(white)); + // if(!dynamic.empty()) + // w.push_back(colMean(dynamic)); + // if (w.size() == 3) + // { + // cv::Mat newWhite = splitJoint(w[1], w[2]); + // w.erase(w.end() - 1); + // w[1] = newWhite; + // } + + // cv::Mat lut = createLUT_gray(w); + + // int channel = (lut.rows % CHANNEL == 0) ? CHANNEL : 459; + // for (size_t i = 0, block = lut.rows / channel; i < block; i++) + // { + // cv::Mat lutROI = lut(cv::Rect(0, i * channel, 256, channel)); + // cv::Mat tran; + // cv::transpose(lutROI, tran); + // memcpy(lutROI.data, tran.data, tran.total()); + // } + // return lut; +} + +cv::Mat calcLUT_gray(std::vector &w) +{ + if (w.size() == 3) + { + cv::Mat newWhite = splitJoint(w[1], w[2]); + w.erase(w.end() - 1); + w[1] = newWhite; + // cv::imwrite("/home/test.bmp",newWhite); + } + + cv::Mat lut = createLUT_gray(w); + + int channel = (lut.rows % CHANNEL == 0) ? CHANNEL : 459; + for (size_t i = 0, block = lut.rows / channel; i < block; i++) + { + cv::Mat lutROI = lut(cv::Rect(0, i * channel, 256, channel)); + cv::Mat tran; + cv::transpose(lutROI, tran); + memcpy(lutROI.data, tran.data, tran.total()); + } + return lut; +} + +cv::Mat create_lut(const cv::Mat &black, const cv::Mat &white, int dpi, bool colormode) +{ +#ifndef USE_NEWFLAT + if (black.empty() || white.empty() || black.channels() != 1 || white.channels() != 1 || black.step != white.step) + return cv::Mat(); + + int channel = 1; + if (black.step == 4896 || black.step == 7344) + channel = 408; + else if (black.step == 14688 || black.step == 22032 || black.step == 44064) + channel = 432; // 486 + + if (channel == 1) + return cv::Mat(); + + const int rows = black.cols / channel; + const int cols = 256; + auto cc = CV_8UC(channel); + Mat lut(rows, cols, CV_8UC(channel)); + const double gain = 255.0 / ((double)Get_Static_CorrectParam().GetFpgaparam(dpi, colormode).MaxBright); + for (size_t i = 0; i < rows; i++) + { + Mat lut_row = lut(cv::Rect(0, i, cols, 1)); + unsigned char *ptr_buffer = lut_row.data; + unsigned char *ptr_black = black.data + i * channel; + unsigned char *ptr_white = white.data + i * channel; + for (size_t j = 0; j < cols; j++) + for (size_t k = 0; k < channel; k++) + { + if (ptr_black[k] >= ptr_white[k]) + { + ptr_buffer[j * channel + k] = 0; + continue; + } + + if (j <= ptr_black[k]) + ptr_buffer[j * channel + k] = 0; + else if (j >= ptr_white[k]) + ptr_buffer[j * channel + k] = 255; + else + { + float val = 255.0f * (j - ptr_black[k]) / (ptr_white[k] - ptr_black[k]) * gain; + ptr_buffer[j * channel + k] = (unsigned char)cv::max(0.0f, cv::min(val, 255.0f)); + } + } + } + cv::Mat saveMat(black.step, 256, CV_8UC1, lut.data); + return saveMat.clone(); +#else + return calcLUT(black, white, false); +#endif +} + +std::vector caculate(const std::vector &points_x, const std::vector &points_y) +{ + int MaxElement = points_x.size() - 1; + // 计算常数f + double f = points_y[0]; + // 求解 + int n, m; + // double a[MaxElement][MaxElement+1]; + std::vector> a; + // a.resize(MaxElement); + for (int i = 0; i < MaxElement; i++) + { + std::vector b; + b.resize(MaxElement + 1); + a.push_back(b); + } + + for (int i = 0; i < MaxElement; i++) + { + for (int j = 0; j < MaxElement; j++) + a[i][j] = cv::pow(points_x[i + 1], MaxElement - j); + a[i][MaxElement] = points_y[i + 1] - f; + } + + int i, j; + n = MaxElement; + + for (j = 0; j < n; j++) + { + double max = 0; + double imax = 0; + for (i = j; i < n; i++) + { + if (imax < cv::abs(a[i][j])) + { + imax = cv::abs(a[i][j]); + max = a[i][j]; // 得到各行中所在列最大元素 + m = i; + } + } + if (cv::abs(a[j][j]) != max) + { + double b = 0; + for (int k = j; k < n + 1; k++) + { + b = a[j][k]; + a[j][k] = a[m][k]; + a[m][k] = b; + } + } + + for (int r = j; r < n + 1; r++) + { + a[j][r] = a[j][r] / max; // 让该行的所在列除以所在列的第一个元素,目的是让首元素为1 + } + + for (i = j + 1; i < n; i++) + { + double c = a[i][j]; + if (c == 0.0) + continue; + for (int s = j; s < n + 1; s++) + { + a[i][s] = a[i][s] - a[j][s] * c; // 前后行数相减,使下一行或者上一行的首元素为0 + } + } + } + for (i = n - 2; i >= 0; i--) + { + for (j = i + 1; j < n; j++) + { + a[i][n] = a[i][n] - a[j][n] * a[i][j]; + } + } + + std::vector result; + for (int k = 0; k < n; k++) + result.push_back(a[k][n]); + result.push_back(f); + return result; +} + +cv::Mat createLUT_gray(const std::vector &mats) +{ + int rows = mats[0].cols; + cv::Mat lut(rows, 256, CV_8UC1); + + double max_val, min_val; + cv::minMaxIdx(mats[0], &min_val, nullptr); + cv::minMaxIdx(mats[1], nullptr, &max_val); + for (size_t i = 0; i < rows; i++) + { + std::vector grayPoints; + for (size_t j = 0; j < mats.size(); j++) + grayPoints.push_back(mats[j].data[i]); + + fittingLUT_gray(grayPoints, static_cast(min_val), static_cast(max_val), lut.data + i * 256); + } + return lut; +} + +cv::Mat createLUT(const std::vector &mats, bool isTextCorrect) +{ + int rows = mats[0].cols; + cv::Mat lut(rows, 256, CV_8UC1); + + double max_val, min_val; + cv::minMaxIdx(mats[0], &min_val, nullptr); + cv::minMaxIdx(mats[1], nullptr, &max_val); + for (size_t i = 0; i < rows; i++) + { + std::vector grayPoints; + for (size_t j = 0; j < mats.size(); j++) + grayPoints.push_back(mats[j].data[i]); + + fittingLUT(grayPoints, static_cast(min_val), static_cast(max_val), lut.data + i * 256); + } + if (isTextCorrect) + { + // std::vector points_x = {0, 25, 205, 255}, points_y = {0, 0, 230, 255}; + std::vector points_x = {0, 25, 215, 255}, points_y = {0, 0, 250, 255}; + // std::vector points_x = {0, 25, 80, 150, 215}, points_y = {0, 0, 80, 170, 255}; + std::vector coefficient = caculate(points_x, points_y); + + uchar buffer[256]; + uchar buffer_B[256]; + for (int i = 0; i < 256; i++) + { + // int temp = coefficient[0] * i * i * i *i+ coefficient[1] * i * i*i + coefficient[2] * i*i + coefficient[3]*i+coefficient[4]; + int temp = coefficient[0] * i * i * i + coefficient[1] * i * i + coefficient[2] * i + coefficient[3]; + buffer[i] = static_cast(cv::min(255, cv::max(0, temp))); + } + + coefficient = caculate({0, 25, 220, 255}, {0, 0, 250, 255}); + for (int i = 0; i < 256; i++) + { + // int temp = coefficient[0] * i * i * i *i+ coefficient[1] * i * i*i + coefficient[2] * i*i + coefficient[3]*i+coefficient[4]; + int temp = coefficient[0] * i * i * i + coefficient[1] * i * i + coefficient[2] * i + coefficient[3]; + buffer_B[i] = static_cast(cv::min(255, cv::max(0, temp))); + } + + cv::Mat lut_lut(256, 1, CV_8UC1, buffer); + cv::Mat lut_lut_B(256, 1, CV_8UC1, buffer_B); + cv::LUT(lut(cv::Rect(0,0,lut.cols,lut.rows/2)), lut_lut, lut(cv::Rect(0,0,lut.cols,lut.rows/2))); + cv::LUT(lut(cv::Rect(0,lut.rows/2,lut.cols,lut.rows/2)), lut_lut_B, lut(cv::Rect(0,lut.rows/2,lut.cols,lut.rows/2))); + + // cv::LUT(lut,lut_lut,lut); + + } + return lut; +} \ No newline at end of file diff --git a/capimage/correct_ultis.h b/capimage/correct_ultis.h new file mode 100644 index 0000000..813582b --- /dev/null +++ b/capimage/correct_ultis.h @@ -0,0 +1,45 @@ +#pragma once +#include +#include +#include "CameraParam.h" + +static cv::Mat lutGrayMat; // 灰色校正值 +static cv::Mat lutColorMat; // 彩色校正值 +static int offsetStep[12]; +static int expStep[2][3]; + +void initStep(); + +cv::Mat colMean(const cv::Mat &image); + +cv::Mat calcLUT(const cv::Mat &black, const cv::Mat &white, bool isTextCorrection); + +cv::Mat calcLUT_gray(const cv::Mat &black, const cv::Mat &white); + +cv::Mat calcLUT_gray(std::vector &w); + +cv::Mat extractRepresentRow2(const cv::Mat &src); + +void initLut(const std::string lutpath, bool iscolor); + +cv::Mat createLUT(const std::vector &mats, bool isTextCorrect); + +cv::Mat createLUT_gray(const std::vector &mats); + +void correctColor(cv::Mat &src, int dpi, int mode, bool isText, int is_8478 = 0); + +void creatLUTData(int dpi, int mode); + +void creatLUTData(int dpi, int mode, FPGAConfigParam param); + +void creatLUTData_gray(int dpi, int mode, FPGAConfigParam param); + +void creatLUTData(int dpi, int mode, FPGAConfigParam_8478 param); + +void creatLUTData_gray(int dpi, int mode, FPGAConfigParam_8478 param); + +FPGAConfigParam GetFpgaparam(int dpi, int mode); + +void SaveFpgaparam(FPGAConfigParam ¶m); + +cv::Mat create_lut(const cv::Mat &black, const cv::Mat &white, int dpi, bool colormode); diff --git a/capimage/deviceconfig.cpp b/capimage/deviceconfig.cpp new file mode 100644 index 0000000..4912a5c --- /dev/null +++ b/capimage/deviceconfig.cpp @@ -0,0 +1,127 @@ +#include "deviceconfig.h" +#include +#include +#include +#include "commondef.h" +#include + +DeviceConfig m_static_deviceconfig; + +DeviceConfig::DeviceConfig() +{ + +} + +DeviceConfig::~DeviceConfig() +{ + +} + +DeviceConfig::DeviceParam DeviceConfig::GetParam() +{ + std::lock_guard lc(m_lock); + json tmp = getjson(); + return json2struct(tmp); +} + +void DeviceConfig::SaveParam(DeviceConfig::DeviceParam param) +{ + std::lock_guard lc(m_lock); + auto tmp = struct2json(param); + savejson(tmp); +} + +json DeviceConfig::struct2json(DeviceConfig::DeviceParam param) +{ + json js; + js[token_code] = param.token; + js[lock_enable] = param.is_lock; + js[gray_correct_enable] = param.gray_param; + js[language] = param.language; + return js; +} + +DeviceConfig::DeviceParam DeviceConfig::json2struct(json js) +{ + bool is_save = false; + DeviceConfig::DeviceParam param; + if(js[lock_enable].is_boolean()) + param.is_lock = js[lock_enable]; + else { + param.is_lock = false; + is_save = true; + } + if(js[token_code].is_string()) + param.token = js[token_code]; + else{ + param.token = "null"; + is_save = true; + } + if(js[gray_correct_enable].is_number_unsigned()) + param.gray_param = js[gray_correct_enable]; + else{ + is_save = true; + param.gray_param = 0; + } + if(js[language].is_number()) + param.language = js[language]; + else{ + is_save = true; + param.language = 0; + } + if(is_save) + savejson(struct2json(param)); + return param; +} + +json DeviceConfig::getdefaultjson() +{ + json m_json; + m_json[lock_enable] = false; + m_json[token_code] = "null"; + m_json[gray_correct_enable] = 0; + m_json[language] = 0; + return m_json; +} + +void DeviceConfig::savejson(json js) +{ + //std::lock_guard lc(m_lock); + std::ofstream o(ParamPath); + o << std::setw(4) << js <> m_json; + i.close(); + return m_json; +} diff --git a/capimage/deviceconfig.h b/capimage/deviceconfig.h new file mode 100644 index 0000000..fce76de --- /dev/null +++ b/capimage/deviceconfig.h @@ -0,0 +1,65 @@ +#pragma once +#include +#include +#include +using json = nlohmann::json; + + +class DeviceConfig +{ +private: + const std::string ParamPath ="/usr/local/huago/deviceconfig.json"; + const std::string lock_enable = "lockenable"; + const std::string token_code = "tokencode"; + const std::string gray_correct_enable = "graycorrectenable"; + const std::string language = "Language"; +public: + struct DeviceParam + { + bool is_lock; + uint32_t gray_param; + uint32_t language; + std::string token; + }; + union Gray_Apply + { + struct + { + uint32_t en_200_gray : 1; + uint32_t en_200_clr : 1; + uint32_t en_300_gray : 1; + uint32_t en_300_clr : 1; + uint32_t en_600_gray : 1; + uint32_t en_600_clr : 1; + uint32_t en_slow_gray : 1; + uint32_t en_slow_clr : 1; + uint32_t en_slow_300_gray : 1; + uint32_t en_slow_300_clr : 1; + uint32_t en_long_Manuscript_200_gray : 1; + uint32_t en_long_Manuscript_200_clr : 1; + uint32_t en_long_Manuscript_300_gray : 1; + uint32_t en_long_Manuscript_300_clr : 1; + uint32_t reserved : 18; + }Param_Setting; + uint32_t value; + }; + + DeviceConfig(/* args */); + ~DeviceConfig(); + DeviceConfig::DeviceParam GetParam(); + void SaveParam(DeviceConfig::DeviceParam param); +private: + json struct2json(DeviceConfig::DeviceParam param); + DeviceConfig::DeviceParam json2struct(json js); + void savejson(json js); + json getjson(); + json getdefaultjson(); + std::mutex m_lock; +}; + +extern DeviceConfig m_static_deviceconfig; + +static DeviceConfig& Get_static_deviceconfig() +{ + return m_static_deviceconfig; +} \ No newline at end of file diff --git a/capimage/gvideo.cpp b/capimage/gvideo.cpp new file mode 100644 index 0000000..1e0b425 --- /dev/null +++ b/capimage/gvideo.cpp @@ -0,0 +1,348 @@ +#include "gvideo.h" +#include +#include /* low-level i/o */ +#include +#include +#include +#include +#include +#include +#include "linux/v4l2-subdev.h" + +#include +#include +#include + +static const std::string loggername = "gVideo"; + +#define LOG_TRACE(...) +#define LOG_ERROR printf +#define LOG_INFO(...) + +using namespace std; +#define CLEAR(x) memset(&(x), 0, sizeof(x)) +#define LOG printf + +int file_size(const char *filename) +{ + struct stat statbuf; + int ret = stat(filename, &statbuf); + int size = -1; + if (ret == 0) + size = statbuf.st_size; + return size; +} + +gVideo::gVideo() + : fd(-1), + buffers(0), + bStart(false), + dev_name("/dev/video3") +{ +} + +gVideo::~gVideo() +{ + close(); +} + +void gVideo::set_buf_count(int count) +{ + v4l_buffer_count = count; +} + +bool gVideo::is_open() +{ + return fd >= 0; +} + +void gVideo::close() +{ + if (is_open()) + { + stop(); + uninit_device(); + close_device(); + } +} + +void gVideo::open(int width, int height) +{ + if (is_open()) + return; + + open_device(); + if (is_open()) + { + // init_device(); + set_size(width, height); + start(); + } +} + +void gVideo::start() +{ + std::lock_guard lck(m_lock); + if (bStart) + return; + + start_capturing(); + bStart = true; +} + +void gVideo::stop() +{ + std::lock_guard lck(m_lock); + if (bStart) + { + stop_capturing(); + bStart = false; + } +} + +void gVideo::grab(int color, bool bcrrect, int timeout, int flatpara) +{ +} + +bool gVideo::hasframe() +{ + return wait(0); +} + +bool gVideo::wait(int msTimeout) +{ + pollfd pfd; + pfd.fd = this->fd; + pfd.events = POLLIN | POLLRDNORM; + + if (poll(&pfd, 1, msTimeout) > 0) + return pfd.revents; + + return false; +} + +void *gVideo::read_frame(int timeout) +{ + if (!wait(timeout)) + { + LOG_TRACE("read frame time out"); + return 0; + } + v4l2_buffer buf; + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + if (-1 == ioctl(fd, VIDIOC_DQBUF, &buf)) + { + LOG_ERROR("VIDIOC_DQBUF error!!! index :%d\n", buf.index); + return 0; + } + if (-1 == ioctl(fd, VIDIOC_QBUF, &buf)) + { + LOG_ERROR("VIDIOC_QBUF error!!! index :%d\n", buf.index); + return 0; + } + return buffers[buf.index].start; +} + +void gVideo::set_size(int width, int height) +{ + if (!buffers.empty()) + uninit_device(); + + v4l_width = width; + v4l_height = height; + // v4l_buffer_count = (10*1024*1024) / (v4l_width*v4l_height*3); + // v4l_buffer_count = std::max(3, std::min(v4l_buffer_count, 40)); /* to-do */ + printf("v4l buffer count %d\n", v4l_buffer_count); + init_device(); +} + +void gVideo::stop_capturing(void) +{ + enum v4l2_buf_type type; + + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (-1 == ioctl(fd, VIDIOC_STREAMOFF, &type)) + LOG_ERROR("streamo off"); +} + +unsigned int querybuf_length; +void gVideo::start_capturing(void) +{ + enum v4l2_buf_type type; + LOG_INFO("start_capturing::querybuf_length = %d.\n", querybuf_length); + for (int i = 0; i < n_buffers; ++i) + { + struct v4l2_buffer buf; + CLEAR(buf); + buf.index = i; + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + + if (-1 == ioctl(fd, VIDIOC_QBUF, &buf)) + LOG_ERROR("VIDIOC_QBUF Error %d", i); + else + LOG_INFO("VIDIOC_QBUF %d\n", i); + } + + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (-1 == ioctl(fd, VIDIOC_STREAMON, &type)) + LOG_ERROR("VIDIOC_STREAMON"); +} + +void gVideo::uninit_device(void) +{ + if (!buffers.empty()) + { + for (int i = 0; i < buffers.size(); ++i) + if (-1 == munmap(buffers[i].start, buffers[i].length)) + LOG_ERROR("munmap %d error\n", i); + + struct v4l2_requestbuffers req; + CLEAR(req); + req.count = 0; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + req.memory = V4L2_MEMORY_MMAP; + + if (-1 == ioctl(fd, VIDIOC_REQBUFS, &req)) + LOG_ERROR("uinit_device VIDIOC_REQBUFS fail\n"); + + buffers.clear(); + } +} + +void gVideo::init_mmap(void) +{ + struct v4l2_requestbuffers req; + int ret; + unsigned int length; + unsigned int offset; + + CLEAR(req); + req.count = v4l_buffer_count; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + req.memory = V4L2_MEMORY_MMAP; + LOG_INFO("set v4l_buffer_count = %d\n", req.count); + LOG_INFO("set v4l_buffer_type = %d\n", req.type); + LOG_INFO("set v4l_buffer_memory = %d\n", req.memory); + + ret = ioctl(fd, VIDIOC_REQBUFS, &req); + if (ret < 0) + { + LOG_ERROR("Unable to request buffers: %s (%d).\n", strerror(errno), errno); + } + else + { + LOG_INFO("%s VIDIOC_REQBUFS sucess\n", dev_name.c_str()); + } + LOG_INFO("%u buffers requested.\n", req.count); + + buffers.resize(req.count); + if (buffers.empty()) + LOG_ERROR("Out of memory\n"); + + // 7.VIDIOC_QUERYBUF + for (n_buffers = 0; n_buffers < req.count; ++n_buffers) + { + const char *ts_type, *ts_source; + struct v4l2_buffer buf; + CLEAR(buf); + buf.index = n_buffers; + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + ret = ioctl(fd, VIDIOC_QUERYBUF, &buf); + if (ret < 0) + LOG_ERROR("Unable to query buffer %u: %s (%d).\n", n_buffers, strerror(errno), errno); + else + LOG_INFO("index %d VIDIOC_QUERYBUF sucess.\n", n_buffers); + // mmap + unsigned int length; + unsigned int offset; + length = buf.length; + offset = buf.m.offset; + LOG_INFO("Buffer %u length = %d.\n", n_buffers, length); + LOG_INFO("Buffer %u offset = %d.\n", n_buffers, offset); + + buffers[n_buffers].length = length; + buffers[n_buffers].start = + mmap(NULL /* start anywhere */, + length, + PROT_READ | PROT_WRITE /* required */, + MAP_SHARED /* recommended */, + fd, offset); + if (buffers[n_buffers].start == MAP_FAILED) + LOG_ERROR("Unable to map buffer %u: %s (%d)\n", n_buffers, strerror(errno), errno); + else + LOG_INFO("Buffer %u mapped at address %p.\n", n_buffers, buffers[n_buffers].start); + } +} + +void printCamInfo(int fd) +{ // 获取摄像头所支持的分辨率 + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + struct v4l2_fmtdesc fmt_1; + struct v4l2_frmsizeenum frmsize; + struct v4l2_frmivalenum frmival; + fmt_1.index = 0; + fmt_1.type = type; + while (ioctl(fd, VIDIOC_ENUM_FMT, &fmt_1) >= 0) + { + frmsize.pixel_format = fmt_1.pixelformat; + frmsize.index = 0; + while (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) >= 0) + { + // if(frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) + // LOG_INFO("line:%d %dx%d", __LINE__, frmsize.discrete.width, frmsize.discrete.height); + // else if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) + // LOG_INFO("line:%d %dx%d", __LINE__, frmsize.discrete.width, frmsize.discrete.height); + frmsize.index++; + } + fmt_1.index++; + } +} + +void gVideo::init_device(void) +{ + struct v4l2_capability cap; + struct v4l2_format fmt; + printCamInfo(fd); + if (-1 == ioctl(fd, VIDIOC_QUERYCAP, &cap)) + { + if (EINVAL == errno) + LOG_ERROR("%s is no V4L2 device", dev_name.c_str()); + else + LOG_ERROR("VIDIOC_QUERYCAP"); + } + + if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) + LOG_ERROR("%s is no video capture device", dev_name.c_str()); + + if (!(cap.capabilities & V4L2_CAP_STREAMING)) + LOG_ERROR("%s does not support streaming i/o", dev_name.c_str()); + + CLEAR(fmt); + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fmt.fmt.pix.width = v4l_width; + fmt.fmt.pix.height = v4l_height; + // LOG_TRACE("v4l2 init_device width:%d, height:%d\n", fmt.fmt.pix.width, fmt.fmt.pix.height); + fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24; + fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; + + if (-1 == ioctl(fd, VIDIOC_S_FMT, &fmt)) + LOG_ERROR("VIDIOC_S_FMT error"); + init_mmap(); +} + +void gVideo::close_device(void) +{ + if (-1 == ::close(fd)) + LOG_ERROR("close"); + + fd = -1; +} + +void gVideo::open_device(void) +{ + if ((fd = ::open(dev_name.c_str(), O_RDWR /* required */ /*| O_NONBLOCK*/, 0)) == -1) + LOG_ERROR("Cannot open %s", dev_name.c_str()); +} diff --git a/capimage/gvideo.h b/capimage/gvideo.h new file mode 100644 index 0000000..dc57f8b --- /dev/null +++ b/capimage/gvideo.h @@ -0,0 +1,49 @@ +#pragma once +#include +#include +#include + +class gVideo +{ +public: + gVideo(); + virtual ~gVideo(); + + bool is_open(); + void close(); + void open(int width, int height); + void start(); + void stop(); + void grab(int color, bool bcrrect = false, int timeout = 1000, int flatpara = 0); + bool hasframe(); + virtual void *read_frame(int timeout); + void set_size(int width, int height); + void set_buf_count(int count); + +protected: + bool wait(int msTimeout); + + virtual void stop_capturing(void); + virtual void start_capturing(void); + virtual void uninit_device(void); + virtual void init_mmap(void); + virtual void init_device(void); + void close_device(void); + void open_device(void); + + struct buffer + { + void *start; + size_t length; + }; + + int v4l_buffer_count = 3; + int v4l_width = 3100; + int v4l_height = 3100; + std::string dev_name; + int fd; + std::vector buffers; + unsigned int n_buffers; + std::mutex m_lock; + volatile bool bStart; +}; diff --git a/capimage/gvideoisp1.cpp b/capimage/gvideoisp1.cpp new file mode 100644 index 0000000..b9e3e70 --- /dev/null +++ b/capimage/gvideoisp1.cpp @@ -0,0 +1,918 @@ +#include "gvideoisp1.h" +#include /* low-level i/o */ +#include +#include +#include +#include +#include "linux/videodev2.h" +#include "linux/v4l2-subdev.h" +#include +#include "string.h" +#include +#include + +#define LOG_TRACE(...) +#define LOG_ERROR printf +#define LOG_INFO(...) + +static const std::string loggername = "GVideoISP1"; + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#define CLEAR(x) memset(&(x), 0, sizeof(x)) + +#define V4L2_BUF_TYPE_META_OUTPUT 14 +#define V4L2_CAP_META_OUTPUT 0x08000000 /* Is a metadata output device */ + +static struct +{ + enum v4l2_buf_type type; + bool supported; + const char *name; + const char *string; +} buf_types[] = { + { + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, + 1, + "Video capture mplanes", + "capture-mplane", + }, + { + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + 1, + "Video output", + "output-mplane", + }, + { + V4L2_BUF_TYPE_VIDEO_CAPTURE, + 1, + "Video capture", + "capture", + }, + { + V4L2_BUF_TYPE_VIDEO_OUTPUT, + 1, + "Video output mplanes", + "output", + }, + {V4L2_BUF_TYPE_VIDEO_OVERLAY, 0, "Video overlay", "overlay"}, + //{ V4L2_BUF_TYPE_META_CAPTURE, 1, "Meta-data capture", "meta-capture", }//, +}; + +static struct v4l2_format_info +{ + const char *name; + unsigned int fourcc; + unsigned char n_planes; +} pixel_formats[] = { + {"RGB332", V4L2_PIX_FMT_RGB332, 1}, + {"RGB444", V4L2_PIX_FMT_RGB444, 1}, + {"ARGB444", V4L2_PIX_FMT_ARGB444, 1}, + {"XRGB444", V4L2_PIX_FMT_XRGB444, 1}, + {"RGB555", V4L2_PIX_FMT_RGB555, 1}, + {"ARGB555", V4L2_PIX_FMT_ARGB555, 1}, + {"XRGB555", V4L2_PIX_FMT_XRGB555, 1}, + {"RGB565", V4L2_PIX_FMT_RGB565, 1}, + {"RGB555X", V4L2_PIX_FMT_RGB555X, 1}, + {"RGB565X", V4L2_PIX_FMT_RGB565X, 1}, + {"BGR666", V4L2_PIX_FMT_BGR666, 1}, + {"BGR24", V4L2_PIX_FMT_BGR24, 1}, + {"RGB24", V4L2_PIX_FMT_RGB24, 1}, + {"BGR32", V4L2_PIX_FMT_BGR32, 1}, + {"ABGR32", V4L2_PIX_FMT_ABGR32, 1}, + {"XBGR32", V4L2_PIX_FMT_XBGR32, 1}, + {"RGB32", V4L2_PIX_FMT_RGB32, 1}, + {"ARGB32", V4L2_PIX_FMT_ARGB32, 1}, + {"XRGB32", V4L2_PIX_FMT_XRGB32, 1}, + //{ "HSV24", V4L2_PIX_FMT_HSV24, 1 }, + //{ "HSV32", V4L2_PIX_FMT_HSV32, 1 }, + {"Y8", V4L2_PIX_FMT_GREY, 1}, + {"Y10", V4L2_PIX_FMT_Y10, 1}, + {"Y12", V4L2_PIX_FMT_Y12, 1}, + {"Y16", V4L2_PIX_FMT_Y16, 1}, + {"UYVY", V4L2_PIX_FMT_UYVY, 1}, + {"VYUY", V4L2_PIX_FMT_VYUY, 1}, + {"YUYV", V4L2_PIX_FMT_YUYV, 1}, + {"YVYU", V4L2_PIX_FMT_YVYU, 1}, + {"NV12", V4L2_PIX_FMT_NV12, 1}, + {"NV12M", V4L2_PIX_FMT_NV12M, 2}, + {"NV21", V4L2_PIX_FMT_NV21, 1}, + {"NV21M", V4L2_PIX_FMT_NV21M, 2}, + {"NV16", V4L2_PIX_FMT_NV16, 1}, + {"NV16M", V4L2_PIX_FMT_NV16M, 2}, + {"NV61", V4L2_PIX_FMT_NV61, 1}, + {"NV61M", V4L2_PIX_FMT_NV61M, 2}, + {"NV24", V4L2_PIX_FMT_NV24, 1}, + {"NV42", V4L2_PIX_FMT_NV42, 1}, + {"YUV420M", V4L2_PIX_FMT_YUV420M, 3}, + {"YUV422M", V4L2_PIX_FMT_YUV422M, 3}, + {"YUV444M", V4L2_PIX_FMT_YUV444M, 3}, + {"YVU420M", V4L2_PIX_FMT_YVU420M, 3}, + {"YVU422M", V4L2_PIX_FMT_YVU422M, 3}, + {"YVU444M", V4L2_PIX_FMT_YVU444M, 3}, + {"SBGGR8", V4L2_PIX_FMT_SBGGR8, 1}, + {"SGBRG8", V4L2_PIX_FMT_SGBRG8, 1}, + {"SGRBG8", V4L2_PIX_FMT_SGRBG8, 1}, + {"SRGGB8", V4L2_PIX_FMT_SRGGB8, 1}, + {"SBGGR10_DPCM8", V4L2_PIX_FMT_SBGGR10DPCM8, 1}, + {"SGBRG10_DPCM8", V4L2_PIX_FMT_SGBRG10DPCM8, 1}, + {"SGRBG10_DPCM8", V4L2_PIX_FMT_SGRBG10DPCM8, 1}, + {"SRGGB10_DPCM8", V4L2_PIX_FMT_SRGGB10DPCM8, 1}, + {"SBGGR10", V4L2_PIX_FMT_SBGGR10, 1}, + {"SGBRG10", V4L2_PIX_FMT_SGBRG10, 1}, + {"SGRBG10", V4L2_PIX_FMT_SGRBG10, 1}, + {"SRGGB10", V4L2_PIX_FMT_SRGGB10, 1}, + {"SBGGR10P", V4L2_PIX_FMT_SBGGR10P, 1}, + {"SGBRG10P", V4L2_PIX_FMT_SGBRG10P, 1}, + {"SGRBG10P", V4L2_PIX_FMT_SGRBG10P, 1}, + {"SRGGB10P", V4L2_PIX_FMT_SRGGB10P, 1}, + {"SBGGR12", V4L2_PIX_FMT_SBGGR12, 1}, + {"SGBRG12", V4L2_PIX_FMT_SGBRG12, 1}, + {"SGRBG12", V4L2_PIX_FMT_SGRBG12, 1}, + {"SRGGB12", V4L2_PIX_FMT_SRGGB12, 1}, + {"DV", V4L2_PIX_FMT_DV, 1}, + {"MJPEG", V4L2_PIX_FMT_MJPEG, 1}, + {"MPEG", V4L2_PIX_FMT_MPEG, 1}, +}; + +static const struct +{ + const char *name; + enum v4l2_field field; +} fields[] = { + {"any", V4L2_FIELD_ANY}, + {"none", V4L2_FIELD_NONE}, + {"top", V4L2_FIELD_TOP}, + {"bottom", V4L2_FIELD_BOTTOM}, + {"interlaced", V4L2_FIELD_INTERLACED}, + {"seq-tb", V4L2_FIELD_SEQ_TB}, + {"seq-bt", V4L2_FIELD_SEQ_BT}, + {"alternate", V4L2_FIELD_ALTERNATE}, + {"interlaced-tb", V4L2_FIELD_INTERLACED_TB}, + {"interlaced-bt", V4L2_FIELD_INTERLACED_BT}, +}; + +GVideoISP1::GVideoISP1() +{ + dev_name = "/dev/video0"; +} + +GVideoISP1::~GVideoISP1() +{ +} + +void *GVideoISP1::read_frame(int timeout) +{ + if (!wait(timeout)) + { + LOG_TRACE("read frame time out!!!\n"); + return 0; + } + struct v4l2_plane planes[VIDEO_MAX_PLANES]; + v4l2_buffer buf; + int ret; + memset(&buf, 0, sizeof buf); + memset(planes, 0, sizeof planes); + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + buf.memory = V4L2_MEMORY_MMAP; + buf.length = VIDEO_MAX_PLANES; + buf.m.planes = planes; + + ret = ioctl(fd, VIDIOC_DQBUF, &buf); + if (ret < 0) + LOG_TRACE("Unable to dequeue buffer: %s (%d).", strerror(errno), errno); + else + LOG_TRACE("VIDIOC_DQBUF sucess"); + + ret = ioctl(fd, VIDIOC_QBUF, &buf); + if (ret < 0) + LOG_ERROR("Unable to requeue buffer: %s (%d).\n", strerror(errno), errno); + else + LOG_TRACE("VIDIOC_QBUF sucess"); + + LOG_TRACE("buf.index = %d,buf.addr = %p\n", buf.index, buffers[buf.index].start); + return buffers[buf.index].start; +} + +void GVideoISP1::start_capturing(void) +{ + unsigned int i; + int ret; + enum v4l2_buf_type type; + + for (i = 0; i < n_buffers; ++i) + { + struct v4l2_buffer buf; + struct v4l2_plane planes[VIDEO_MAX_PLANES]; + CLEAR(buf); + CLEAR(planes); + for (int j = 0; j < VIDEO_MAX_PLANES; j++) + { + planes[j].length = buffers[i].length; + planes[j].m.userptr = (unsigned long)buffers[i].start; + } + buf.index = i; + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + buf.memory = V4L2_MEMORY_MMAP; + buf.m.planes = planes; + buf.length = 1; + + ret = ioctl(fd, VIDIOC_QBUF, &buf); + if (ret < 0) + LOG_ERROR("Unable to queue buffer: %s (%d).", strerror(errno), errno); + else + LOG_TRACE("buf.index = %d VIDIOC_QBUF sucess.", i); + } + + type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + ret = ioctl(fd, VIDIOC_STREAMON, &type); + if (ret < 0) + LOG_ERROR("Unable to %s streaming: %s (%d).", "start", strerror(errno), errno); + else + LOG_TRACE("VIDIOC_STREAMON sucess."); +} + +void GVideoISP1::stop_capturing(void) +{ + enum v4l2_buf_type type; + + type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + if (-1 == ioctl(fd, VIDIOC_STREAMOFF, &type)) + LOG_ERROR("streamo off error\n"); +} + +static void get_ts_flags(uint32_t flags, const char **ts_type, const char **ts_source) +{ + switch (flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) + { + case V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN: + *ts_type = "unk"; + break; + case V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC: + *ts_type = "mono"; + break; + case V4L2_BUF_FLAG_TIMESTAMP_COPY: + *ts_type = "copy"; + break; + default: + *ts_type = "inv"; + } + switch (flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK) + { + case V4L2_BUF_FLAG_TSTAMP_SRC_EOF: + *ts_source = "EoF"; + break; + case V4L2_BUF_FLAG_TSTAMP_SRC_SOE: + *ts_source = "SoE"; + break; + default: + *ts_source = "inv"; + } +} + +static const char *v4l2_buf_type_name(__u32 type) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(buf_types); ++i) + { + if (buf_types[i].type == type) + return buf_types[i].name; + } + + if (type & V4L2_BUF_TYPE_PRIVATE) + return "Private"; + else + return "Unknown"; +} + +static const struct v4l2_format_info *v4l2_format_by_fourcc(unsigned int fourcc) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(pixel_formats); ++i) + { + if (pixel_formats[i].fourcc == fourcc) + return &pixel_formats[i]; + } + + return NULL; +} + +static const char *v4l2_format_name(unsigned int fourcc) +{ + const struct v4l2_format_info *info; + static char name[5]; + unsigned int i; + + info = v4l2_format_by_fourcc(fourcc); + if (info) + return info->name; + + for (i = 0; i < 4; ++i) + { + name[i] = fourcc & 0xff; + fourcc >>= 8; + } + + name[4] = '\0'; + return name; +} + +static void video_enum_frame_intervals(int fd, __u32 pixelformat, + unsigned int width, unsigned int height) +{ + struct v4l2_frmivalenum ival; + unsigned int i; + int ret; + + for (i = 0;; ++i) + { + memset(&ival, 0, sizeof ival); + ival.index = i; + ival.pixel_format = pixelformat; + ival.width = width; + ival.height = height; + ret = ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival); + if (ret < 0) + break; + + if (i != ival.index) + LOG_TRACE("Warning: driver returned wrong ival index " + "%u.\n", + ival.index); + if (pixelformat != ival.pixel_format) + LOG_TRACE("Warning: driver returned wrong ival pixel " + "format %08x.\n", + ival.pixel_format); + if (width != ival.width) + LOG_TRACE("Warning: driver returned wrong ival width " + "%u.\n", + ival.width); + if (height != ival.height) + LOG_TRACE("Warning: driver returned wrong ival height " + "%u.\n", + ival.height); + + if (i != 0) + LOG_TRACE(", "); + + switch (ival.type) + { + case V4L2_FRMIVAL_TYPE_DISCRETE: + LOG_TRACE("%u/%u", ival.discrete.numerator, ival.discrete.denominator); + break; + + case V4L2_FRMIVAL_TYPE_CONTINUOUS: + LOG_TRACE("%u/%u - %u/%u", ival.stepwise.min.numerator, ival.stepwise.min.denominator, ival.stepwise.max.numerator, ival.stepwise.max.denominator); + return; + + case V4L2_FRMIVAL_TYPE_STEPWISE: + LOG_TRACE("%u/%u - %u/%u (by %u/%u)", ival.stepwise.min.numerator, ival.stepwise.min.denominator, ival.stepwise.max.numerator, ival.stepwise.max.denominator, ival.stepwise.step.numerator, ival.stepwise.step.denominator); + return; + + default: + break; + } + } +} + +static void video_enum_frame_sizes(int fd, __u32 pixelformat) +{ + struct v4l2_frmsizeenum frame; + unsigned int i; + int ret; + + for (i = 0;; ++i) + { + memset(&frame, 0, sizeof frame); + frame.index = i; + frame.pixel_format = pixelformat; + ret = ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frame); + if (ret < 0) + break; + + if (i != frame.index) + LOG_TRACE("Warning: driver returned wrong frame index " + "%u.\n", + frame.index); + if (pixelformat != frame.pixel_format) + LOG_TRACE("Warning: driver returned wrong frame pixel " + "format %08x.\n", + frame.pixel_format); + + switch (frame.type) + { + case V4L2_FRMSIZE_TYPE_DISCRETE: + LOG_TRACE("\tFrame size: %ux%u (", frame.discrete.width, frame.discrete.height); + video_enum_frame_intervals(fd, frame.pixel_format, frame.discrete.width, frame.discrete.height); + break; + + case V4L2_FRMSIZE_TYPE_CONTINUOUS: + LOG_TRACE("\tFrame size: %ux%u - %ux%u (", frame.stepwise.min_width, frame.stepwise.min_height, frame.stepwise.max_width, frame.stepwise.max_height); + video_enum_frame_intervals(fd, frame.pixel_format, frame.stepwise.max_width, frame.stepwise.max_height); + break; + + case V4L2_FRMSIZE_TYPE_STEPWISE: + LOG_TRACE("\tFrame size: %ux%u - %ux%u (by %ux%u) (\n", frame.stepwise.min_width, frame.stepwise.min_height, frame.stepwise.max_width, frame.stepwise.max_height, frame.stepwise.step_width, frame.stepwise.step_height); + video_enum_frame_intervals(fd, frame.pixel_format, frame.stepwise.max_width, frame.stepwise.max_height); + break; + + default: + break; + } + } +} + +static void video_enum_formats(int fd, enum v4l2_buf_type type) +{ + struct v4l2_fmtdesc fmt; + unsigned int i; + int ret; + + for (i = 0;; ++i) + { + memset(&fmt, 0, sizeof fmt); + fmt.index = i; + fmt.type = type; + ret = ioctl(fd, VIDIOC_ENUM_FMT, &fmt); + if (ret < 0) + break; + + if (i != fmt.index) + LOG_TRACE("Warning: driver returned wrong format index " + "%u.\n", + fmt.index); + if (type != fmt.type) + LOG_TRACE("Warning: driver returned wrong format type " + "%u.\n", + fmt.type); + + LOG_TRACE("\tFormat %u: %s (%08x)\n", i, v4l2_format_name(fmt.pixelformat), fmt.pixelformat); + LOG_TRACE("\tType: %s (%u)\n", v4l2_buf_type_name(fmt.type), fmt.type); + LOG_TRACE("\tName: %.32s\n", fmt.description); + video_enum_frame_sizes(fd, fmt.pixelformat); + } +} + +static void video_enum_inputs(int fd) +{ + struct v4l2_input input; + unsigned int i; + int ret; + + for (i = 0;; ++i) + { + memset(&input, 0, sizeof input); + input.index = i; + ret = ioctl(fd, VIDIOC_ENUMINPUT, &input); + if (ret < 0) + break; + + if (i != input.index) + LOG_TRACE("Warning: driver returned wrong input index " + "%u.\n", + input.index); + + LOG_TRACE("\tInput %u: %s.\n", i, input.name); + } +} + +static const char *v4l2_field_name(__u32 field) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(fields); ++i) + { + if (fields[i].field == field) + return fields[i].name; + } + + return "unknown"; +} + +static void rkisp_sd_set_crop(const char *ispsd, int fd, int pad, int *w, int *h) +{ + struct v4l2_subdev_selection sel; + int ret; + + memset(&sel, 0, sizeof(sel)); + sel.which = V4L2_SUBDEV_FORMAT_ACTIVE; + sel.pad = pad; + sel.r.width = *w; + sel.r.height = *h; + sel.r.left = 0; + sel.r.top = 0; + sel.target = V4L2_SEL_TGT_CROP; + sel.flags = V4L2_SEL_FLAG_LE; + ret = ioctl(fd, VIDIOC_SUBDEV_S_SELECTION, &sel); + if (ret) + { + LOG_ERROR("subdev %s pad %d crop failed, ret = %d\n", ispsd, sel.pad, ret); + } + else + { + LOG_TRACE("VIDIOC_SUBDEV_S_SELECTION sucess.\n"); + } + + *w = sel.r.width; + *h = sel.r.height; +} + +static void rkisp_video_set_crop(int fd, int x, int y, int w, int h) +{ + struct v4l2_selection sel; + int ret; + memset(&sel, 0, sizeof(sel)); + sel.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + sel.r.width = w; + sel.r.height = h; + sel.r.left = x; + sel.r.top = y; + sel.target = V4L2_SEL_TGT_CROP; + sel.flags = 0; + ret = ioctl(fd, VIDIOC_S_SELECTION, &sel); + if (ret) + { + LOG_ERROR("VIDIOC_S_SELECTION::set output crop(0,0/%dx%d) failed, %s\n", w, h, strerror(errno)); + } + else + { + LOG_TRACE("sVIDIOC_S_SELECTION scuess\n"); + } +} + +void GVideoISP1::init_device(void) +{ + struct v4l2_capability cap; + struct v4l2_format fmt; + + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + struct v4l2_fmtdesc fmt_1; + struct v4l2_frmsizeenum frmsize; + struct v4l2_frmivalenum frmival; + struct v4l2_subdev_format subdev_fmt; + int subdev_fd; + + unsigned int caps; + bool has_video; + bool has_meta; + bool has_capture; + bool has_output; + bool has_mplane; + + int ret; + int i; + //---------------------------set /dev/v4l2-subdev*-------------------------------------// + //----------------------1.v4l2_subdev2 set format----------------------// + subdev_fd = ::open(subdev2_name.c_str(), O_RDWR, 0); + if (-1 == subdev_fd) + { + LOG_ERROR("Cannot open '%s'\n", subdev2_name.c_str()); + } + else + { + LOG_TRACE("open %s success.fd = %d.\n", subdev2_name.c_str(), subdev_fd); + } + memset(&subdev_fmt, 0, sizeof subdev_fmt); + subdev_fmt.pad = 0; + subdev_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; + ret = ioctl(subdev_fd, VIDIOC_SUBDEV_G_FMT, &subdev_fmt); + if (ret < 0) + { + LOG_ERROR("VIDIOC_SUBDEV_G_FMT failed.\n"); + } + else + { + LOG_TRACE("VIDIOC_SUBDEV_G_FMT SUCESS\n"); + } + LOG_TRACE("VIDIOC_SUBDEV_G_FMT:height = %d;width = %d;code = %d.\n", subdev_fmt.format.height, subdev_fmt.format.width, subdev_fmt.format.code); + + subdev_fmt.format.width = v4l_width; + subdev_fmt.format.height = v4l_height; + LOG_TRACE("set height = %d\n", subdev_fmt.format.height); + LOG_TRACE("set width = %d\n", subdev_fmt.format.width); + ret = ioctl(subdev_fd, VIDIOC_SUBDEV_S_FMT, &subdev_fmt); + if (ret < 0) + { + LOG_ERROR("VIDIOC_SUBDEV_S_FMT failed.\n"); + } + else + { + LOG_TRACE("VIDIOC_SUBDEV_S_FMT SUCESS\n"); + } + LOG_TRACE("VIDIOC_SUBDEV_S_FMT:height = %d;width = %d;code = %d.\n", subdev_fmt.format.height, subdev_fmt.format.width, subdev_fmt.format.code); + ::close(subdev_fd); + //-------------------------------------------------------------// + + //----------------------2.v4l2_subdev0 set format::pad0----------------------// + subdev_fd = ::open(subdev0_name.c_str(), O_RDWR, 0); + if (-1 == subdev_fd) + { + LOG_ERROR("Cannot open '%s'\n", subdev0_name.c_str()); + } + else + { + LOG_TRACE("open %s success.fd = %d.\n", subdev0_name.c_str(), subdev_fd); + } + memset(&subdev_fmt, 0, sizeof subdev_fmt); + subdev_fmt.pad = 0; + subdev_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; + ret = ioctl(subdev_fd, VIDIOC_SUBDEV_G_FMT, &subdev_fmt); + if (ret < 0) + { + LOG_ERROR("VIDIOC_SUBDEV_G_FMT failed.\n"); + } + else + { + LOG_TRACE("VIDIOC_SUBDEV_G_FMT SUCESS\n"); + } + LOG_TRACE("VIDIOC_SUBDEV_G_FMT:pad = %d;height = %d;width = %d;code = %d.\n", subdev_fmt.pad, subdev_fmt.format.height, subdev_fmt.format.width, subdev_fmt.format.code); + subdev_fmt.format.width = v4l_width; + subdev_fmt.format.height = v4l_height; + LOG_TRACE("set height = %d;width = %d\n", subdev_fmt.format.height, subdev_fmt.format.width); + + ret = ioctl(subdev_fd, VIDIOC_SUBDEV_S_FMT, &subdev_fmt); + if (ret < 0) + { + LOG_ERROR("VIDIOC_SUBDEV_S_FMT failed.\n"); + } + else + { + LOG_TRACE("VIDIOC_SUBDEV_S_FMT SUCESS\n"); + } + LOG_TRACE("VIDIOC_SUBDEV_S_FMT:pad = %d;height = %d;width = %d;code = %d.\n", subdev_fmt.pad, subdev_fmt.format.height, subdev_fmt.format.width, subdev_fmt.format.code); + rkisp_sd_set_crop(subdev0_name.c_str(), subdev_fd, 0, &v4l_width, &v4l_height); + LOG_TRACE("v4l_set height = %d;width = %d\n", v4l_width, v4l_height); + //----------------------3.v4l2_subdev0 set format::pad2----------------------// + rkisp_sd_set_crop(subdev0_name.c_str(), subdev_fd, 2, &v4l_width, &v4l_height); + LOG_TRACE("v4l_set height = %d;width = %d\n", v4l_width, v4l_height); + memset(&subdev_fmt, 0, sizeof subdev_fmt); + subdev_fmt.pad = 2; + subdev_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; + ret = ioctl(subdev_fd, VIDIOC_SUBDEV_G_FMT, &subdev_fmt); + if (ret < 0) + { + LOG_TRACE("VIDIOC_SUBDEV_G_FMT failed.\n"); + } + else + { + LOG_TRACE("VIDIOC_SUBDEV_G_FMT SUCESS\n"); + } + LOG_TRACE("VIDIOC_SUBDEV_G_FMT:pad = %d\n", subdev_fmt.pad); + LOG_TRACE("VIDIOC_SUBDEV_G_FMT:subdev_fmt.format.height = %d\n", subdev_fmt.format.height); + LOG_TRACE("VIDIOC_SUBDEV_G_FMT:subdev_fmt.format.width = %d\n", subdev_fmt.format.width); + LOG_TRACE("VIDIOC_SUBDEV_G_FMT:subdev_fmt.format.code = %d\n", subdev_fmt.format.code); + subdev_fmt.format.width = v4l_width; + subdev_fmt.format.height = v4l_height; + LOG_TRACE("set height = %d\n", subdev_fmt.format.height); + LOG_TRACE("set width = %d\n", subdev_fmt.format.width); + + ret = ioctl(subdev_fd, VIDIOC_SUBDEV_S_FMT, &subdev_fmt); + if (ret < 0) + { + LOG_TRACE("VIDIOC_SUBDEV_S_FMT failed.\n"); + } + else + { + LOG_TRACE("VIDIOC_SUBDEV_S_FMT SUCESS\n"); + } + LOG_TRACE("VIDIOC_SUBDEV_G_FMT:pad = %d\n", subdev_fmt.pad); + LOG_TRACE("VIDIOC_SUBDEV_S_FMT:subdev_fmt.format.height = %d\n", subdev_fmt.format.height); + LOG_TRACE("VIDIOC_SUBDEV_S_FMT:subdev_fmt.format.width = %d\n", subdev_fmt.format.width); + LOG_TRACE("VIDIOC_SUBDEV_S_FMT:subdev_fmt.format.code = %d\n", subdev_fmt.format.code); + //-------------------------------------------------------------// + + //-------4.set video selection(crop) because ispsd size changed------------------// + rkisp_video_set_crop(fd, 0, 0, v4l_width, v4l_height); + //----------------------1.VIDIOC_QUERYCAP----------------------// + memset(&cap, 0, sizeof cap); + if (-1 == ioctl(fd, VIDIOC_QUERYCAP, &cap)) + + ret = ioctl(fd, VIDIOC_QUERYCAP, &cap); + if (ret < 0) + { + LOG_TRACE("VIDIOC_QUERYCAP failed.\n"); + } + else + { + LOG_TRACE("cap.capabilities = %x .\n", cap.capabilities); + LOG_TRACE("cap.device_caps = %x .\n", cap.device_caps); + } + caps = cap.capabilities & V4L2_CAP_DEVICE_CAPS + ? cap.device_caps + : cap.capabilities; + + has_video = caps & (V4L2_CAP_VIDEO_CAPTURE_MPLANE | + V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_VIDEO_OUTPUT_MPLANE | + V4L2_CAP_VIDEO_OUTPUT); + // has_meta = caps & (V4L2_CAP_META_CAPTURE | + // V4L2_CAP_META_OUTPUT); + // has_capture = caps & (V4L2_CAP_VIDEO_CAPTURE_MPLANE | + // V4L2_CAP_VIDEO_CAPTURE | + // V4L2_CAP_META_CAPTURE); + has_output = caps & (V4L2_CAP_VIDEO_OUTPUT_MPLANE | + V4L2_CAP_VIDEO_OUTPUT | + V4L2_CAP_META_OUTPUT); + has_mplane = caps & (V4L2_CAP_VIDEO_CAPTURE_MPLANE | + V4L2_CAP_VIDEO_OUTPUT_MPLANE); + + LOG_TRACE("Device `%s' on `%s' (driver '%s') supports%s%s%s%s %s mplanes.\n", cap.card, cap.bus_info, cap.driver, has_video ? " video," : "", has_meta ? " meta-data," : "", has_capture ? " capture," : "", has_output ? " output," : "", has_mplane ? "with" : "without"); + + if (!(cap.capabilities & V4L2_CAP_STREAMING)) + { + LOG_ERROR("%s does not support streaming i/o\n", dev_name.c_str()); + } + else + { + LOG_TRACE("%s support streaming i/o\n", dev_name.c_str()); + } + //-------------------------------------------------------------// + + //----------------------2.VIDIOC_ENUM_FMT----------------------// + LOG_TRACE("- Available formats:\n"); + LOG_TRACE("------------------------------------------------------\n"); + LOG_TRACE("fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE = %d\n", V4L2_BUF_TYPE_VIDEO_CAPTURE); + video_enum_formats(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE); + + LOG_TRACE("------------------------------------------------------\n"); + LOG_TRACE("fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE = %d\n", V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + video_enum_formats(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + + LOG_TRACE("------------------------------------------------------\n"); + LOG_TRACE("fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT = %d\n", V4L2_BUF_TYPE_VIDEO_OUTPUT); + video_enum_formats(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT); + + LOG_TRACE("------------------------------------------------------\n"); + LOG_TRACE("fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE = %d\n", V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + video_enum_formats(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); + + LOG_TRACE("------------------------------------------------------\n"); + LOG_TRACE("fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY = %d\n", V4L2_BUF_TYPE_VIDEO_OVERLAY); + video_enum_formats(fd, V4L2_BUF_TYPE_VIDEO_OVERLAY); + + LOG_TRACE("------------------------------------------------------\n"); + // LOG_TRACE( "fmt.type = V4L2_BUF_TYPE_META_CAPTURE = %d\n", V4L2_BUF_TYPE_META_CAPTURE)); + // video_enum_formats(fd, V4L2_BUF_TYPE_META_CAPTURE); + + LOG_TRACE("------------------------------------------------------\n"); + LOG_TRACE("fmt.type = V4L2_BUF_TYPE_META_OUTPUT = %d\n", V4L2_BUF_TYPE_META_OUTPUT); + // video_enum_formats(fd, V4L2_BUF_TYPE_META_OUTPUT); + LOG_TRACE("------------------------------------------------------\n"); + //--------------------------------------------------------------// + + //----------------------3.VIDIOC_ENUMINPUT----------------------// + LOG_TRACE("- Available inputs:\n"); + video_enum_inputs(fd); + //-------------------------------------------------------------// + + //----------------------4.VIDIOC_S_FMT-------------------------// + LOG_TRACE("..........................................................................\n"); + CLEAR(fmt); + // fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + fmt.fmt.pix.width = v4l_width; + fmt.fmt.pix.height = v4l_height; + LOG_TRACE("v4l2 VIDIOC_S_FMT width:%d, height:%d\n", fmt.fmt.pix.width, fmt.fmt.pix.height); + // fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; + fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_RGB24; + fmt.fmt.pix_mp.field = 0; + fmt.fmt.pix_mp.num_planes = 1; + fmt.fmt.pix_mp.flags = 0; + fmt.fmt.pix_mp.plane_fmt[0].bytesperline = 0; + fmt.fmt.pix_mp.plane_fmt[0].sizeimage = 0; + + ret = ioctl(fd, VIDIOC_S_FMT, &fmt); + if (ret < 0) + { + LOG_TRACE("Unable to set format: %s (%d).\n", strerror(errno), errno); + } + else + { + LOG_TRACE("VIDIOC_S_FMT sucess.\n"); + } + + LOG_TRACE("Video format set: %s (%08x) %ux%u field %s, %u planes: \n", v4l2_format_name(fmt.fmt.pix_mp.pixelformat), fmt.fmt.pix_mp.pixelformat, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, v4l2_field_name(fmt.fmt.pix_mp.field), fmt.fmt.pix_mp.num_planes); + + for (i = 0; i < fmt.fmt.pix_mp.num_planes; i++) + { + LOG_TRACE(" * bytesperline %u, buffer size %u\n", fmt.fmt.pix_mp.plane_fmt[i].bytesperline, fmt.fmt.pix_mp.plane_fmt[i].sizeimage); + } + //-------------------------------------------------------------// + + //----------------------5.VIDIOC_G_FMT-------------------------// + memset(&fmt, 0, sizeof fmt); + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + ret = ioctl(fd, VIDIOC_G_FMT, &fmt); + if (ret < 0) + { + LOG_TRACE("Unable to get format: %s (%d).\n", strerror(errno), errno); + } + else + { + LOG_TRACE("VIDIOC_G_FMT sucess."); + } + LOG_TRACE("Video format: %s (%08x) %ux%u field %s, %u planes: \n", v4l2_format_name(fmt.fmt.pix_mp.pixelformat), fmt.fmt.pix_mp.pixelformat, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, v4l2_field_name(fmt.fmt.pix_mp.field), fmt.fmt.pix_mp.num_planes); + for (i = 0; i < fmt.fmt.pix_mp.num_planes; i++) + LOG_TRACE(" * bytesperline %u, buffer size %u\n", fmt.fmt.pix_mp.plane_fmt[i].bytesperline, fmt.fmt.pix_mp.plane_fmt[i].sizeimage); + + ::close(subdev_fd); + //-------------------------------------------------------------// + + // 6.VIDIOC_REQBUFS //7.VIDIOC_QUERYBUF mmmap + init_mmap(); + //-------------------------------------------------------------// +} + +void GVideoISP1::init_mmap(void) +{ + struct v4l2_requestbuffers req; + int ret; + unsigned int length; + unsigned int offset; + + CLEAR(req); + req.count = v4l_buffer_count; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + req.memory = V4L2_MEMORY_MMAP; + LOG_INFO("set v4l_buffer_count = %d\n", req.count); + LOG_INFO("set v4l_buffer_type = %d\n", req.type); + LOG_INFO("set v4l_buffer_memory = %d\n", req.memory); + + ret = ioctl(fd, VIDIOC_REQBUFS, &req); + if (ret < 0) + { + LOG_ERROR("Unable to request buffers: %s (%d).\n", strerror(errno), errno); + } + else + { + LOG_INFO("%s VIDIOC_REQBUFS sucess\n", dev_name.c_str()); + } + LOG_INFO("%u buffers requested.\n", req.count); + + buffers.resize(req.count); + if (buffers.empty()) + LOG_ERROR("Out of memory\n"); + + // 7.VIDIOC_QUERYBUF + for (n_buffers = 0; n_buffers < req.count; ++n_buffers) + { + const char *ts_type, *ts_source; + struct v4l2_buffer buf; + struct v4l2_plane planes[VIDEO_MAX_PLANES]; + CLEAR(buf); + CLEAR(planes); + buf.index = n_buffers; + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + buf.memory = V4L2_MEMORY_MMAP; + buf.length = VIDEO_MAX_PLANES; + buf.m.planes = planes; + + ret = ioctl(fd, VIDIOC_QUERYBUF, &buf); + if (ret < 0) + LOG_ERROR("Unable to query buffer %u: %s (%d).\n", n_buffers, strerror(errno), errno); + else + LOG_INFO("index %d VIDIOC_QUERYBUF sucess.\n", n_buffers); + // mmap + unsigned int length; + unsigned int offset; + length = buf.m.planes[0].length; + offset = buf.m.planes[0].m.mem_offset; + LOG_INFO("Buffer %u length = %d.\n", n_buffers, length); + LOG_INFO("Buffer %u offset = %d.\n", n_buffers, offset); + + buffers[n_buffers].length = length; + buffers[n_buffers].start = + mmap(NULL /* start anywhere */, + length, + PROT_READ | PROT_WRITE /* required */, + MAP_SHARED /* recommended */, + fd, offset); + if (buffers[n_buffers].start == MAP_FAILED) + LOG_ERROR("Unable to map buffer %u: %s (%d)\n", n_buffers, strerror(errno), errno); + else + LOG_INFO("Buffer %u mapped at address %p.\n", n_buffers, buffers[n_buffers].start); + } +} + +void GVideoISP1::uninit_device(void) +{ + if (!buffers.empty()) + { + for (int i = 0; i < buffers.size(); ++i) + if (-1 == munmap(buffers[i].start, buffers[i].length)) + LOG_ERROR("munmap %d error\n", i); + + struct v4l2_requestbuffers req; + CLEAR(req); + req.count = 0; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + req.memory = V4L2_MEMORY_MMAP; + + if (-1 == ioctl(fd, VIDIOC_REQBUFS, &req)) + LOG_ERROR("uinit_device VIDIOC_REQBUFS fail\n"); + + buffers.clear(); + } +} \ No newline at end of file diff --git a/capimage/gvideoisp1.h b/capimage/gvideoisp1.h new file mode 100644 index 0000000..3ca884b --- /dev/null +++ b/capimage/gvideoisp1.h @@ -0,0 +1,24 @@ +#pragma once +#include "gvideo.h" + +class GVideoISP1 : public gVideo +{ +public: + GVideoISP1(); + virtual ~GVideoISP1(); + + virtual void *read_frame(int timeout); + +protected: + virtual void start_capturing(void); + virtual void stop_capturing(void); + virtual void init_device(void); + virtual void init_mmap(void); + virtual void uninit_device(void); + +private: + const std::string subdev0_name = "/dev/v4l-subdev0"; + const std::string subdev1_name = "/dev/v4l-subdev1"; + const std::string subdev2_name = "/dev/v4l-subdev2"; + const std::string subdev3_name = "/dev/v4l-subdev3"; +}; diff --git a/capimage/hgutils.cpp b/capimage/hgutils.cpp new file mode 100644 index 0000000..f3af8b8 --- /dev/null +++ b/capimage/hgutils.cpp @@ -0,0 +1,316 @@ +#include "hgutils.h" +#include +#include +#include +#include +#include "CImageMerge.h" + +using namespace cv; + +cv::Mat extractRepresentRow(const cv::Mat &src) +{ + printf("extractRepresentRow2 enter \n"); + Mat src_temp(src.rows, src.step, CV_8UC1, src.data); + Mat dst(1, src.cols, CV_8UC(src.channels())); + Mat dst_temp(1, src.step, CV_8UC1, dst.data); + + for (int i = 0, length = src.step; i < length; i++) + { + Mat col = src_temp(Rect(i, 0, 1, src_temp.rows)); + float value = 0; + for (int j = 0, rows = col.rows; j < rows; j++) + { + value += (float)col.at(Point(0, j)) / rows; + } + dst_temp.data[i] = (int)value; + } + printf("extractRepresentRow2 exit \n"); + return dst; +} + +cv::Mat flipRightHalf(Mat &src, int papertype) +{ + Mat left = src(cv::Rect(0, 0, src.cols / 2, src.rows)); + Mat right = src(cv::Rect(src.cols / 2, 0, src.cols / 2, src.rows)); + Mat rightFlip; + if (papertype == (int)(PaperSize::G400_A4R)) + { + flip(right, rightFlip, 0); + } + else + { + flip(right, rightFlip, 1); + } + + Mat dst; + hconcat(left, rightFlip, dst); + return dst; +} + +float curve_coffes[2][3][3] = { + {{-6e-5, 0.9928, 0.289}, + {4e-5, 1.0045, -0.0338}, + {3e-5, 1.0028, -0.2547}}, + {{0.00025215105482649316, 0.9162675232424231, 2.2064225897716527}, + {-6.242394612635725e-05, 1.0212590446315797, -0.7470581333124157}, + {-0.0002324551311266845, 1.072239346671703, -1.7099159032971474}}}; + +cv::Mat create_lut(const cv::Mat &black, const cv::Mat &white, bool colormode, CISVendor vendor) +{ + printf("create_lut enter \n"); + int channel = 4896 / 12; // 1632*3 + + const int rows = black.cols / channel; // 408 + const int cols = 256; + printf("LUT White width: %d height :%d channels:%d \n", white.cols, white.rows, white.channels()); + printf("LUT black width: %d height :%d channels:%d \n", black.cols, black.rows, black.channels()); + Mat lut(rows, cols, CV_8UC(channel)); + float *cisCoffoes; + float *coffoes; + if (vendor == CISVendor::DUNNAN_CIS_V0) + cisCoffoes = &curve_coffes[0][0][0]; + else if (vendor == CISVendor::HUALIN_CIS_V0) + cisCoffoes = &curve_coffes[1][0][0]; + else + { + cisCoffoes = &curve_coffes[1][0][0]; + printf("warnning!!! unknown cis type,use hualin CIS cisCoffoes params \n"); + } + + for (size_t i = 0; i < rows; i++) + { + Mat lut_row = lut(cv::Rect(0, i, cols, 1)); + unsigned char *ptr_buffer = lut_row.data; + unsigned char *ptr_black = black.data + i * channel; + unsigned char *ptr_white = white.data + i * channel; + for (size_t j = 0; j < cols; j++) + { + for (size_t k = 0; k < channel; k++) + { + if (ptr_black[k] >= ptr_white[k]) + { + ptr_buffer[j * channel + k] = 0; + printf("ptr_black[%d] >= ptr_white[%d]", k, k); + continue; + } + if (j <= ptr_black[k]) + { + ptr_buffer[j * channel + k] = 0; + } + else if (j >= ptr_white[k]) + { + ptr_buffer[j * channel + k] = 255; + } + else + { + if (white.channels() == 3) + { + float val = 255.0 * (j - ptr_black[k]) / (ptr_white[k] - ptr_black[k]) * 1.2; + // float val = 255.0 * (j - ptr_black[k]) / (ptr_white[k] - ptr_black[k]); + // coffoes = cisCoffoes + 3 * (k % 3); + // val = coffoes[0] * val * val + coffoes[1] * val + coffoes[2]; + if (val > 255) + val = 255; + + if (val < 0) + val = 0; + ptr_buffer[j * channel + k] = (unsigned char)val; + } + else + { + // float val = 255 * (j - ptr_black[k]) / (ptr_white[k] - ptr_black[k]); + float val = 255 * (j - ptr_black[k]) / (ptr_white[k] - ptr_black[k]) * 1.2; + if (val > 255) + val = 255; + + if (val < 0) + val = 0; + ptr_buffer[j * channel + k] = (unsigned char)val; + } + } + } + } + } + printf("create_lut exit \n"); + return lut; +} + +void initLut() +{ + if (access(LUT_GRAY_LUT_PATH, F_OK) != -1) + lutGrayMat_old = cv::imread(LUT_GRAY_LUT_PATH, IMREAD_GRAYSCALE); // 灰色校正值 + if (access(LUT_COLOR_LUT_PATH, F_OK) != -1) + lutColorMat_old = cv::imread(LUT_COLOR_LUT_PATH, IMREAD_GRAYSCALE); // 彩色校正值 +} + +void correctColor(cv::Mat src, bool enhance) +{ + Mat tSrc; + Mat lutMat; + int patch = 0; + int SIZE = src.cols / 12; + // printf("lutMat.empty() src.width::%d SIZE: %d \n", src.cols, SIZE); + + if (src.type() == CV_8UC3) + { + patch = (src.cols * 3) / SIZE; + if (lutColorMat_old.empty()) + { + if (access(LUT_COLOR_LUT_PATH, F_OK) != -1) + { + lutColorMat_old = imread(LUT_COLOR_LUT_PATH, IMREAD_GRAYSCALE); + } + else + { + // printf("error error error %s NOT FOUND \n", LUT_COLOR_LUT_PATH); + return; + } + } + lutMat = lutColorMat_old; + } + else + { + patch = (src.cols) / SIZE; + if (lutGrayMat_old.empty()) + { + if (access(LUT_GRAY_LUT_PATH, F_OK) != -1) + { + lutGrayMat_old = imread(LUT_GRAY_LUT_PATH, IMREAD_GRAYSCALE); + } + else + { + // printf("error error error %s NOT FOUND", LUT_GRAY_LUT_PATH); + return; + } + } + lutMat = lutGrayMat_old; + } + if (lutMat.empty()) + { + return; + } + lutMat = cv::Mat(patch, 256, CV_8UC(SIZE), lutMat.data); + tSrc = cv::Mat(src.rows, patch, CV_8UC(SIZE), src.data); + for (int i = 0; i < patch; i++) + { + LUT(tSrc(cv::Rect(i, 0, 1, src.rows)), lutMat(cv::Rect(0, i, 256, 1)), tSrc(cv::Rect(i, 0, 1, src.rows))); + } +} + +void creatLUTData(int mode, CISVendor vendor) +{ + printf("eneter creatLUTData \n"); + auto colormode = mode == IMAGE_COLOR ? IMREAD_COLOR : IMREAD_GRAYSCALE; + std::string blackPath = mode == IMAGE_COLOR ? LUT_COLOR_BLACK_PATH : LUT_GRAY_BLACK_PATH; + std::string whitePath = mode == IMAGE_COLOR ? LUT_COLOR_WHITE_PATH : LUT_GRAY_WHITE_PATH; + std::string lutsavePath = mode == IMAGE_COLOR ? LUT_COLOR_LUT_PATH : LUT_GRAY_LUT_PATH; + cv::Mat lut; + cv::Mat twMat = cv::imread(whitePath, colormode); + cv::Mat tbMat = cv::imread(blackPath, colormode); + cv::Mat wMat, bMat; + if (mode == IMAGE_COLOR) + { + wMat = cv::Mat(twMat.rows, twMat.cols * 3, CV_8UC1, twMat.data); + bMat = cv::Mat(twMat.rows, twMat.cols * 3, CV_8UC1, tbMat.data); + } + else + { + wMat = twMat; + bMat = tbMat; + } + + lut = create_lut(extractRepresentRow(bMat), extractRepresentRow(wMat), mode, vendor); // add by liuyong: 刘丁维提供 2019/4/12 + Mat dst(bMat.cols * bMat.channels(), 256, CV_8UC1); + memcpy(dst.data, lut.data, bMat.cols * bMat.channels() * 256); + cv::imwrite(lutsavePath, dst); + printf("exit creatLUTData \n"); +} +static int num = 0; +cv::Mat GetMergeMat(void *data, int width, int height, int type) +{ + if (!data) + return cv::Mat(); + + cv::Mat mat; + cv::Mat saveMat; + std::vector ch_mats(3); + int dstwidth, dstheight; + dstwidth = width * 3; + dstheight = height / 3 - 1; + + if (type == CV_8UC3) + { + mat = cv::Mat(height / 3 - 1, width * 9, CV_8UC1, data); + saveMat = cv::Mat(dstheight, dstwidth, CV_8UC3); + } + else + { // gray + saveMat = cv::Mat(height, width * 3, CV_8UC1, data); + } + static int savenum; + if (type == CV_8UC3) + { + for (int i = 0; i < 3; i++) + { // B G R + cv::Mat mattemp = mat(cv::Rect(dstwidth * i, 0, dstwidth, dstheight)); + // ch_mats.push_back(mattemp); + ch_mats[i] = mattemp; + } + swap(ch_mats[1], ch_mats[2]); + cv::merge(ch_mats, saveMat); + } + return saveMat.clone(); +} + +// 3399 旧版本 华凌cis拼接算法 +cv::Mat GetMergeMat(cv::Mat &mat, int width, int height, int type) +{ + if (mat.empty()) + return cv::Mat(); + cv::Mat saveMat; + std::vector ch_mats(3); + int dstwidth, dstheight; + dstwidth = width * 3; + dstheight = height / 3 - 1; + + if (type == CV_8UC3) + { + saveMat = cv::Mat(dstheight, dstwidth, CV_8UC3); + for (int i = 0; i < 3; i++) + { // B G R + cv::Mat mattemp = mat(cv::Rect(dstwidth * i, 0, dstwidth, dstheight)); + // ch_mats.push_back(mattemp); + ch_mats[i] = mattemp; + } + swap(ch_mats[1], ch_mats[2]); + cv::merge(ch_mats, saveMat); + return saveMat; + } + return mat; +} + +// 3399 敦南cis 300 600 拼接算法 +cv::Mat GetMergeMat(int dstwidth, int dstheight, int type, cv::Mat &mat, unsigned int fpgaversion) +{ + return CImageMerge().MergeImage(type == CV_8UC3, mat, dstwidth, dstheight, fpgaversion); +} + +void savescannerinfo(ScannerNativeParam params) +{ + Get_static_jsonconfig().savescannerinfo(params); +} + +ScannerNativeParam getscannerinfo() +{ + return Get_static_jsonconfig().getscannerinfo(); +} + +void savecisparams(HGCorrectConfigs cfgs) +{ + Get_static_jsonconfig().savecisconfig(cfgs); +} + +HGCorrectConfigs getcisparams() +{ + return Get_static_jsonconfig().getcorrectconfigs(); +} \ No newline at end of file diff --git a/capimage/hgutils.h b/capimage/hgutils.h new file mode 100644 index 0000000..cf876a3 --- /dev/null +++ b/capimage/hgutils.h @@ -0,0 +1,33 @@ +#pragma once +#include +#include "jsonconfig.h" +#include "commondef.h" + +static cv::Mat lutGrayMat_old; // 灰色校正值 +static cv::Mat lutColorMat_old; // 彩色校正值 + +cv::Mat extractRepresentRow(const cv::Mat &src); + +cv::Mat create_lut(const cv::Mat &black, const cv::Mat &white, bool colormode, CISVendor vendor); + +cv::Mat flipRightHalf(cv::Mat &src, int papertype); + +void initLut(); + +cv::Mat GetMergeMat(void *data, int width, int height, int type); + +cv::Mat GetMergeMat(cv::Mat &mat, int width, int height, int type); + +cv::Mat GetMergeMat(int dstwidth, int dstheight, int type, cv::Mat &mat, unsigned int fpgaversion = 0x00090001); + +void correctColor(cv::Mat src, bool enhance); + +void creatLUTData(int mode, CISVendor vendor); + +void savescannerinfo(ScannerNativeParam params); + +ScannerNativeParam getscannerinfo(); + +void savecisparams(HGCorrectConfigs cfgs); + +HGCorrectConfigs getcisparams(); diff --git a/capimage/jsonconfig.cpp b/capimage/jsonconfig.cpp new file mode 100644 index 0000000..bc8f989 --- /dev/null +++ b/capimage/jsonconfig.cpp @@ -0,0 +1,442 @@ +#include "jsonconfig.h" +#include +#include +#include +#include +#include +#include + +#define SP_COLOR_DEFAULT 0x438 +#define SP_GRAY_DEFAULT 0xca8 + +jsonconfig m_static_jsonconfig; + +jsonconfig::jsonconfig() +{ + getscannerinfo(); +} + +jsonconfig::~jsonconfig() +{ +} + +void jsonconfig::savecisconfig(HGCorrectConfigs configs) +{ + if (access(JSON_CORRECTDIR_PATH, 0) == -1) + { + auto ret = mkdir(JSON_CORRECTDIR_PATH, 0777); + if (ret != 0) + { + printf("make dir failed .path=%s \n", JSON_CORRECTDIR_PATH); + } + } + json m_json; + m_json[STRCON(STR_COLOR, STR_EXPF)] = configs.color.expF; + m_json[STRCON(STR_COLOR, STR_EXPB)] = configs.color.expB; + m_json[STRCON(STR_COLOR, STR_GAINF)] = configs.color.gainF; + m_json[STRCON(STR_COLOR, STR_GAINB)] = configs.color.gainB; + m_json[STRCON(STR_COLOR, STR_OFFSETF)] = configs.color.offsetsF; + m_json[STRCON(STR_COLOR, STR_OFFSETB)] = configs.color.offsetsB; + if (configs.color.sp <= 0) + { + configs.color.sp = SP_COLOR_DEFAULT; + } + m_json[STRCON(STR_COLOR, STR_SP)] = configs.color.sp; + + m_json[STRCON(STR_CORRECTCOLOR, STR_EXPF)] = configs.colorCorrect.expF; + m_json[STRCON(STR_CORRECTCOLOR, STR_EXPB)] = configs.colorCorrect.expB; + m_json[STRCON(STR_CORRECTCOLOR, STR_GAINF)] = configs.colorCorrect.gainF; + m_json[STRCON(STR_CORRECTCOLOR, STR_GAINB)] = configs.colorCorrect.gainB; + m_json[STRCON(STR_CORRECTCOLOR, STR_OFFSETF)] = configs.colorCorrect.offsetsF; + m_json[STRCON(STR_CORRECTCOLOR, STR_OFFSETB)] = configs.colorCorrect.offsetsB; + if (configs.colorCorrect.sp <= 0) + { + configs.colorCorrect.sp = SP_COLOR_DEFAULT; + } + m_json[STRCON(STR_CORRECTCOLOR, STR_SP)] = configs.colorCorrect.sp; + + m_json[STRCON(STR_GRAY, STR_EXPF)] = configs.gray.expF; + m_json[STRCON(STR_GRAY, STR_EXPB)] = configs.gray.expB; + m_json[STRCON(STR_GRAY, STR_GAINF)] = configs.gray.gainF; + m_json[STRCON(STR_GRAY, STR_GAINB)] = configs.gray.gainB; + m_json[STRCON(STR_GRAY, STR_OFFSETF)] = configs.gray.offsetsF; + m_json[STRCON(STR_GRAY, STR_OFFSETB)] = configs.gray.offsetsB; + if (configs.gray.sp <= 0) + { + configs.gray.sp = SP_GRAY_DEFAULT; + } + m_json[STRCON(STR_GRAY, STR_SP)] = configs.gray.sp; + + m_json[STRCON(STR_CORRECTGRAY, STR_EXPF)] = configs.grayCorrect.expF; + m_json[STRCON(STR_CORRECTGRAY, STR_EXPB)] = configs.grayCorrect.expB; + m_json[STRCON(STR_CORRECTGRAY, STR_GAINF)] = configs.grayCorrect.gainF; + m_json[STRCON(STR_CORRECTGRAY, STR_GAINB)] = configs.grayCorrect.gainB; + m_json[STRCON(STR_CORRECTGRAY, STR_OFFSETF)] = configs.grayCorrect.offsetsF; + m_json[STRCON(STR_CORRECTGRAY, STR_OFFSETB)] = configs.grayCorrect.offsetsB; + if (configs.grayCorrect.sp <= 0) + { + configs.grayCorrect.sp = SP_GRAY_DEFAULT; + } + m_json[STRCON(STR_CORRECTGRAY, STR_SP)] = configs.grayCorrect.sp; + + std::cout << m_json << std::endl; + + std::ofstream o(JSON_CORRECTFILE_PATH); + o << std::setw(4) << m_json << std::endl; + o.close(); +} + +HGCorrectConfigs jsonconfig::getcorrectconfigs() +{ + HGCorrectConfigs cfs; + if (access(JSON_CORRECTDIR_PATH, 0) == -1) + { + auto ret = mkdir(JSON_CORRECTDIR_PATH, 0777); + if (ret != 0) + { + printf("make dir failed .path=%s \n", JSON_CORRECTDIR_PATH); + } + } + + if (access(JSON_CORRECTFILE_PATH, F_OK) != 0) + { + cfs = getdefaultconfigs(); + savecisconfig(cfs); + return cfs; + } + + std::ifstream i(JSON_CORRECTFILE_PATH); + auto pos = i.tellg(); + i.seekg(0, std::ios::end); + // printf("file length =%d ", i.tellg()); + if (i.tellg() <= 2) + { + cfs = getdefaultconfigs(); + savecisconfig(cfs); + return cfs; + } + i.seekg(pos); + json m_json; + i >> m_json; + i.close(); + cfs.colorCorrect.sp = cfs.color.sp = SP_COLOR_DEFAULT; + cfs.grayCorrect.sp = cfs.gray.sp = SP_GRAY_DEFAULT; + std::cout << "GET GET GET GET GET GET" << m_json << std::endl; + m_json[STRCON(STR_COLOR, STR_EXPF)].get_to(cfs.color.expF); + m_json[STRCON(STR_COLOR, STR_EXPB)].get_to(cfs.color.expB); + m_json[STRCON(STR_COLOR, STR_GAINF)].get_to(cfs.color.gainF); + m_json[STRCON(STR_COLOR, STR_GAINB)].get_to(cfs.color.gainB); + m_json[STRCON(STR_COLOR, STR_OFFSETF)].get_to(cfs.color.offsetsF); + m_json[STRCON(STR_COLOR, STR_OFFSETB)].get_to(cfs.color.offsetsB); + m_json[STRCON(STR_COLOR, STR_SP)].get_to(cfs.color.sp); + + m_json[STRCON(STR_CORRECTCOLOR, STR_EXPF)].get_to(cfs.colorCorrect.expF); + m_json[STRCON(STR_CORRECTCOLOR, STR_EXPB)].get_to(cfs.colorCorrect.expB); + m_json[STRCON(STR_CORRECTCOLOR, STR_GAINF)].get_to(cfs.colorCorrect.gainF); + m_json[STRCON(STR_CORRECTCOLOR, STR_GAINB)].get_to(cfs.colorCorrect.gainB); + m_json[STRCON(STR_CORRECTCOLOR, STR_OFFSETF)].get_to(cfs.colorCorrect.offsetsF); + m_json[STRCON(STR_CORRECTCOLOR, STR_OFFSETB)].get_to(cfs.colorCorrect.offsetsB); + m_json[STRCON(STR_CORRECTCOLOR, STR_SP)].get_to(cfs.colorCorrect.sp); + + m_json[STRCON(STR_GRAY, STR_EXPF)].get_to(cfs.gray.expF); + m_json[STRCON(STR_GRAY, STR_EXPB)].get_to(cfs.gray.expB); + m_json[STRCON(STR_GRAY, STR_GAINF)].get_to(cfs.gray.gainF); + m_json[STRCON(STR_GRAY, STR_GAINB)].get_to(cfs.gray.gainB); + m_json[STRCON(STR_GRAY, STR_OFFSETF)].get_to(cfs.gray.offsetsF); + m_json[STRCON(STR_GRAY, STR_OFFSETB)].get_to(cfs.gray.offsetsB); + m_json[STRCON(STR_GRAY, STR_SP)].get_to(cfs.gray.sp); + + m_json[STRCON(STR_CORRECTGRAY, STR_EXPF)].get_to(cfs.grayCorrect.expF); + m_json[STRCON(STR_CORRECTGRAY, STR_EXPB)].get_to(cfs.grayCorrect.expB); + m_json[STRCON(STR_CORRECTGRAY, STR_GAINF)].get_to(cfs.grayCorrect.gainF); + m_json[STRCON(STR_CORRECTGRAY, STR_GAINB)].get_to(cfs.grayCorrect.gainB); + m_json[STRCON(STR_CORRECTGRAY, STR_OFFSETF)].get_to(cfs.grayCorrect.offsetsF); + m_json[STRCON(STR_CORRECTGRAY, STR_OFFSETB)].get_to(cfs.grayCorrect.offsetsB); + m_json[STRCON(STR_CORRECTGRAY, STR_SP)].get_to(cfs.grayCorrect.sp); + return cfs; +} + +HGCorrectConfigs jsonconfig::getdefaultconfigs() +{ + HGCorrectConfigs cfs; + for (int i = 0; i < 3; i++) + { + + int expclorF, expgrayF, expclorB, expgrayB; + switch (i) + { + case 0: // B + expclorF = 1300; // 789 + expclorB = 1350; + expgrayF = 420; + expgrayB = 420; + break; + case 1: // G + expclorF = 1350; + expclorB = 1280; + expgrayF = 420; + expgrayB = 420; + break; + case 2: // R + expclorF = 789; + expclorB = 824; + expgrayF = 420; + expgrayB = 420; + break; + default: + break; + } + cfs.colorCorrect.expB[i] = expclorF; + cfs.colorCorrect.expF[i] = expclorB; + cfs.grayCorrect.expB[i] = expgrayF; + cfs.grayCorrect.expF[i] = expgrayB; + cfs.gray.expB[i] = expgrayB; + cfs.gray.expF[i] = expgrayF; + cfs.color.expF[i] = expclorF; + cfs.color.expB[i] = expclorB; + } + for (int i = 0; i < 6; i++) + { + cfs.colorCorrect.gainB[i] = cfs.colorCorrect.gainF[i] = 120; + cfs.grayCorrect.gainB[i] = cfs.grayCorrect.gainF[i] = 120; + cfs.gray.gainB[i] = cfs.gray.gainF[i] = 120; + cfs.color.gainB[i] = cfs.color.gainF[i] = 120; + cfs.colorCorrect.offsetsB[i] = cfs.colorCorrect.offsetsF[i] = 125; + cfs.grayCorrect.offsetsB[i] = cfs.grayCorrect.offsetsF[i] = 125; + cfs.gray.offsetsB[i] = cfs.gray.offsetsF[i] = 125; + cfs.color.offsetsB[i] = cfs.color.offsetsF[i] = 125; + } + + cfs.colorCorrect.sp = cfs.color.sp = SP_COLOR_DEFAULT; + cfs.grayCorrect.sp = cfs.gray.sp = SP_GRAY_DEFAULT; + return cfs; +} + +void jsonconfig::savescannerinfo(ScannerNativeParam param) +{ + m_mem_param = param; + json m_json; + m_json[S_INFO_DOUNUM] = (param.DoubleFeedTimes); + m_json[S_INFO_FEEDERROR] = (param.FeedErrorTimes); + m_json[S_INFO_HRATIO] = (param.H_ratio); + m_json[S_INFO_JAMNUM] = (param.JamTimes); + m_json[S_INFO_ROLLERNUM] = (param.RollerNum); + m_json[S_INFO_SCANSESSIONCOUNT] = (param.ScanSessionsCount); + m_json[S_INFO_SERIALNUM] = (param.SerialNum); + m_json[S_INFO_TOKEN] = (param.Token); + m_json[S_INFO_TOTALSCANNED] = (param.TotalScanned); + m_json[S_INFO_VRATIO] = (param.V_ratio); + m_json[S_COLOR_SP] = (param.color_sp); + m_json[S_GRAY_SP] = (param.gray_sp); + m_json[S_INFO_SLEEPTIME] = (param.sleeptime); + m_json[S_INFO_CLR_MAXBRT] = (param.clr_maxbright); + m_json[S_INFO_GRAY_MAXBRT] = (param.gray_maxbright); + m_json[S_INFO_SPEEDMODE] = (param.speedmode); + m_json[S_INFO_VID] = (param.Vid); + m_json[S_INFO_PID] = (param.Pid); + m_json[S_INFO_CHUZHI_MOTOR_SPEED_200] = (param.chu_motor_speed_200); + m_json[S_INFO_CHUZHI_MOTOR_SPEED_300] = (param.chu_motor_speed_300); + m_json[S_INFO_CHUZHI_MOTOR_SPEED_600] = (param.chu_motor_speed_600); + std::ofstream o(JSON_SCANNER_INFO_FILE); + o << std::setw(4) << m_json << std::endl; + o.close(); + printf("\n %s speedmode value = %d", JSON_SCANNER_INFO_FILE, param.speedmode); +} + +ScannerNativeParam jsonconfig::getscannerinfo() +{ + std::lock_guard lc(mtx); + + ScannerNativeParam snp; + + if (access(JSON_SCANNER_INFO_DIR, 0) == -1) + { + auto ret = mkdir(JSON_SCANNER_INFO_DIR, 0777); + if (ret != 0) + { + printf("make dir failed .path=%s \n", JSON_SCANNER_INFO_DIR); + } + } + if (access(JSON_SCANNER_INFO_FILE, 0) == -1) + { + printf("\nerror !!! file no exist"); + snp = getdefaultscannerinfo(); + savescannerinfo(snp); + return snp; + } + std::ifstream i(JSON_SCANNER_INFO_FILE); + + auto pos = i.tellg(); + + i.seekg(0, std::ios::end); + + // printf("file length =%d ", i.tellg()); + if (i.tellg() <= 2) + { + printf("\nerror !!! file data error"); + snp = getdefaultscannerinfo(); + savescannerinfo(snp); + return snp; + } + i.seekg(pos); + json m_json; + i >> m_json; + + if (!m_json[S_INFO_DOUNUM].is_null()) + m_json[S_INFO_DOUNUM].get_to(snp.DoubleFeedTimes); + else + snp.DoubleFeedTimes = 0; + + if (!m_json[S_INFO_FEEDERROR].is_null()) + m_json[S_INFO_FEEDERROR].get_to(snp.FeedErrorTimes); + else + snp.FeedErrorTimes = 0; + + if (!m_json[S_INFO_HRATIO].is_null()) + m_json[S_INFO_HRATIO].get_to(snp.H_ratio); + else + snp.H_ratio = 1065353216; + + if (!m_json[S_INFO_JAMNUM].is_null()) + m_json[S_INFO_JAMNUM].get_to(snp.JamTimes); + else + snp.JamTimes = 0; + + if (!m_json[S_INFO_ROLLERNUM].is_null()) + m_json[S_INFO_ROLLERNUM].get_to(snp.RollerNum); + else + snp.RollerNum = 0; + if (!m_json[S_INFO_SCANSESSIONCOUNT].is_null()) + m_json[S_INFO_SCANSESSIONCOUNT].get_to(snp.ScanSessionsCount); + else + snp.ScanSessionsCount = 0; + + if (!m_json[S_INFO_SERIALNUM].is_null()) + m_json[S_INFO_SERIALNUM].get_to(snp.SerialNum); + else + snp.SerialNum = SERIALNUM; + + if (!m_json[S_INFO_TOKEN].is_null()) + m_json[S_INFO_TOKEN].get_to(snp.Token); + else + snp.Token = "abcdefghijklmnopqrstuvwxyz012345"; + + if (!m_json[S_INFO_TOTALSCANNED].is_null()) + m_json[S_INFO_TOTALSCANNED].get_to(snp.TotalScanned); + else + snp.TotalScanned = 0; + + if (!m_json[S_INFO_VRATIO].is_null()) + m_json[S_INFO_VRATIO].get_to(snp.V_ratio); + else + snp.V_ratio = 1065353216; + + if (!m_json[S_COLOR_SP].is_null()) + m_json[S_COLOR_SP].get_to(snp.color_sp); + else +#ifdef G200 + snp.color_sp = 0x27C; +#else + snp.color_sp = 0x2B6; +#endif + + if (!m_json[S_GRAY_SP].is_null()) + m_json[S_GRAY_SP].get_to(snp.gray_sp); + else +#ifdef G200 + snp.gray_sp = 0x775; +#else + snp.gray_sp = 0x822; +#endif + + if (!m_json[S_INFO_SLEEPTIME].is_null()) + m_json[S_INFO_SLEEPTIME].get_to(snp.sleeptime); + else + snp.sleeptime = 10800; + + if (!m_json[S_INFO_CLR_MAXBRT].is_null()) + m_json[S_INFO_CLR_MAXBRT].get_to(snp.clr_maxbright); + else + snp.clr_maxbright = 200; + + if (!m_json[S_INFO_GRAY_MAXBRT].is_null()) + m_json[S_INFO_GRAY_MAXBRT].get_to(snp.gray_maxbright); + else + snp.gray_maxbright = 200; + + if (!m_json[S_INFO_SPEEDMODE].is_null()) + m_json[S_INFO_SPEEDMODE].get_to(snp.speedmode), printf("\n %s Get speedmode value = %d", JSON_SCANNER_INFO_FILE, snp.speedmode); + else + snp.speedmode = 0, printf("\n %s Get speedmode failed ", JSON_SCANNER_INFO_FILE); + + if (!m_json[S_INFO_PID].is_null()) + m_json[S_INFO_PID].get_to(snp.Pid); + else + { +#ifdef G100 + snp.Pid = 0x139; +#else + snp.Pid = 0x239; +#endif + } + + if (!m_json[S_INFO_VID].is_null()) + m_json[S_INFO_VID].get_to(snp.Vid); + else + snp.Vid = 0x3072; + + if (!m_json[S_INFO_CHUZHI_MOTOR_SPEED_200].is_null()) + m_json[S_INFO_CHUZHI_MOTOR_SPEED_200].get_to(snp.chu_motor_speed_200); + else + snp.chu_motor_speed_200 = 300; + + if (!m_json[S_INFO_CHUZHI_MOTOR_SPEED_300].is_null()) + m_json[S_INFO_CHUZHI_MOTOR_SPEED_300].get_to(snp.chu_motor_speed_300); + else + snp.chu_motor_speed_300 = 200; + + if (!m_json[S_INFO_CHUZHI_MOTOR_SPEED_600].is_null()) + m_json[S_INFO_CHUZHI_MOTOR_SPEED_600].get_to(snp.chu_motor_speed_600); + else + snp.chu_motor_speed_600 = 100; + + // printf("vid = %d pid =%d \n",snp.Vid,snp.Pid ); + m_mem_param = snp; + return snp; +} + +ScannerNativeParam jsonconfig::getdefaultscannerinfo() +{ + ScannerNativeParam param; + param.DoubleFeedTimes = 0; + param.FeedErrorTimes = 0; + param.H_ratio = 1065353216; + param.V_ratio = 1065353216; + param.JamTimes = 0; + param.RollerNum = param.TotalScanned = 0; + param.Token = "abcdefghijklmnopqrstuvwxyz012345"; // default 32byte length + param.SerialNum = SERIALNUM; +#ifdef G200 + param.gray_sp = 0x775; // G200 140 ppm 0x27c 0x775 G100 100 ppm 0x2B6 0x822 + param.color_sp = 0x27C; + param.speedmode = 100; + param.Pid = 0x0239; +#else + param.gray_sp = 0x822; // G200 140 ppm 0x27c 0x781 G100 100 ppm 0x2B6 0x822 + param.color_sp = 0x2B6; + param.speedmode = 70; + param.Pid = 0x0139; +#endif + param.Vid = 0x3072; + param.sleeptime = 10800; + param.clr_maxbright = param.gray_maxbright = 200; + param.chu_motor_speed_200 = 300; + param.chu_motor_speed_300 = 200; + param.chu_motor_speed_600 = 100; + return param; +} + +ScannerNativeParam jsonconfig::getmemparam() +{ + return m_mem_param; +} \ No newline at end of file diff --git a/capimage/jsonconfig.h b/capimage/jsonconfig.h new file mode 100644 index 0000000..1e55f9d --- /dev/null +++ b/capimage/jsonconfig.h @@ -0,0 +1,31 @@ +#pragma once +#include "json.hpp" +#include "commondef.h" +#include +using json = nlohmann::json; + +class jsonconfig +{ +private: + /* data */ + ScannerNativeParam m_mem_param; +public: + jsonconfig(/* args */); + ~jsonconfig(); + + void savecisconfig(HGCorrectConfigs configs); + void savescannerinfo(ScannerNativeParam scannerinfo); + HGCorrectConfigs getcorrectconfigs(); + ScannerNativeParam getscannerinfo(); + HGCorrectConfigs getdefaultconfigs(); + ScannerNativeParam getdefaultscannerinfo(); + ScannerNativeParam getmemparam(); + std::mutex mtx; +}; + +extern jsonconfig m_static_jsonconfig; + +static jsonconfig& Get_static_jsonconfig() +{ + return m_static_jsonconfig; +} \ No newline at end of file diff --git a/capimage/scannersysinfo.h b/capimage/scannersysinfo.h new file mode 100644 index 0000000..4b71a9d --- /dev/null +++ b/capimage/scannersysinfo.h @@ -0,0 +1,69 @@ +#pragma once +#include +#include "commondef.h" +enum class SysType +{ + Sys_Linux_Debian = 1, + Sys_Linux_Uos, + Sys_Android +}; + +enum class Scanner_Serial +{ + S_G100 = 1, + S_G200, + S_G300, + S_G300_UV, + S_G400 +}; + +enum class SCPU +{ + CPU_3288 = 1, + CPU_3399 +}; + +enum class SMBType +{ + MB_DRV_UNKNOWUN, + MB_DRV_8825, + MB_DRV_TMC216, + MB_DRV_ANLU, + MB_DRV_LATIACE +}; + +enum class HGCISType +{ + CIS_UNKOWNUN, + CIS_HUALIN_MONO_V0, + CIS_DUNNAN_MONO_V0, + CIS_DUNNAN_COLOR_V0 +}; + +enum class ScreenType +{ + ST_None = 1, + ST_SmallLcd, + ST_BigLcd, + ST_8Inch, + ST_7Inch +}; + +typedef struct Scanner_SysInfo +{ + SCPU CPU; // 3288 3399 + SysType Systype; + ScreenType Screentype; + unsigned int MtBoardVersion; + SMBType MtType; + unsigned int FPGAVersion; + HGCISType Cistype; + unsigned int ResSup[3]; // 分辨率支持 + unsigned int MemTotal; // 单位 MB + unsigned int DiskTotal; // 单位 MB + unsigned int DiskUsed; // 已使用空间 + std::string KernelVersion; + unsigned int Have_EthernPort; + std::string ServiceVersion; + float UsbProtocol; // 1.0 2.0 2.xx +} ScannerSysInfo; diff --git a/changelog.txt b/changelog.txt new file mode 100644 index 0000000..e1900c2 --- /dev/null +++ b/changelog.txt @@ -0,0 +1,165 @@ +2021年7月12日 + 固件版本号:G139210712 + 第一版程序 + 1.解决配置fpga 增益异常问题; + 2.增加校正功能; + 3.基本打通基础功能流程; + +2021年7月15日 + 固件版本号:G139210715 + 修改说明: + 1.彩色灰度分两步校正,避免校正时颜色模式切换导致的采图异常; + 2.修复灰度校正过程中,明场背面亮度无法提高问题; + 3.修复扫描报双张、卡纸,图像上传问题; + 4.修复报双张、卡纸,未触发PC通知问题; + 5.修复扫描结束报开盖异常,双张报开盖问题; + 6.解决usb jpeg buffer传输一位图,解压后图像引入噪点问题; + +2021年7月19日 + 固件版本号:G139210719 + 修改说明: + 1.解决传输一位图卡死问题 + 2.双张、卡纸等异常交由上层twain处理删除图像数据 + 3.屏蔽notify中的消息发送的等待清除代码 + 4.添加扫描结束stopscan信号上传 + +2021年7月21日 + 固件版本号:G139210720 + 1.修复自动校正offset计算时,IC控制的图像条块宽度与计算宽度不一致问题; + 2.增加fpga固件自动升级功能; + 3.在获取增加images数据长度时增加images队列数量判断,修复跳过空白页时传入空mat崩溃问题 + 4.屏蔽int 端点 notify 接口while循环导致消息丢失问题; + +2021年9月30日 + 固件版本号:G1392A0930 + 1.修复扫描单张卡纸出图问题 + 2.增加G100 110ppm速度模式 + 3.添加获取ip地址,以及fpga版本功能 + +2021年11月17日 + 固件版本号:G1393A1116 + 1.添加折角和尺寸检测到扫描流程 + 2.每次扫描完成后reset fpga + 3.vid pid可设置 + 4.修改按键休眠不生效问题 + 5.修复600 dpi首张图像丢失问题 + 6.添加数字增益 1.2 + 7.调整usb短时间内拔插导致usbbulk端点阻塞问题 + +2022年3月30日 + 固件版本号:G1393B0330 + 1.优化扫描流程,pick_paper放在readframe之前 + 2.添加reload fpga + 3.更新1.3.12裁切纠偏算法 + 4.修复连续扫描产生的系列问题 + 5.添加带孔扫描 + 6.修复连续扫描下按键操作问题,增加按键停止连续扫描功能 + 7.休眠休眠连续扫描未pc不能关闭问题 + 8.G200 明场最大值调整为200,校正数据上下各裁切50行再进行校正 + 9.修复液晶问题 + 10.调整usb兼容id为600 + +2022年7月30日 + 固件版本号:G1393B0730 + 1.添加休眠唤醒接口,添加分纸强度获取设置接口 + 2.添加自动调节分纸强度功能 + 3.更新除穿孔,跳过空白页算法 + + +2022年8月13日 + 1. 电机板FPGA增加托盘档位功能,软件支持设置托盘位置 + +2022年9月17日 + 1. 针对通达海调整除穿孔以及跳过空白页算法,除穿孔分为指定上下左右填充避免误填; + +2022年9月27日~2022年10月9日 + 1. 适配3288固件,调整拼接算法,临时解决重影问题,开放自适应幅面 + 2. 配合系统备份功能,USB增加系统备份功能通信指令 + +2022年10月19日 + 1. 添加对折模式选择对折方向功能 + 2. 新增设备锁定功能 + 3. 增加清理纸道协议 + 4. 增加0x90002fpga兼容,更新图像拼接算法 + 5. 添加vsp设置功能,默认为2,范围1-20 + 6. 支持不同dpi与颜色模式单独校正 + 7. 添加色偏算法 + 8. 畸变参数由单一参数改为不同dpi不同畸变参数 -22.12.07 + 9. 去掉pickpaper之前的有无纸判断 -22.12.14 + 10.调整休眠唤醒获取接口,由直接读取文件改为获取标志位 -23.01.03 + 11.更新除穿孔算法到1.92版本 -23.01.09 + 12.调整校正,减少校正时间 -23.01.11 + 13.开放填黑框自适应颜色填充 -23.02.21 + 14.除背景色二值化阈值调整为50 (100 - 50) -23.02.21 + +2023年3月3日 + 固件版本号:GX393C0303 + 1.修复历史张数清零协议错误问题 -23.03.03 + 2.添加执行shell命令协议 -23.03.03 + 3.添加按键5秒关机动作 -23.03.03 + 4.更新除色,除摩尔纹算法 -23.03.11 + 5.适配9000afpga,vsp调整为75,80 -23.03.11 + 6.更新色偏矫正算法 + 7.调整9000a版本vsp为80,120 -23.04.15 + 8.脱胶版本 默认开启亮度锐化 -23.04.18 + 9.除色散算法更新到v2.0版本 -23.04.18 + 10.调整脱焦 锐化 参数 -23.04.25 + 11.增加慢速除摩尔纹配置,开启后200 300 dpi,扫描应用110ppm 300dpi sp、80ppm 300dpi电机速度,再缩放至指定幅面 -23.05.10 + 12.休眠唤醒调整,长按3秒关机,短按0.2s唤醒,去掉按键休眠功能 -23.05.13 + 13.增加9000b版本fpga兼容 -23.05.13 + 14.去掉MonoCapturer构造函数内的fpga—reset和reset-adc -23.05.15 + 15.更新色偏矫正算法到2.0版本,调整9000b版本拼接算法 -23.05.15 + 16.更新穿孔算法到1.93版本 -23.05.16 + 17.修复不扫描不休眠问题 -23.05.18 + 18.图像处理线程由6调整为4,除色散算法回退到1.30版本 -23.05.18 + 19.调整休眠回调异常崩溃问题 -23.05.18 + 20.调整自动分纸强度不生效问题 -23.05.25 + 21.自适应幅面最小高度调整为A4横向 --23.05.31 + 22.调整校正使用暗场最小值大于0 均值小于25的方式校正,校正前将offset全部重新设置成默认值 --23.06.05 + +2023年6月16日 + 固件版本号:GX393C0518 + 1.调整加入灰阶校正方案,新加校正复原功能 --23.06.16 + 2.调整算法,默认使用红色增强plus --23.06.16 + 3.调整除网文算法使用CImageApplyFilter,屏蔽除摩尔纹算法 --23.06.17 + 4.修复休眠时崩溃问题,调整编译器优化选项 --23.07.11 + 5.调整文件传输usb协议,限制固定范围内可读写 --23.07.11 + 6.增加一件备份还原huago文件夹协议 --23.07.11 + 7.增加G100 100ppm速度兼容,设置速度时默认重新设置摩尔纹模式sp --23.07.13 + 8.修改开盖与无纸显示优先级 --23.07.13 + 9.更新除色与颜色增强算法 --23.08.01 + 10.增加灰阶校正配置使能功能,initlut调整 --23.08.29 + 11.调整自定义裁切执行顺序,放在缩放之后 --23.08.29 + 12.添加syslog日志输出 --23.09.26 + + +2023年10月07日 + 固件版本号:GX393C1007 + 1.增加G200 90ppm速度模式 --23.10.07 + 2.增加双张出纸口过纸使能 --23.10.07 + 3.增加液晶面板滚轴张数操作 --23.10.07 + 4.int端点增加扫描张数信息、异常信息 --23.10.11 + 5.增加镜头脏污检测功能 --23.10.16 + 6.调整vsp寄存器配置 8 bit-> 9bit --23.10.17 + 7.使用全局变量统一读写json --23.10.23 + 8.流程调整,提速 --23.10.23 + 9.增加获取或设置片上时间功能 --23.10.25 + 10.基于文件大小跳过空白页 --23.11.03 + 11.修复双张校验异常提示取图失败问题 --23.11.16 + 12.调整旋转对折方式 --23.11.17 + 13.适配9000c版本,修复拼缝问题,fpga增加采集过滤功能 --23.11.17 + 14.增加pick_paper校验 --23.11.22 + 15.修复文件拷贝时未加f参数导致未成功备份问题 --23.11.23 + 16.调整脏污检测与待纸扫描异常提示问题 --23.11.30 + 17.调整200dpi 灰度时缩放算法参数 由双线性插值改为区域均值 --23.11.30 + 18.调整双张图像上传与跳过空白页算法逻辑 --23.12.05 + 19.更新脏污检测算法 --23.12.06 + 20.更新算法 跳过空白页 ->1.91 + 穿孔算法 -> 1.11 + 答题卡除红 ->1.54 + 防渗透算法 ->3.1 --23.12.06 + 21.更新裁切纠偏 除穿孔算法,分离除色散算法 --23.12.08 + 22.修复G200 代码脏污检测报错再结束中断之前问题 --23.12.08 + 23.调整跳过空白页到亮度、对比度算法之后 --23.12.08 + 24.G100按键液晶增加耗材查询功能 --23.12.11 + 25.屏蔽灰度除色散算法 --23.12.11 \ No newline at end of file diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..0fe93d4 --- /dev/null +++ b/config.h.in @@ -0,0 +1,10 @@ +#pragma once + +#define FPGA_UART "/dev/ttyUSB0" +#define MOTOR_UART "/dev/ttyS4" +/* #undef CIS_TYPE */ +/* #undef TEST_IMAGE_DIR */ +/* #undef CAP_UNFIXED */ +#define TEST_FPGA "ON" +/* #undef LOOP_DEBUG */ +#define VIDEO_CLASS GVideoISP1 \ No newline at end of file diff --git a/deviceio/CMakeLists.txt b/deviceio/CMakeLists.txt new file mode 100644 index 0000000..1c8bcc8 --- /dev/null +++ b/deviceio/CMakeLists.txt @@ -0,0 +1,16 @@ +project(deviceio) +add_compile_options(-std=c++14) +#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -O2") +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -O2") + +aux_source_directory(${PROJECT_SOURCE_DIR} DIR_SRCS) +file(GLOB DIR_HEADS "${PROJECT_SOURCE_DIR}/*.h" "${PROJECT_SOURCE_DIR}/*.hpp") +set(DIR_SRCS ${DIR_SRCS} ${DIR_HEADS}) + +add_library(${PROJECT_NAME} STATIC ${DIR_SRCS}) + +target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR}/../packages/common.pkg/include + ) + +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../bin) \ No newline at end of file diff --git a/deviceio/DevUtil.cpp b/deviceio/DevUtil.cpp new file mode 100644 index 0000000..289db35 --- /dev/null +++ b/deviceio/DevUtil.cpp @@ -0,0 +1,32 @@ +#include "DevUtil.h" +#include +#include "stringex.hpp" + +#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(string_format(PWMEXPORTPATH, pwms[i]), 0); +} diff --git a/deviceio/DevUtil.h b/deviceio/DevUtil.h new file mode 100644 index 0000000..3c3d261 --- /dev/null +++ b/deviceio/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 = 70, + +#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/deviceio/Gpio.cpp b/deviceio/Gpio.cpp new file mode 100644 index 0000000..7b0cbdb --- /dev/null +++ b/deviceio/Gpio.cpp @@ -0,0 +1,95 @@ +// +// Created by yingluo907 on 2019/4/11. +// +#include "Gpio.h" +#include "DevUtil.h" +#include "stringex.hpp" +#include +#include +#include +#include + +#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 = string_format(IOPATH, path_gpiobase.c_str(), port, path_value.c_str()); + path_edge = string_format(IOPATH, path_gpiobase.c_str(), port, path_edge.c_str()); + path_direction = string_format(IOPATH, path_gpiobase.c_str(), port, path_direction.c_str()); + path_active_low = string_format(IOPATH, path_gpiobase.c_str(), port, path_active_low.c_str()); + char fpath[128]{}; + sprintf(fpath, "/sys/class/gpio/gpio%d/value", port); + printf("Gpio::Gpio(int port = %d) \n", port); + gpio_fd = open(fpath, O_RDWR); +} + +Gpio::~Gpio() +{ + close(gpio_fd); +} +int Gpio::getPort() +{ + return port; +} + +void Gpio::setValue(GpioLevel level) +{ + // write_dev(path_value, level); + if (port == 153 || port == 150) + printf("\n Gpio %d setvalue %d ", port, level == Low ? 0 : 1); + if (level == Low) + write(gpio_fd, "0\n", 2); + else + write(gpio_fd, "1\n", 2); +} + +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) +{ + if (port == 153 || port == 150) + printf("\n Gpio %d setDirection %s ", port, direction.c_str()); + 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/deviceio/Gpio.h b/deviceio/Gpio.h new file mode 100644 index 0000000..f9f236c --- /dev/null +++ b/deviceio/Gpio.h @@ -0,0 +1,52 @@ +#pragma once +#include + +class Gpio +{ +public: + enum GpioLevel + { + Low, + High + }; + + Gpio(int port); + ~Gpio(); + 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"; + int gpio_fd; +}; + +class GpioOut : public Gpio +{ +public: + GpioOut(int port); +}; diff --git a/deviceio/Led.cpp b/deviceio/Led.cpp new file mode 100644 index 0000000..098e869 --- /dev/null +++ b/deviceio/Led.cpp @@ -0,0 +1,45 @@ +#include "Led.h" +#include "stringex.hpp" + +#define LEDPATH "%s/%s/%s" + +std::string Led::timer = "timer"; +std::string Led::none = "none"; + +Led::Led(std::string name) +{ + path_brightness = string_format(LEDPATH, path_base.c_str(), name.c_str(), path_brightness.c_str()); + path_trigger = string_format(LEDPATH, path_base.c_str(), name.c_str(), path_trigger.c_str()); + path_delay_off = string_format(LEDPATH, path_base.c_str(), name.c_str(), path_delay_off.c_str()); + path_delay_on = string_format(LEDPATH, path_base.c_str(), name.c_str(), path_delay_on.c_str()); +} + +Led::~Led() +{ +} + +void Led::on(int time_ms) +{ + if (time_ms != 0) + { + write_dev(path_trigger, timer); + write_dev(path_delay_off, time_ms); + write_dev(path_delay_on, time_ms); + } + else + { + // if (read_dev_s(path_trigger).find(none) == std::string::npos) + write_dev(path_trigger, none); + } + write_dev(path_brightness, 1); +} + +void Led::off() +{ + write_dev(path_brightness, 0); +} + +bool Led::isOn() +{ + return (bool)read_dev_i(path_brightness); +} diff --git a/deviceio/Led.h b/deviceio/Led.h new file mode 100644 index 0000000..7e8d469 --- /dev/null +++ b/deviceio/Led.h @@ -0,0 +1,24 @@ +#pragma once +#include "DevUtil.h" + +class Led +{ +public: + static std::string timer; + static std::string none; + +public: + Led(std::string name); + ~Led(); + + void on(int time_ms = 0); + void off(); + bool isOn(); + +private: + const std::string path_base = "/sys/class/leds"; + std::string path_brightness = "brightness"; + std::string path_trigger = "trigger"; + std::string path_delay_off = "delay_off"; + std::string path_delay_on = "delay_on"; +}; diff --git a/deviceio/PinMonitor.cpp b/deviceio/PinMonitor.cpp new file mode 100644 index 0000000..4c17f3e --- /dev/null +++ b/deviceio/PinMonitor.cpp @@ -0,0 +1,76 @@ +#include "PinMonitor.h" +#include "DevUtil.h" +#include +#include +#include +#include +#include +#include "StopWatch.h" + +PinMonitor::PinMonitor(unsigned int pinNum, std::function call_back) + : pin(pinNum) +{ + pin.setDirection(Gpio::in); + pin.setEdge(Gpio::falling); + this->call_back = call_back; + thread_monitor = std::thread(&PinMonitor::monitor, this); + // printf("PinMonitor threadid = %d \n",thread_monitor.get_id()); +} + +PinMonitor::~PinMonitor() +{ + bMonitor = false; + if (thread_monitor.joinable()) + thread_monitor.join(); +} + +void PinMonitor::monitor() +{ + pollfd pfd; + int ret = 0; + pfd.fd = -1; + char buf[8]; + int num; + StopWatch sw; + + pfd.fd = open(pin.getValuePath().c_str(), O_RDONLY); + if (pfd.fd < 0) + ret = -1; + + pfd.events = POLLPRI; + num = read(pfd.fd, buf, 8); // This is to clear the avaible read + + while (bMonitor) + { + ret = poll(&pfd, 1, 1000); + if (ret > 0) + { + if (pfd.revents & POLLPRI) + { + lseek(pfd.fd, 0, SEEK_SET); + num = read(pfd.fd, buf, 8); + + buf[num - 1] = '\0'; + ret = atoi(buf); + + if (call_back) + call_back(pin.getPort()); + + sw.reset(); + while (sw.elapsed_ms() < 30) + { + ret = poll(&pfd, 1, 1); + if (ret > 0) + { + num = read(pfd.fd, buf, 8); + buf[num - 1] = '\0'; + ret = atoi(buf); + // printf("pMonitor nread = %d ret val = %d \n",num,ret); + } + } + } + } + } + + close(pfd.fd); +} \ No newline at end of file diff --git a/deviceio/PinMonitor.h b/deviceio/PinMonitor.h new file mode 100644 index 0000000..60fd831 --- /dev/null +++ b/deviceio/PinMonitor.h @@ -0,0 +1,19 @@ +#pragma once +#include "Gpio.h" +#include +#include + +class PinMonitor +{ +public: + PinMonitor(unsigned int pinNum, std::function call_back); + ~PinMonitor(); + +private: + void monitor(); + + Gpio pin; + std::function call_back; + std::thread thread_monitor; + volatile bool bMonitor = true; +}; \ No newline at end of file diff --git a/deviceio/Pwm.cpp b/deviceio/Pwm.cpp new file mode 100644 index 0000000..1fd76be --- /dev/null +++ b/deviceio/Pwm.cpp @@ -0,0 +1,38 @@ +#include "Pwm.h" +#include "DevUtil.h" +#include "stringex.hpp" + +#define PWMPATH "%s%d/pwm0/%s" + +Pwm::Pwm(int port) +{ + path_enable = string_format(PWMPATH, path_base.c_str(), port, path_enable.c_str()); + path_duty_cycle = string_format(PWMPATH, path_base.c_str(), port, path_duty_cycle.c_str()); + path_period = string_format(PWMPATH, path_base.c_str(), port, path_period.c_str()); +} + +Pwm::~Pwm() +{ +} + +void Pwm::setFreq(int freq) +{ + int value = PWM_PERIOD / freq; + write_dev(path_period, value); + write_dev(path_duty_cycle, value / 2); +} + +int Pwm::getFreq() +{ + return PWM_PERIOD / read_dev_i(path_period); +} + +void Pwm::enable(bool bEnable) +{ + write_dev(path_enable, bEnable); +} + +bool Pwm::isEnable() +{ + return (bool)read_dev_i(path_enable); +} diff --git a/deviceio/Pwm.h b/deviceio/Pwm.h new file mode 100644 index 0000000..3782a2e --- /dev/null +++ b/deviceio/Pwm.h @@ -0,0 +1,22 @@ +#pragma once +#include +#define PWM_PERIOD 1000000000 + +class Pwm +{ +public: + Pwm(int port); + ~Pwm(); + + void setFreq(int freq); + int getFreq(); + + void enable(bool bEnable); + bool isEnable(); + +private: + const std::string path_base = "/sys/class/pwm/pwmchip"; + std::string path_enable = "enable"; + std::string path_duty_cycle = "duty_cycle"; + std::string path_period = "period"; +}; diff --git a/deviceio/xmake.lua b/deviceio/xmake.lua new file mode 100644 index 0000000..e234c1c --- /dev/null +++ b/deviceio/xmake.lua @@ -0,0 +1,8 @@ +add_rules("mode.debug", "mode.release") + +target("deviceio") + set_kind("static") + add_syslinks("pthread") + add_files("*.cpp") + add_includedirs(".", { public = true}) + add_packages("common") diff --git a/display/CMakeLists.txt b/display/CMakeLists.txt new file mode 100644 index 0000000..97c8e14 --- /dev/null +++ b/display/CMakeLists.txt @@ -0,0 +1,18 @@ +project(display) +add_compile_options(-std=c++14) +#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -O2") +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -O2") + +aux_source_directory(${PROJECT_SOURCE_DIR} DIR_SRCS) +file(GLOB DIR_HEADS "${PROJECT_SOURCE_DIR}/*.h" "${PROJECT_SOURCE_DIR}/*.hpp") +set(DIR_SRCS ${DIR_SRCS} ${DIR_HEADS}) + +add_library(${PROJECT_NAME} STATIC ${DIR_SRCS}) + +target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR}/../packages/common.pkg/include + ${PROJECT_SOURCE_DIR}/../deviceio + ${PROJECT_SOURCE_DIR}/../capimage + ) + +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../bin) \ No newline at end of file diff --git a/display/DisplayCenter.cpp b/display/DisplayCenter.cpp new file mode 100644 index 0000000..5f7be70 --- /dev/null +++ b/display/DisplayCenter.cpp @@ -0,0 +1,61 @@ +#include "DisplayCenter.h" +#include "deviceconfig.h" + +DisplayCenter::DisplayCenter():m_lcd(new LCDDisplay(Get_static_deviceconfig().GetParam().language)) + ,brun(false) +{ + m_showthread.reset(new std::thread(&DisplayCenter::runloop,this)); + m_distype = DisType::Dis_Idel; +} + +DisplayCenter::~DisplayCenter() +{ + brun = false; + if(m_showthread.get()&& m_showthread->joinable()) + { + m_showthread->join(); + m_showthread.reset(); + } + + if(!m_msgs.IsShutDown()) + m_msgs.ShutDown(); + + m_lcd.reset(); +} + +void DisplayCenter::PutMsg(DisType distype,int pagenum,ClearScreen clearscreen) +{ + m_msgs.Put({distype,clearscreen,(unsigned int )pagenum,""}); + m_distype = distype; + printf("\n ----- distype = %d ",distype); +} + +void DisplayCenter::ResetMsgQueue() +{ + m_msgs.Clear(); +} + +void DisplayCenter::runloop() +{ + brun = true; + while (brun) + { + if(m_msgs.Size()>0) + { + auto msg= m_msgs.Take(); + m_lcd->DisplayState(msg.distype,msg.pagenum,msg.clearscree); + } + else + std::this_thread::sleep_for(std::chrono::milliseconds(2)); + } +} + +DisType DisplayCenter::getcurdistype() +{ + return m_distype; +} + +void DisplayCenter::set_language(LCDDisplay::Language language) +{ + if(m_lcd.get()) m_lcd->set_language(language); +} \ No newline at end of file diff --git a/display/DisplayCenter.h b/display/DisplayCenter.h new file mode 100644 index 0000000..ed5d748 --- /dev/null +++ b/display/DisplayCenter.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include "BlockingQueue.h" +#include "Displaydef.h" +#include "LCDDisplay.h" + +class DisplayCenter +{ +public: + DisplayCenter(); + ~DisplayCenter(); + void PutMsg(DisType distype,int pagenum,ClearScreen clearscreen); + void ResetMsgQueue(); + void set_language(LCDDisplay::Language language); + DisType getcurdistype(); +private: + struct MsgPair{ + DisType distype; + ClearScreen clearscree; + unsigned int pagenum; + std::string infomsg; + }; + void runloop(); +private: + BlockingQueue m_msgs; + std::shared_ptr m_showthread; + std::shared_ptr m_lcd; + volatile DisType m_distype; + bool brun; +}; \ No newline at end of file diff --git a/display/Displaydef.h b/display/Displaydef.h new file mode 100644 index 0000000..20c8b83 --- /dev/null +++ b/display/Displaydef.h @@ -0,0 +1,83 @@ +#pragma once +#include +#include +#include "HgLCDfont.h" + +enum class DisType{ + Dis_Unkown, + Dis_Init,//启动欢迎界面 + Dis_Welcome, + Dis_Idel,//就绪 + Dis_Scan, + Dis_Err_JamIn, + Dis_Err_DoubleFeed, + Dis_Err_PaperScrew, + Dis_Err_Stable, + Dis_Err_AqrImgTimeout, + Dis_Err_CoverOpen, + Dis_Err_JamOut, + Dis_Err_HandModeJam, + Dis_Err_FeedError, + Dis_Err_NoPaper, + Dis_Err_DogEar, + Dis_Err_Size, + Dis_Set_PollPaperIntensity, + Dis_Set_PollPI_High, + Dis_Set_PollPI_Mid, + Dis_Set_PollPI_Low, + Dis_Count_Page, + Dis_Scan_Page, + Dis_Set_ClearPaperPass, + Dis_Set_Count, + Dis_Set_SleepMode, + Dis_Set_SleepMode_5M, + Dis_Set_SleepMode_10M, + Dis_Set_SleepMode_20M, + Dis_Set_SleepMode_30M, + Dis_Set_SleepMode_1H, + Dis_Set_SleepMode_2H, + Dis_Set_SleepMode_4H, + Dis_Set_SleepMode_NEVER, + Dis_Set_Poweroff, + Dis_Set_Return, + Dis_HandMode, + Dis_Set_Item_Return, + Dis_Set_TrayPosition, + Dis_Set_TrayPosition_Low, + Dis_Set_TrayPosition_Mid, + Dis_Set_TrayPosition_High, + Dis_Device_Lock, + Dis_Set_ScanNum_Option, + Dis_Set_Get_History_ScanNum, + Dis_Set_Clear_Roller_ScanNum, + Dis_Set_Get_Roller_ScanNum, + Dis_Set_Is_Sure, + Dis_Set_YES, + Dis_Set_No, + Dis_Language, + Dis_Language_Chinese, + Dis_Language_Chinese_Traditional, + Dis_Language_English, +}; + +enum class DisDrawtype +{ + DD_All, + DD_TopLeft, + DD_BotRight +}; + +enum class ClearScreen +{ + All, + TOP, + BOT, +}; + +struct DisInfo{ + unsigned char page; + unsigned char col; + DisDrawtype drawtype; + std::vector str; +}; + diff --git a/display/HgLCDfont.h b/display/HgLCDfont.h new file mode 100644 index 0000000..b0ff673 --- /dev/null +++ b/display/HgLCDfont.h @@ -0,0 +1,1186 @@ +#pragma once + +/*就绪*/ +static unsigned char f_ready[]={ +0x04,0xE4,0x25,0x26,0x24,0xE4,0x04,0x20,0x20,0xFF,0x20,0xE2,0x2C,0x20,0x20,0x00, +0x10,0x4B,0x82,0x7E,0x02,0x0B,0x90,0x60,0x1C,0x03,0x00,0x3F,0x40,0x40,0x70,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x20,0x30,0xAC,0x63,0x10,0x20,0x24,0x24,0xA4,0x7F,0x24,0x34,0x28,0x26,0x20,0x00, +0x22,0x67,0x22,0x12,0x12,0x04,0x02,0xFF,0x49,0x49,0x49,0x49,0xFF,0x00,0x00,0x00 +}; + +/*就绪 Ready*/ +static unsigned char f_ready_EN[]={ +'R','e','a','d','y',0x00 +}; + +/*就绪 就緒*/ +static unsigned char f_ready_TC[]={ +0x04,0xE4,0x25,0x26,0x24,0xE4,0x04,0x20,0x20,0xFF,0x20,0xE2,0x2C,0x20,0x20,0x00, +0x10,0x4B,0x82,0x7E,0x02,0x0B,0x90,0x60,0x1C,0x03,0x00,0x3F,0x40,0x40,0x70,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x20,0x30,0xAC,0x63,0x20,0x18,0x20,0x24,0x24,0xA4,0x7F,0x24,0x34,0x28,0x26,0x00, +0x42,0x33,0x02,0x32,0x03,0x36,0x04,0x02,0xFF,0x49,0x49,0x49,0x49,0xFF,0x00,0x00 +}; + +/*图标*/ +static unsigned char f_logo[]={ +0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00, +0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x03, +0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xF0,0xFC,0xFC, +0x3C,0x3F,0x3F,0x3F,0x3C,0x3C,0x3C,0x00,0x00,0x00,0x00,0xC0,0xF0,0xFC,0xFC,0x3C, +0x3F,0x3F,0x3C,0xFC,0xFC,0xF0,0xC0,0x00,0x00,0x00,0x00,0xF0,0xFC,0x3C,0x3F,0x3F, +0x3F,0x3C,0x3C,0x3C,0x00,0x00,0x00,0xC0,0xF0,0xFC,0xFC,0x3F,0x3F,0x3F,0x3F,0x3C, +0x3C,0xFC,0x30,0x00,0x00,0x00,0x00,0x00,0xC3,0xFF,0xFF,0xFF,0xFF,0xFC,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFC,0xC0,0x00,0x00,0x00,0x03,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xF0,0xC0,0xC0,0xC0,0xC0,0xF0,0xFF,0xFF,0x00,0x00,0x00,0x00, +0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0xC0,0xFC, +0xFF,0x3F,0x00,0x03,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x0F,0x00, +0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0xC0,0xFF,0xFF,0x03,0x00,0x00, +0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xF0,0x00,0x00,0x0F,0xFF,0xFF,0xF0,0xF0,0xC0, +0xC0,0xC0,0x00,0x00,0x00,0x00,0xFC,0xFF,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0x03,0x00,0x00,0x3F,0xFF,0xFF,0x00, +0x00,0x00,0x00,0x00,0x00,0xFF,0x03,0x0F,0x3F,0xFF,0xFC,0x00,0x00,0x00,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0x07,0x01,0x01,0x01,0x01,0x07,0xFF,0xFF,0x00,0x00,0x00,0x00, +0xFF,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x7F,0x00,0x00,0x80,0xFF,0xFF, +0xF9,0xE0,0xE0,0xE0,0xE0,0xFF,0xFF,0xFF,0xF8,0x00,0x00,0xFF,0xFF,0xFF,0xE0,0x00, +0x00,0x00,0x07,0x07,0x07,0xFF,0xFF,0x00,0x00,0x00,0x01,0xFF,0xFF,0xE0,0x00,0x00, +0x00,0x00,0x00,0x00,0x80,0xFF,0xFF,0x1F,0x00,0x00,0x00,0x00,0x01,0x01,0x07,0x07, +0x1F,0xFF,0xFF,0xF8,0x00,0x00,0x7F,0xFF,0xF8,0x80,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xE0,0xFE,0xFF,0xFF,0xE0,0xE0,0xE0,0xE0,0xF9,0xFF,0xFE, +0x80,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x01,0x1F,0xF8,0x80,0x80,0xFF,0xFF, +0x7F,0x7F,0x7F,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x7F,0x00,0x00,0x00,0x00, +0x01,0x1F,0x7F,0x7E,0x78,0x78,0x7E,0x7E,0x1F,0x07,0x00,0x00,0x60,0x7F,0x1F,0x07, +0x01,0x01,0x01,0x01,0x01,0x01,0x07,0x7F,0x7F,0x60,0x00,0x01,0x07,0x1F,0x1F,0x7E, +0x7E,0x78,0x78,0x78,0x78,0x7F,0x7F,0x00,0x00,0x00,0x00,0x07,0x1F,0x1F,0x7E,0x7E, +0x78,0x78,0x7E,0x7E,0x7F,0x1F,0x01,0x00,0x00,0x00,0x00,0x78,0x78,0x78,0x78,0x7E, +0x7E,0x7F,0x1F,0x01,0x00,0x00,0x00,0x01,0x1F,0x7F,0x7E,0x7E,0x78,0x78,0x78,0x7E, +0x7E,0x1E,0x18,0x00,0x78,0x7F,0x7F,0x07,0x01,0x01,0x01,0x01,0x01,0x01,0x07,0x7F, +0x7F,0x78,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x1F,0x7F,0x7F,0x7F,0x7F +}; + + +/*欢迎使用*/ +static unsigned char f_welcome[] = { +0x04,0x24,0x44,0x84,0x64,0x9C,0x40,0x30,0x0F,0xC8,0x08,0x08,0x28,0x18,0x00,0x00, +0x10,0x08,0x06,0x01,0x82,0x4C,0x20,0x18,0x06,0x01,0x06,0x18,0x20,0x40,0x80,0x00, +0x40,0x40,0x42,0xCC,0x00,0x00,0xFC,0x04,0x02,0x00,0xFC,0x04,0x04,0xFC,0x00,0x00, +0x00,0x40,0x20,0x1F,0x20,0x40,0x4F,0x44,0x42,0x40,0x7F,0x42,0x44,0x43,0x40,0x00, +0x80,0x60,0xF8,0x07,0x04,0xE4,0x24,0x24,0x24,0xFF,0x24,0x24,0x24,0xE4,0x04,0x00, +0x00,0x00,0xFF,0x00,0x80,0x81,0x45,0x29,0x11,0x2F,0x41,0x41,0x81,0x81,0x80,0x00, +0x00,0x00,0xFE,0x22,0x22,0x22,0x22,0xFE,0x22,0x22,0x22,0x22,0xFE,0x00,0x00,0x00, +0x80,0x60,0x1F,0x02,0x02,0x02,0x02,0x7F,0x02,0x02,0x42,0x82,0x7F,0x00,0x00,0x00, +}; + +/*欢迎使用 welcome*/ +static unsigned char f_welcome_EN[] = { +'W','e','l','c','o','m','e',0x00 +}; + + +/*欢迎使用 歡迎使用*/ +static unsigned char f_welcome_TC[] = { +0x04,0x74,0x5F,0xF4,0x04,0x74,0xDF,0x74,0x24,0x18,0x0F,0xC8,0x08,0x28,0x18,0x00, +0x04,0x02,0xFF,0x55,0x55,0x7F,0x55,0x55,0x80,0x60,0x1C,0x03,0x1C,0x60,0x80,0x00, +0x40,0x40,0x42,0xCC,0x00,0x00,0xFC,0x04,0x02,0x00,0xFC,0x04,0x04,0xFC,0x00,0x00, +0x00,0x40,0x20,0x1F,0x20,0x40,0x4F,0x44,0x42,0x40,0x7F,0x42,0x44,0x43,0x40,0x00, +0x80,0x60,0xF8,0x07,0x04,0xE4,0x24,0x24,0x24,0xFF,0x24,0x24,0x24,0xE4,0x04,0x00, +0x00,0x00,0xFF,0x00,0x80,0x81,0x45,0x29,0x11,0x2F,0x41,0x41,0x81,0x81,0x80,0x00, +0x00,0x00,0xFE,0x22,0x22,0x22,0x22,0xFE,0x22,0x22,0x22,0x22,0xFE,0x00,0x00,0x00, +0x80,0x60,0x1F,0x02,0x02,0x02,0x02,0x7F,0x02,0x02,0x42,0x82,0x7F,0x00,0x00,0x00 +}; + +/*清理纸道*/ +static unsigned char f_clearpaperpass[]={ +0x10,0x60,0x02,0x8C,0x00,0x44,0x54,0x54,0x54,0x7F,0x54,0x54,0x54,0x44,0x40,0x00, +0x04,0x04,0x7E,0x01,0x00,0x00,0xFF,0x15,0x15,0x15,0x55,0x95,0x7F,0x00,0x00,0x00, +0x04,0x84,0x84,0xFC,0x84,0x84,0x00,0xFE,0x92,0x92,0xFE,0x92,0x92,0xFE,0x00,0x00, +0x20,0x60,0x20,0x1F,0x10,0x10,0x40,0x44,0x44,0x44,0x7F,0x44,0x44,0x44,0x40,0x00, +0x20,0x30,0xAC,0x63,0x30,0x00,0xFC,0x84,0x84,0x84,0xFE,0x82,0x83,0x82,0x80,0x00, +0x22,0x67,0x22,0x12,0x12,0x00,0xFF,0x40,0x20,0x00,0x01,0x0E,0x30,0x40,0xF8,0x00, +0x40,0x40,0x42,0xCC,0x00,0x08,0xE9,0xAA,0xB8,0xA8,0xA8,0xAA,0xE9,0x08,0x00,0x00, +0x00,0x40,0x20,0x1F,0x20,0x40,0x5F,0x4A,0x4A,0x4A,0x4A,0x4A,0x5F,0x40,0x40,0x00 +}; + +/*清理纸道 CLN paper path*/ +static unsigned char f_clearpaperpass_EN[]={ +'C','L','N',' ','P','a','p','e','r',' ','P','a','t','h',0x00 +}; + + +/*清理纸道*/ +static unsigned char f_clearpaperpass_TC[]={ +0x10,0x60,0x02,0x8C,0x00,0x44,0x54,0x54,0x54,0x7F,0x54,0x54,0x54,0x44,0x40,0x00, +0x04,0x04,0x7E,0x01,0x00,0x00,0xFF,0x15,0x15,0x15,0x55,0x95,0x7F,0x00,0x00,0x00, +0x04,0x84,0x84,0xFC,0x84,0x84,0x00,0xFE,0x92,0x92,0xFE,0x92,0x92,0xFE,0x00,0x00, +0x20,0x60,0x20,0x1F,0x10,0x10,0x40,0x44,0x44,0x44,0x7F,0x44,0x44,0x44,0x40,0x00, +0x20,0x30,0xAC,0x63,0x20,0x18,0x00,0xFC,0x84,0x84,0x84,0xFE,0x82,0x83,0x82,0x00, +0x42,0x33,0x02,0x32,0x03,0x36,0x00,0xFF,0x40,0x20,0x00,0x07,0x38,0x40,0xF0,0x00, +0x40,0x40,0x42,0xCC,0x00,0x08,0xE9,0xAA,0xB8,0xA8,0xA8,0xAA,0xE9,0x08,0x00,0x00, +0x00,0x40,0x20,0x1F,0x20,0x40,0x5F,0x4A,0x4A,0x4A,0x4A,0x4A,0x5F,0x40,0x40,0x00 +}; + + +/*计数*/ +static unsigned char f_countmode[] = { +0x40,0x40,0x42,0xCC,0x00,0x40,0x40,0x40,0x40,0xFF,0x40,0x40,0x40,0x40,0x40,0x00, +0x00,0x00,0x00,0x7F,0x20,0x10,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x90,0x52,0x34,0x10,0xFF,0x10,0x34,0x52,0x80,0x70,0x8F,0x08,0x08,0xF8,0x08,0x00, +0x82,0x9A,0x56,0x63,0x22,0x52,0x8E,0x00,0x80,0x40,0x33,0x0C,0x33,0x40,0x80,0x00 +}; + +/*计数 Count*/ +static unsigned char f_countmode_EN[] = { +'C','o','u','n','t',0x00 +}; + +/*计数 計數*/ +static unsigned char f_countmode_TC[] = { +0x08,0xA8,0xA9,0xAE,0xA8,0xA8,0x48,0x40,0x40,0x40,0xFF,0x40,0x40,0x40,0x40,0x00, +0x00,0x7E,0x22,0x22,0x22,0x7E,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x08,0xBE,0xAA,0xAA,0xFF,0xAA,0xAA,0xBE,0x08,0x20,0xD8,0x17,0x10,0xF0,0x10,0x00, +0x88,0xAB,0xBA,0xAE,0x4B,0x4A,0xAA,0x9B,0x80,0x40,0x37,0x08,0x36,0x41,0x80,0x00 +}; + +/*折角*/ +static unsigned char f_dogear[] = { +0x10,0x10,0x10,0xFF,0x10,0x90,0x00,0xFC,0x44,0x44,0x44,0xC2,0x43,0x42,0x40,0x00, +0x04,0x44,0x82,0x7F,0x01,0x80,0x60,0x1F,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x20,0x10,0xE8,0x24,0x27,0x24,0x24,0xE4,0x24,0x34,0x2C,0x20,0xE0,0x00,0x00,0x00, +0x80,0x60,0x1F,0x09,0x09,0x09,0x09,0x7F,0x09,0x09,0x49,0x89,0x7F,0x00,0x00,0x00, +}; + +/*折角 EN*/ +static unsigned char f_dogear_EN[] = { +'F','o','l','d','e','d',' ','C','o','r','n','e','r',0x00 +}; + +/*折角 折角*/ +static unsigned char f_dogear_TC[] = { +0x10,0x10,0x10,0xFF,0x10,0x90,0x00,0xFC,0x44,0x44,0x44,0xC2,0x43,0x42,0x40,0x00, +0x04,0x44,0x82,0x7F,0x01,0x80,0x60,0x1F,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x20,0x10,0xE8,0x24,0x27,0x24,0x24,0xE4,0x24,0x34,0x2C,0x20,0xE0,0x00,0x00,0x00, +0x80,0x60,0x1F,0x09,0x09,0x09,0x09,0x7F,0x09,0x09,0x49,0x89,0x7F,0x00,0x00,0x00, +}; + +static unsigned char f_size[] = { +0x00,0x00,0x00,0xFE,0x42,0x42,0x42,0x42,0xC2,0x42,0x42,0x42,0x7E,0x00,0x00,0x00, +0x80,0x40,0x30,0x0F,0x00,0x00,0x00,0x00,0x03,0x0C,0x10,0x20,0x40,0x80,0x80,0x00, +0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x10,0x10,0x00, +0x00,0x00,0x00,0x01,0x06,0x00,0x00,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x02,0x02,0x02,0x02,0x82,0x42,0xF2,0x0E,0x42,0x82,0x02,0x02,0x02,0x00,0x00, +0x10,0x08,0x04,0x02,0x01,0x00,0x00,0xFF,0x00,0x00,0x00,0x01,0x02,0x0C,0x00,0x00, +0x10,0x08,0x04,0x87,0x6C,0x14,0x84,0x94,0x88,0x87,0x84,0xEC,0x94,0x84,0x84,0x00, +0x04,0x02,0x01,0xFF,0x00,0x00,0x00,0x02,0x0C,0x40,0x80,0x7F,0x00,0x00,0x00,0x00, +}; + +/*双张*/ +static unsigned char f_doublefeed[] = { +0x04,0x34,0xC4,0x04,0xC4,0x3C,0x00,0x04,0xFC,0x04,0x04,0x04,0xC4,0x3C,0x00,0x00, +0x40,0x30,0x0C,0x03,0x0C,0x30,0x80,0x40,0x20,0x13,0x0C,0x13,0x20,0x40,0x80,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x02,0xE2,0x22,0x22,0x3E,0x80,0x80,0xFF,0x80,0xA0,0x90,0x88,0x86,0x80,0x80,0x00, +0x00,0x43,0x82,0x42,0x3E,0x00,0x00,0xFF,0x40,0x21,0x06,0x08,0x10,0x20,0x40,0x00 +}; + +/*双张 Double Feed */ +static unsigned char f_doublefeed_EN[] = { +'D','B','L',' ','F','e','e','d',0x00 +}; + +/*双张 雙張 */ +static unsigned char f_doublefeed_TC[] = { +0x10,0x08,0xFE,0x54,0x55,0xFE,0x54,0x54,0x08,0xFE,0x54,0x55,0xFE,0x54,0x54,0x00, +0x80,0x80,0x83,0x45,0x4D,0x55,0x25,0x25,0x24,0x57,0x4D,0x45,0x81,0x81,0x81,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x02,0xE2,0x22,0x22,0x3E,0x80,0x80,0x80,0xFE,0xAA,0xAA,0xAA,0xAA,0x82,0x80,0x00, +0x00,0x43,0x82,0x42,0x3E,0x00,0x00,0xFF,0x40,0x21,0x06,0x08,0x14,0x22,0x40,0x00 +}; + +/*订书针*/ +static unsigned char f_stable[] = { +0x10,0x10,0xD0,0xFF,0x90,0x50,0x20,0x50,0x4C,0x43,0x4C,0x50,0x20,0x40,0x40,0x00, +0x04,0x03,0x00,0xFF,0x00,0x41,0x44,0x58,0x41,0x4E,0x60,0x58,0x47,0x40,0x40,0x00, +0x10,0x60,0x02,0x8C,0x00,0xFE,0x02,0xF2,0x02,0xFE,0x00,0xF8,0x00,0xFF,0x00,0x00, +0x04,0x04,0x7E,0x01,0x80,0x47,0x30,0x0F,0x10,0x27,0x00,0x47,0x80,0x7F,0x00,0x00, +0x42,0x62,0x52,0x4A,0xC6,0x42,0x52,0x62,0xC2,0x00,0xF8,0x00,0x00,0xFF,0x00,0x00, +0x40,0xC4,0x44,0x44,0x7F,0x24,0x24,0x24,0x20,0x00,0x0F,0x40,0x80,0x7F,0x00,0x00, +0x40,0x40,0x42,0xCC,0x00,0x00,0x04,0x04,0x04,0x04,0xFC,0x04,0x04,0x04,0x04,0x00, +0x00,0x00,0x00,0x7F,0x20,0x10,0x00,0x00,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x08,0x08,0x08,0x08,0xFF,0x08,0x08,0x08,0xF9,0x02,0x04,0x00,0x00,0x00, +0x01,0x01,0x01,0x01,0x01,0x01,0xFF,0x01,0x01,0x01,0x21,0x41,0x21,0x1F,0x00,0x00, +0x40,0x20,0x38,0xE7,0x24,0x24,0x44,0x40,0x40,0x40,0xFF,0x40,0x40,0x40,0x40,0x00, +0x01,0x01,0x01,0x7F,0x21,0x11,0x09,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00, +}; + +/*订书针*/ +static unsigned char f_stable_EN[] = { +'S','t','a','b','l','e',0x00 +}; + +/*订书针*/ +static unsigned char f_stable_TC[] = { +0x08,0xA8,0xA9,0xAE,0xA8,0xA8,0x08,0x04,0x04,0x04,0xFC,0x04,0x04,0x04,0x04,0x00, +0x00,0x7E,0x22,0x22,0x22,0x7E,0x00,0x00,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x08,0x08,0xAA,0xAA,0xAA,0xAA,0xAA,0xFF,0xAA,0xAA,0xAA,0xBE,0x88,0x08,0x08,0x00, +0x02,0x02,0x02,0xFA,0xAA,0xAA,0xAA,0xAB,0xAA,0xAA,0xAA,0xFA,0x02,0x02,0x02,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x20,0x10,0x2C,0xE3,0x24,0x28,0x50,0x40,0x40,0x40,0xFF,0x40,0x40,0x40,0x40,0x00, +0x45,0xD9,0x41,0x7F,0x29,0x25,0x21,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00 +}; + +/*开盖*/ +static unsigned char f_coveropen[] = { +0x40,0x40,0x42,0xCC,0x00,0x40,0xA0,0x9E,0x82,0x82,0x82,0x9E,0xA0,0x20,0x20,0x00, +0x00,0x00,0x00,0x3F,0x90,0x88,0x40,0x43,0x2C,0x10,0x28,0x46,0x41,0x80,0x80,0x00, +0x80,0x90,0x90,0x48,0x4C,0x57,0x24,0x24,0x24,0x54,0x4C,0x44,0x80,0x80,0x80,0x00, +0x00,0x00,0x00,0xFF,0x49,0x49,0x49,0x7F,0x49,0x49,0x49,0xFF,0x00,0x00,0x00,0x00, +0x80,0x82,0x82,0x82,0xFE,0x82,0x82,0x82,0x82,0x82,0xFE,0x82,0x82,0x82,0x80,0x00, +0x00,0x80,0x40,0x30,0x0F,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00, +0x00,0x04,0x24,0x24,0x25,0x26,0x24,0xFC,0x24,0x26,0x25,0x24,0x24,0x04,0x00,0x00, +0x81,0x81,0xF9,0x89,0x89,0xF9,0x89,0x89,0x89,0xF9,0x89,0x89,0xF9,0x81,0x81,0x00 +}; + +/*开盖*/ +static unsigned char f_coveropen_EN[] = { +'C','o','v','e','r',' ','O','p','e','n','e','d',0x00 +}; + +/*开盖*/ +static unsigned char f_coveropen_TC[] = { +0x00,0xFE,0x2A,0x2A,0xAA,0xBE,0x80,0x80,0xBE,0xAA,0x2A,0x2A,0xFE,0x00,0x00,0x00, +0x00,0xFF,0x00,0x44,0x24,0x1F,0x04,0x04,0x7F,0x04,0x44,0x80,0x7F,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x02,0x42,0x52,0x52,0xD7,0x52,0x52,0x7A,0x52,0x52,0x57,0x52,0x52,0x42,0x02,0x00, +0x40,0x40,0x7A,0x4B,0x4A,0x7A,0x4A,0x4A,0x4A,0x7A,0x4A,0x4B,0x7A,0x40,0x40,0x00 +}; + +/*手动模式卡纸*/ +static unsigned char f_handmodepaperjam[] = { +0x00,0x00,0x24,0x24,0x24,0x24,0x24,0xFC,0x22,0x22,0x22,0x23,0x22,0x00,0x00,0x00, +0x02,0x02,0x02,0x02,0x02,0x42,0x82,0x7F,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,/*"手",0*/ +0x40,0x44,0xC4,0x44,0x44,0x44,0x40,0x10,0x10,0xFF,0x10,0x10,0x10,0xF0,0x00,0x00, +0x10,0x3C,0x13,0x10,0x14,0xB8,0x40,0x30,0x0E,0x01,0x40,0x80,0x40,0x3F,0x00,0x00,/*"动",1*/ +0x10,0x10,0xD0,0xFF,0x90,0x14,0xE4,0xAF,0xA4,0xA4,0xA4,0xAF,0xE4,0x04,0x00,0x00, +0x04,0x03,0x00,0xFF,0x00,0x89,0x4B,0x2A,0x1A,0x0E,0x1A,0x2A,0x4B,0x88,0x80,0x00,/*"模",2*/ +0x10,0x10,0x90,0x90,0x90,0x90,0x90,0x10,0x10,0xFF,0x10,0x10,0x11,0x16,0x10,0x00, +0x00,0x20,0x60,0x20,0x3F,0x10,0x10,0x10,0x00,0x03,0x0C,0x10,0x20,0x40,0xF8,0x00,/*"式",3*/ +0x40,0x40,0x40,0x40,0x40,0x40,0xFF,0x44,0x44,0x44,0x44,0x44,0x44,0x40,0x40,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x02,0x04,0x08,0x10,0x00,0x00,0x00,/*"卡",4*/ +0x20,0x30,0xAC,0x63,0x30,0x00,0xFC,0x84,0x84,0x84,0xFE,0x82,0x83,0x82,0x80,0x00, +0x22,0x67,0x22,0x12,0x12,0x00,0xFF,0x40,0x20,0x00,0x01,0x0E,0x30,0x40,0xF8,0x00,/*"纸",5*/ +}; + + +/*手动模式卡纸*/ +static unsigned char f_handmodepaperjam_EN[] = { +'J','a','m',0x00 +}; + + +/*手动模式卡纸*/ +static unsigned char f_handmodepaperjam_TC[] = { +0x00,0x00,0x24,0x24,0x24,0x24,0x24,0xFC,0x22,0x22,0x22,0x23,0x22,0x00,0x00,0x00, +0x02,0x02,0x02,0x02,0x02,0x42,0x82,0x7F,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00, +0x08,0xEA,0xAA,0xAA,0xFF,0xA9,0xA9,0xE9,0x08,0x10,0xFF,0x10,0x10,0xF0,0x00,0x00, +0x40,0xCB,0x4A,0x4A,0x7F,0x2A,0x2A,0xAB,0x60,0x30,0x0F,0x40,0x80,0x7F,0x00,0x00, +0x10,0x10,0xD0,0xFF,0x90,0x14,0xE4,0xAF,0xA4,0xA4,0xA4,0xAF,0xE4,0x04,0x00,0x00, +0x04,0x03,0x00,0xFF,0x00,0x89,0x4B,0x2A,0x1A,0x0E,0x1A,0x2A,0x4B,0x88,0x80,0x00, +0x10,0x10,0x90,0x90,0x90,0x90,0x90,0x10,0x10,0xFF,0x10,0x10,0x11,0x16,0x10,0x00, +0x00,0x20,0x60,0x20,0x3F,0x10,0x10,0x10,0x00,0x03,0x0C,0x10,0x20,0x40,0xF8,0x00, +0x40,0x40,0x40,0x40,0x40,0x40,0xFF,0x44,0x44,0x44,0x44,0x44,0x44,0x40,0x40,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x02,0x04,0x08,0x10,0x00,0x00,0x00, +0x20,0x30,0xAC,0x63,0x20,0x18,0x00,0xFC,0x84,0x84,0x84,0xFE,0x82,0x83,0x82,0x00, +0x42,0x33,0x02,0x32,0x03,0x36,0x00,0xFF,0x40,0x20,0x00,0x07,0x38,0x40,0xF0,0x00 + +}; + +/*手动模式*/ +static unsigned char f_handmode[] = { +0x00,0x00,0x24,0x24,0x24,0x24,0x24,0xFC,0x22,0x22,0x22,0x23,0x22,0x00,0x00,0x00, +0x02,0x02,0x02,0x02,0x02,0x42,0x82,0x7F,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00, +0x40,0x44,0xC4,0x44,0x44,0x44,0x40,0x10,0x10,0xFF,0x10,0x10,0x10,0xF0,0x00,0x00, +0x10,0x3C,0x13,0x10,0x14,0xB8,0x40,0x30,0x0E,0x01,0x40,0x80,0x40,0x3F,0x00,0x00, +0x10,0x10,0xD0,0xFF,0x90,0x14,0xE4,0xAF,0xA4,0xA4,0xA4,0xAF,0xE4,0x04,0x00,0x00, +0x04,0x03,0x00,0xFF,0x00,0x89,0x4B,0x2A,0x1A,0x0E,0x1A,0x2A,0x4B,0x88,0x80,0x00, +0x10,0x10,0x90,0x90,0x90,0x90,0x90,0x10,0x10,0xFF,0x10,0x10,0x11,0x16,0x10,0x00, +0x00,0x20,0x60,0x20,0x3F,0x10,0x10,0x10,0x00,0x03,0x0C,0x10,0x20,0x40,0xF8,0x00, +}; + +/*手动模式*/ +static unsigned char f_handmode_EN[] = { +'M','a','n','u','a','l',' ','M','o','d','e',0x00 +}; + +/*手动模式*/ +static unsigned char f_handmode_TC[] = { +0x00,0x00,0x24,0x24,0x24,0x24,0x24,0xFC,0x22,0x22,0x22,0x23,0x22,0x00,0x00,0x00, +0x02,0x02,0x02,0x02,0x02,0x42,0x82,0x7F,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00, +0x08,0xEA,0xAA,0xAA,0xFF,0xA9,0xA9,0xE9,0x08,0x10,0xFF,0x10,0x10,0xF0,0x00,0x00, +0x40,0xCB,0x4A,0x4A,0x7F,0x2A,0x2A,0xAB,0x60,0x30,0x0F,0x40,0x80,0x7F,0x00,0x00, +0x10,0x10,0xD0,0xFF,0x90,0x14,0xE4,0xAF,0xA4,0xA4,0xA4,0xAF,0xE4,0x04,0x00,0x00, +0x04,0x03,0x00,0xFF,0x00,0x89,0x4B,0x2A,0x1A,0x0E,0x1A,0x2A,0x4B,0x88,0x80,0x00, +0x10,0x10,0x90,0x90,0x90,0x90,0x90,0x10,0x10,0xFF,0x10,0x10,0x11,0x16,0x10,0x00, +0x00,0x20,0x60,0x20,0x3F,0x10,0x10,0x10,0x00,0x03,0x0C,0x10,0x20,0x40,0xF8,0x00 +}; + +/*纸张歪斜*/ +static unsigned char f_paperscrew[] = { +0x20,0x30,0xAC,0x63,0x30,0x00,0xFC,0x84,0x84,0x84,0xFE,0x82,0x83,0x82,0x80,0x00, +0x22,0x67,0x22,0x12,0x12,0x00,0xFF,0x40,0x20,0x00,0x01,0x0E,0x30,0x40,0xF8,0x00, +0x02,0xE2,0x22,0x22,0x3E,0x80,0x80,0xFF,0x80,0xA0,0x90,0x88,0x86,0x80,0x80,0x00, +0x00,0x43,0x82,0x42,0x3E,0x00,0x00,0xFF,0x40,0x21,0x06,0x08,0x10,0x20,0x40,0x00, +0x00,0x42,0x42,0x22,0x22,0x12,0x0A,0x7E,0x02,0x12,0x12,0x22,0x22,0x42,0x00,0x00, +0x40,0x41,0x41,0x7D,0x41,0x41,0x41,0x7F,0x49,0x49,0x49,0x49,0x49,0x41,0x40,0x00, +0x20,0x10,0x28,0x24,0xE3,0x24,0x28,0x10,0x00,0x22,0xCC,0x00,0xFF,0x00,0x00,0x00, +0x20,0x11,0x4D,0x81,0x7F,0x01,0x05,0x19,0x00,0x02,0x02,0x02,0xFF,0x01,0x01,0x00 +}; + +/*纸张歪斜*/ +static unsigned char f_paperscrew_EN[] = { +'S','k','e','w',0x00 +}; + +/*纸张歪斜*/ +static unsigned char f_paperscrew_TC[] = { +0x20,0x30,0xAC,0x63,0x20,0x18,0x00,0xFC,0x84,0x84,0x84,0xFE,0x82,0x83,0x82,0x00, +0x42,0x33,0x02,0x32,0x03,0x36,0x00,0xFF,0x40,0x20,0x00,0x07,0x38,0x40,0xF0,0x00, +0x02,0xE2,0x22,0x22,0x3E,0x80,0x80,0x80,0xFE,0xAA,0xAA,0xAA,0xAA,0x82,0x80,0x00, +0x00,0x43,0x82,0x42,0x3E,0x00,0x00,0xFF,0x40,0x21,0x06,0x08,0x14,0x22,0x40,0x00, +0x00,0x42,0x42,0x22,0x22,0x12,0x0A,0x7E,0x02,0x12,0x12,0x22,0x22,0x42,0x00,0x00, +0x40,0x41,0x41,0x7D,0x41,0x41,0x41,0x7F,0x49,0x49,0x49,0x49,0x49,0x41,0x40,0x00, +0x20,0x10,0x28,0x24,0xE3,0x24,0x28,0x10,0x00,0x22,0xCC,0x00,0xFF,0x00,0x00,0x00, +0x20,0x11,0x4D,0x81,0x7F,0x01,0x05,0x19,0x00,0x02,0x02,0x02,0xFF,0x01,0x01,0x00 +}; + +/*卡纸*/ +static unsigned char f_paperjam[] = { +0x40,0x40,0x40,0x40,0x40,0x40,0xFF,0x44,0x44,0x44,0x44,0x44,0x44,0x40,0x40,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x02,0x04,0x08,0x10,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x20,0x30,0xAC,0x63,0x30,0x00,0xFC,0x84,0x84,0x84,0xFE,0x82,0x83,0x82,0x80,0x00, +0x22,0x67,0x22,0x12,0x12,0x00,0xFF,0x40,0x20,0x00,0x01,0x0E,0x30,0x40,0xF8,0x00 +}; + +/*卡纸*/ +static unsigned char f_paperjam_EN[] = { +'J','a','m',0x00 +}; + +/*卡纸*/ +static unsigned char f_paperjam_TC[] = { +0x40,0x40,0x40,0x40,0x40,0x40,0xFF,0x44,0x44,0x44,0x44,0x44,0x44,0x40,0x40,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x02,0x04,0x08,0x10,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x20,0x30,0xAC,0x63,0x20,0x18,0x00,0xFC,0x84,0x84,0x84,0xFE,0x82,0x83,0x82,0x00, +0x42,0x33,0x02,0x32,0x03,0x36,0x00,0xFF,0x40,0x20,0x00,0x07,0x38,0x40,0xF0,0x00 +}; + +/*卡纸001*/ +static unsigned char f_paperjam001[] = { +0x40,0x40,0x40,0x40,0x40,0x40,0xFF,0x44,0x44,0x44,0x44,0x44,0x44,0x40,0x40,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x02,0x04,0x08,0x10,0x00,0x00,0x00, +0x20,0x30,0xAC,0x63,0x30,0x00,0xFC,0x84,0x84,0x84,0xFE,0x82,0x83,0x82,0x80,0x00, +0x22,0x67,0x22,0x12,0x12,0x00,0xFF,0x40,0x20,0x00,0x01,0x0E,0x30,0x40,0xF8,0x00, +0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00, +0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00, +0x00,0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00 +}; + +/*卡纸002*/ +static unsigned char f_paperjam002[] = { +0x40,0x40,0x40,0x40,0x40,0x40,0xFF,0x44,0x44,0x44,0x44,0x44,0x44,0x40,0x40,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x02,0x04,0x08,0x10,0x00,0x00,0x00, +0x20,0x30,0xAC,0x63,0x30,0x00,0xFC,0x84,0x84,0x84,0xFE,0x82,0x83,0x82,0x80,0x00, +0x22,0x67,0x22,0x12,0x12,0x00,0xFF,0x40,0x20,0x00,0x01,0x0E,0x30,0x40,0xF8,0x00, +0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00, +0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00, +0x00,0x70,0x08,0x08,0x08,0x08,0xF0,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00 +}; + +/*卡纸003*/ +static unsigned char f_paperjam003[] = { +0x40,0x40,0x40,0x40,0x40,0x40,0xFF,0x44,0x44,0x44,0x44,0x44,0x44,0x40,0x40,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x02,0x04,0x08,0x10,0x00,0x00,0x00, +0x20,0x30,0xAC,0x63,0x30,0x00,0xFC,0x84,0x84,0x84,0xFE,0x82,0x83,0x82,0x80,0x00, +0x22,0x67,0x22,0x12,0x12,0x00,0xFF,0x40,0x20,0x00,0x01,0x0E,0x30,0x40,0xF8,0x00, +0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00, +0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00, +0x00,0x30,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x18,0x20,0x21,0x21,0x22,0x1C,0x00 +}; + +/*搓纸失败*/ +static unsigned char f_feederror[] = { +0x10,0x10,0x10,0xFF,0x10,0x90,0x88,0xA9,0xAE,0xF8,0xA8,0xAC,0xAB,0x88,0x80,0x00, +0x04,0x44,0x82,0x7F,0x21,0x10,0x48,0x46,0x45,0x44,0x7C,0x44,0x44,0x44,0x40,0x00, +0x20,0x30,0xAC,0x63,0x30,0x00,0xFC,0x84,0x84,0x84,0xFE,0x82,0x83,0x82,0x80,0x00, +0x22,0x67,0x22,0x12,0x12,0x00,0xFF,0x40,0x20,0x00,0x01,0x0E,0x30,0x40,0xF8,0x00, +0x00,0x40,0x30,0x1E,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x00, +0x81,0x81,0x41,0x21,0x11,0x0D,0x03,0x01,0x03,0x0D,0x11,0x21,0x41,0x81,0x81,0x00, +0x00,0xFE,0x02,0xFA,0x02,0xFE,0x40,0x20,0xD8,0x17,0x10,0x10,0xF0,0x10,0x10,0x00, +0x80,0x47,0x30,0x0F,0x10,0x67,0x80,0x40,0x21,0x16,0x08,0x16,0x21,0x40,0x80,0x00 +}; + +/*搓纸失败*/ +static unsigned char f_feederror_EN[] = { +'F','e','e','d',' ','E','o','r','r','o','r',0x00 +}; + +/*搓纸失败*/ +static unsigned char f_feederror_TC[] = { +0x10,0x10,0x10,0xFF,0x10,0x90,0x88,0xA9,0xAE,0xF8,0xA8,0xAC,0xAB,0x88,0x80,0x00, +0x04,0x44,0x82,0x7F,0x21,0x10,0x48,0x46,0x45,0x44,0x7C,0x44,0x44,0x44,0x40,0x00, +0x20,0x30,0xAC,0x63,0x20,0x18,0x00,0xFC,0x84,0x84,0x84,0xFE,0x82,0x83,0x82,0x00, +0x42,0x33,0x02,0x32,0x03,0x36,0x00,0xFF,0x40,0x20,0x00,0x07,0x38,0x40,0xF0,0x00, +0x00,0x40,0x30,0x1E,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x00, +0x81,0x81,0x41,0x21,0x11,0x0D,0x03,0x01,0x03,0x0D,0x11,0x21,0x41,0x81,0x81,0x00, +0x00,0xFE,0x92,0x92,0x92,0xFE,0x40,0x30,0xCC,0x0B,0x08,0x08,0xF8,0x08,0x08,0x00, +0x80,0x47,0x34,0x04,0x14,0x67,0x80,0x40,0x21,0x16,0x08,0x16,0x21,0x40,0x80,0x00 +}; + +/*取图超时*/ +static unsigned char f_aqrimgtimeout[] = { +0x02,0x02,0xFE,0x92,0x92,0x92,0xFE,0x02,0x06,0xFC,0x04,0x04,0x04,0xFC,0x00,0x00, +0x08,0x18,0x0F,0x08,0x08,0x04,0xFF,0x04,0x84,0x40,0x27,0x18,0x27,0x40,0x80,0x00, +0x00,0xFE,0x02,0x42,0x22,0x32,0x5E,0x92,0x52,0x32,0x12,0x02,0x02,0xFE,0x00,0x00, +0x00,0xFF,0x42,0x42,0x42,0x51,0x55,0x64,0x69,0x41,0x42,0x42,0x42,0xFF,0x00,0x00, +0x40,0x48,0x48,0x48,0xFF,0x48,0x48,0x42,0xA2,0x9E,0x82,0xA2,0xC2,0xBE,0x00,0x00, +0x80,0x60,0x1F,0x20,0x7F,0x44,0x44,0x40,0x4F,0x48,0x48,0x48,0x48,0x4F,0x40,0x00, +0x00,0xFC,0x84,0x84,0x84,0xFC,0x00,0x10,0x10,0x10,0x10,0x10,0xFF,0x10,0x10,0x00, +0x00,0x3F,0x10,0x10,0x10,0x3F,0x00,0x00,0x01,0x06,0x40,0x80,0x7F,0x00,0x00,0x00 +}; + + +/*取图超时*/ +static unsigned char f_aqrimgtimeout_EN[] = { +'C','a','p','t','u','r','e',' ','T','M','O',0x00 +}; + +/*取图超时*/ +static unsigned char f_aqrimgtimeout_TC[] = { +0x02,0x02,0xFE,0x92,0x92,0x92,0xFE,0x02,0x06,0xFC,0x04,0x04,0x04,0xFC,0x00,0x00, +0x08,0x18,0x0F,0x08,0x08,0x04,0xFF,0x04,0x84,0x40,0x27,0x18,0x27,0x40,0x80,0x00, +0x00,0xFF,0x41,0x41,0x5D,0x55,0x55,0xF5,0x55,0x55,0x5D,0x41,0x41,0xFF,0x00,0x00, +0x00,0xFF,0x40,0x5F,0x51,0x5D,0x55,0x55,0x55,0x5D,0x51,0x5F,0x40,0xFF,0x00,0x00, +0x40,0x48,0x48,0x48,0xFF,0x48,0x48,0x42,0xA2,0x9E,0x82,0xA2,0xC2,0xBE,0x00,0x00, +0x80,0x60,0x1F,0x20,0x7F,0x44,0x44,0x40,0x4F,0x48,0x48,0x48,0x48,0x4F,0x40,0x00, +0x00,0xFC,0x84,0x84,0x84,0xFC,0x40,0x48,0x48,0x48,0x7F,0x48,0xC8,0x48,0x40,0x00, +0x00,0x3F,0x10,0x10,0x10,0x3F,0x00,0x02,0x0A,0x12,0x42,0x82,0x7F,0x02,0x02,0x00 +}; + + + +/*分纸强度*/ +static unsigned char f_pollpaperintensity[] = { +0x80,0x40,0x20,0x90,0x88,0x86,0x80,0x80,0x80,0x83,0x8C,0x10,0x20,0x40,0x80,0x00, +0x00,0x80,0x40,0x20,0x18,0x07,0x00,0x40,0x80,0x40,0x3F,0x00,0x00,0x00,0x00,0x00, +0x20,0x30,0xAC,0x63,0x30,0x00,0xFC,0x84,0x84,0x84,0xFE,0x82,0x83,0x82,0x80,0x00, +0x22,0x67,0x22,0x12,0x12,0x00,0xFF,0x40,0x20,0x00,0x01,0x0E,0x30,0x40,0xF8,0x00, +0x02,0xE2,0x22,0x22,0x3E,0x00,0x80,0x9E,0x92,0x92,0xF2,0x92,0x92,0x9E,0x80,0x00, +0x00,0x43,0x82,0x42,0x3E,0x40,0x47,0x44,0x44,0x44,0x7F,0x44,0x44,0x54,0xE7,0x00, +0x00,0x00,0xFC,0x24,0x24,0x24,0xFC,0x25,0x26,0x24,0xFC,0x24,0x24,0x24,0x04,0x00, +0x40,0x30,0x8F,0x80,0x84,0x4C,0x55,0x25,0x25,0x25,0x55,0x4C,0x80,0x80,0x80,0x00, +}; + + +/*分纸强度*/ +static unsigned char f_pollpaperintensity_EN[] = { +'S','e','p','a','r','a','t','i','o','n',' ','M','o','d','e',0x00 +}; + +/*分纸强度*/ +static unsigned char f_pollpaperintensity_TC[] = { +0x80,0x40,0x20,0x90,0x88,0x86,0x80,0x80,0x80,0x83,0x8C,0x10,0x20,0x40,0x80,0x00, +0x00,0x80,0x40,0x20,0x18,0x07,0x00,0x40,0x80,0x40,0x3F,0x00,0x00,0x00,0x00,0x00, +0x20,0x30,0xAC,0x63,0x20,0x18,0x00,0xFC,0x84,0x84,0x84,0xFE,0x82,0x83,0x82,0x00, +0x42,0x33,0x02,0x32,0x03,0x36,0x00,0xFF,0x40,0x20,0x00,0x07,0x38,0x40,0xF0,0x00, +0x02,0xE2,0x22,0x22,0x3E,0x00,0x90,0x98,0x94,0x92,0xF1,0x90,0x94,0x98,0xB0,0x00, +0x00,0x43,0x82,0x42,0x3E,0x40,0x47,0x44,0x44,0x44,0x7F,0x44,0x44,0x54,0xE7,0x00, +0x00,0x00,0xFC,0x24,0x24,0x24,0xFC,0x25,0x26,0x24,0xFC,0x24,0x24,0x24,0x04,0x00, +0x40,0x30,0x8F,0x80,0x84,0x4C,0x55,0x25,0x25,0x25,0x55,0x4C,0x80,0x80,0x80,0x00 +}; + +/*高*/ +static unsigned char f_intensityHigh[] = { +0x04,0x04,0x04,0x04,0xF4,0x94,0x95,0x96,0x94,0x94,0xF4,0x04,0x04,0x04,0x04,0x00, +0x00,0xFE,0x02,0x02,0x7A,0x4A,0x4A,0x4A,0x4A,0x4A,0x7A,0x02,0x82,0xFE,0x00,0x00 +}; + +/*高*/ +static unsigned char f_intensityHigh_EN[] = { +'H','i','g','h',0x00 +}; + +/*高*/ +static unsigned char f_intensityHigh_TC[] = { +0x04,0x04,0x04,0x04,0xF4,0x94,0x95,0x96,0x94,0x94,0xF4,0x04,0x04,0x04,0x04,0x00, +0x00,0xFE,0x02,0x02,0x7A,0x4A,0x4A,0x4A,0x4A,0x4A,0x7A,0x02,0x82,0xFE,0x00,0x00 +}; + + +/*中*/ +static unsigned char f_intensityMid[] = { +0x00,0x00,0xF0,0x10,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x10,0xF0,0x00,0x00,0x00, +0x00,0x00,0x0F,0x04,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x0F,0x00,0x00,0x00 +}; + +/*中*/ +static unsigned char f_intensityMid_EN[] = { +'M','i','d',0x00 +}; + +/*中*/ +static unsigned char f_intensityMid_TC[] = { +0x00,0x00,0xF0,0x10,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x10,0xF0,0x00,0x00,0x00, +0x00,0x00,0x0F,0x04,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x0F,0x00,0x00,0x00 +}; + +/*弱*/ +static unsigned char f_intensityLow[] = { +0x00,0xF2,0x92,0x92,0x92,0x92,0x9E,0x00,0xF2,0x92,0x92,0x92,0x92,0x9E,0x00,0x00, +0x00,0x10,0x11,0x4A,0x88,0x44,0x3F,0x00,0x10,0x11,0x4A,0x88,0x44,0x3F,0x00,0x00 +}; + +/*弱*/ +static unsigned char f_intensityLow_EN[] = { +'W','e','a','k',0x00 +}; + +/*弱*/ +static unsigned char f_intensityLow_TC[] = { +0x00,0xF2,0x92,0x92,0x92,0x92,0x9E,0x00,0xF2,0x92,0x92,0x92,0x92,0x9E,0x00,0x00, +0x00,0x10,0x11,0x4A,0x88,0x44,0x3F,0x00,0x10,0x11,0x4A,0x88,0x44,0x3F,0x00,0x00 +}; + +/*低*/ +static unsigned char f_traypositionLow[] = { +0x00,0x80,0x60,0xF8,0x07,0x00,0xFC,0x84,0x84,0x84,0xFE,0x82,0x83,0x82,0x80,0x00, +0x01,0x00,0x00,0xFF,0x00,0x00,0xFF,0x40,0x20,0x00,0x41,0x8E,0x30,0x40,0xF8,0x00 +}; + +/*低*/ +static unsigned char f_traypositionLow_EN[] = { +'L','o','w',0x00 +}; + +/*低*/ +static unsigned char f_traypositionLow_TC[] = { +0x00,0x80,0x60,0xF8,0x07,0x00,0xFC,0x84,0x84,0x84,0xFE,0x82,0x83,0x82,0x80,0x00, +0x01,0x00,0x00,0xFF,0x00,0x00,0xFF,0x40,0x20,0x00,0x41,0x8E,0x30,0x40,0xF8,0x00 +}; + +/*张*/ +static unsigned char f_page[] = { +0x02,0xE2,0x22,0x22,0x3E,0x80,0x80,0xFF,0x80,0xA0,0x90,0x88,0x86,0x80,0x80,0x00, +0x00,0x43,0x82,0x42,0x3E,0x00,0x00,0xFF,0x40,0x21,0x06,0x08,0x10,0x20,0x40,0x00 +}; + + +/*张*/ +static unsigned char f_page_EN[] = { +' ',0x00 +}; + + +/*張*/ +static unsigned char f_page_TC[] = { +0x02,0xE2,0x22,0x22,0x3E,0x80,0x80,0x80,0xFE,0xAA,0xAA,0xAA,0xAA,0x82,0x80,0x00, +0x00,0x43,0x82,0x42,0x3E,0x00,0x00,0xFF,0x40,0x21,0x06,0x08,0x14,0x22,0x40,0x00 +}; + +/*扫描...*/ +static unsigned char f_scan[] = { +0x10,0x10,0x10,0xFF,0x10,0x90,0x04,0x84,0x84,0x84,0x84,0x84,0x84,0xFC,0x00,0x00, +0x04,0x44,0x82,0x7F,0x01,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7F,0x00,0x00,/*"扫",0*/ +0x10,0x10,0x10,0xFF,0x10,0x90,0x04,0xC4,0x5F,0x44,0xC4,0x44,0x5F,0xC4,0x04,0x00, +0x04,0x44,0x82,0x7F,0x01,0x00,0x00,0xFF,0x44,0x44,0x7F,0x44,0x44,0xFF,0x00,0x00,/*"描",1*/ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00 +}; + +/*扫描...*/ +static unsigned char f_scan_EN[] = { +'S','c','a','n','n','i','n','g','.','.','.' ,0x00 +}; + +/*扫描...*/ +static unsigned char f_scan_TC[] = { +0x10,0x10,0x10,0xFF,0x10,0x10,0x80,0xA2,0xAA,0xAA,0xAA,0xAA,0xAA,0xBE,0x80,0x00, +0x04,0x44,0x82,0x7F,0x01,0x00,0x01,0x7C,0x04,0x04,0xFF,0x24,0x44,0x3C,0x01,0x00, +0x10,0x10,0x10,0xFF,0x10,0x90,0x04,0xC4,0x5F,0x44,0xC4,0x44,0x5F,0xC4,0x04,0x00, +0x04,0x44,0x82,0x7F,0x01,0x00,0x00,0xFF,0x44,0x44,0x7F,0x44,0x44,0xFF,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00 +}; + +/*返回*/ +static unsigned char f_back[] = { +0x40,0x40,0x42,0xCE,0xCC,0x00,0xFC,0xFC,0xA4,0xA4,0x26,0x22,0xA3,0xE3,0x62,0x00, +0x00,0x40,0x60,0x3F,0x3F,0x78,0x5F,0x57,0x58,0x4D,0x47,0x47,0x4D,0x58,0x50,0x40, +0x00,0x00,0xFE,0xFE,0x02,0xF2,0xF2,0x12,0x12,0xF2,0xF2,0x02,0xFE,0xFE,0x00,0x00, +0x00,0x00,0x7F,0x7F,0x20,0x27,0x27,0x24,0x24,0x27,0x27,0x20,0x7F,0x7F,0x00,0x00 +}; + +/*返回*/ +static unsigned char f_back_EN[] = { +'R','e','t','u','r','n',0x00 +}; + +/*返回*/ +static unsigned char f_back_TC[] = { +0x40,0x40,0x42,0xCE,0xCC,0x00,0xFC,0xFC,0xA4,0xA4,0x26,0x22,0xA3,0xE3,0x62,0x00, +0x00,0x40,0x60,0x3F,0x3F,0x78,0x5F,0x57,0x58,0x4D,0x47,0x47,0x4D,0x58,0x50,0x40, +0x00,0x00,0xFE,0xFE,0x02,0xF2,0xF2,0x12,0x12,0xF2,0xF2,0x02,0xFE,0xFE,0x00,0x00, +0x00,0x00,0x7F,0x7F,0x20,0x27,0x27,0x24,0x24,0x27,0x27,0x20,0x7F,0x7F,0x00,0x00 +}; + +/*确认*/ +static unsigned char f_confirm[] = { +0x04,0x84,0xE4,0x5C,0x44,0xC4,0x20,0x10,0xE8,0x27,0x24,0xE4,0x34,0x2C,0xE0,0x00, +0x02,0x01,0x7F,0x10,0x10,0x3F,0x80,0x60,0x1F,0x09,0x09,0x3F,0x49,0x89,0x7F,0x00, +0x40,0x40,0x42,0xCC,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x3F,0x90,0x48,0x20,0x18,0x07,0x00,0x07,0x18,0x20,0x40,0x80,0x00 +}; + +/*确认*/ +static unsigned char f_confirm_EN[] = { +'C','o','n','f','i','r','m','?',0x00 +}; + +/*确认*/ +static unsigned char f_confirm_TC[] = { +0x04,0xE4,0x5C,0x44,0xC4,0x00,0x8C,0xE4,0x3C,0x27,0x2C,0xF4,0x24,0x24,0x2C,0x00, +0x01,0x3F,0x10,0x10,0x3F,0x01,0x00,0xFF,0x49,0x49,0x49,0x7F,0x49,0x49,0x49,0x00, +0x10,0x0C,0x44,0x44,0x44,0x44,0x45,0xC6,0x44,0x44,0x44,0x44,0x44,0x14,0x0C,0x00, +0x80,0x40,0x20,0x1E,0x20,0x40,0x40,0x7F,0x44,0x44,0x44,0x44,0x44,0x40,0x40,0x00 +}; + +/*开*/ +static unsigned char f_opened[] = { +0x80,0x82,0x82,0x82,0xFE,0x82,0x82,0x82,0x82,0x82,0xFE,0x82,0x82,0x82,0x80,0x00, +0x00,0x80,0x40,0x30,0x0F,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00 +}; + +/*开*/ +static unsigned char f_opened_EN[] = { +'O','p','e','n',0x00 +}; + +/*开*/ +static unsigned char f_opened_TC[] = { +0x00,0xFE,0x2A,0x2A,0xAA,0xBE,0x80,0x80,0xBE,0xAA,0x2A,0x2A,0xFE,0x00,0x00,0x00, +0x00,0xFF,0x00,0x44,0x24,0x1F,0x04,0x04,0x7F,0x04,0x44,0x80,0x7F,0x00,0x00,0x00 +}; + +/*关*/ +static unsigned char f_closed[] = { +0x80,0x82,0x82,0x82,0xFE,0x82,0x82,0x82,0x82,0x82,0xFE,0x82,0x82,0x82,0x80,0x00, +0x00,0x80,0x40,0x30,0x0F,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00 +}; + + +/*关*/ +static unsigned char f_closed_EN[] = { +'C','l','o','s','e',0x00 +}; + +/*关*/ +static unsigned char f_closed_TC[] = { +0x00,0xFF,0x15,0xD5,0xB5,0x9F,0x40,0x00,0xC0,0xBF,0x95,0x55,0x15,0xFF,0x00,0x00, +0x00,0xFF,0x00,0x1A,0x93,0x52,0x3F,0x00,0xFE,0x13,0x12,0x5B,0x80,0x7F,0x00,0x00 +}; + +/*无纸*/ +static unsigned char f_nopaper[] = { +0x00,0x40,0x42,0x42,0x42,0xC2,0x7E,0x42,0xC2,0x42,0x42,0x42,0x40,0x40,0x00,0x00, +0x80,0x40,0x20,0x10,0x0C,0x03,0x00,0x00,0x3F,0x40,0x40,0x40,0x40,0x70,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x20,0x30,0xAC,0x63,0x30,0x00,0xFC,0x84,0x84,0x84,0xFE,0x82,0x83,0x82,0x80,0x00, +0x22,0x67,0x22,0x12,0x12,0x00,0xFF,0x40,0x20,0x00,0x01,0x0E,0x30,0x40,0xF8,0x00 +}; + +/*无纸*/ +static unsigned char f_nopaper_EN[] = { +'N','o',' ','P','a','p','e','r',0x00 +}; + +/*无纸*/ +static unsigned char f_nopaper_TC[] = { +0x00,0x50,0x48,0x47,0xFC,0x44,0xFC,0x44,0xFC,0x44,0xFC,0x44,0x44,0x44,0x00,0x00, +0x80,0x44,0x34,0x04,0x07,0x14,0x67,0x04,0x17,0x64,0x07,0x04,0x14,0xE4,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x20,0x30,0xAC,0x63,0x20,0x18,0x00,0xFC,0x84,0x84,0x84,0xFE,0x82,0x83,0x82,0x00, +0x42,0x33,0x02,0x32,0x03,0x36,0x00,0xFF,0x40,0x20,0x00,0x07,0x38,0x40,0xF0,0x00 +}; + +/*休眠模式*/ +static unsigned char f_sleepmode[] = { +0x00,0x80,0x60,0xF8,0x07,0x10,0x10,0x10,0xD0,0xFF,0xD0,0x10,0x10,0x10,0x10,0x00, +0x01,0x00,0x00,0xFF,0x10,0x08,0x04,0x03,0x00,0xFF,0x00,0x03,0x04,0x08,0x10,0x00, +0x00,0xFC,0x24,0x24,0x24,0xFC,0x00,0xFE,0x22,0x22,0xE2,0x22,0x22,0x3E,0x00,0x00, +0x00,0x3F,0x11,0x11,0x11,0x3F,0x00,0xFF,0x41,0x21,0x07,0x19,0x21,0x41,0xF1,0x00, +0x10,0x10,0xD0,0xFF,0x90,0x14,0xE4,0xAF,0xA4,0xA4,0xA4,0xAF,0xE4,0x04,0x00,0x00, +0x04,0x03,0x00,0xFF,0x00,0x89,0x4B,0x2A,0x1A,0x0E,0x1A,0x2A,0x4B,0x88,0x80,0x00, +0x10,0x10,0x90,0x90,0x90,0x90,0x90,0x10,0x10,0xFF,0x10,0x10,0x11,0x16,0x10,0x00, +0x00,0x20,0x60,0x20,0x3F,0x10,0x10,0x10,0x00,0x03,0x0C,0x10,0x20,0x40,0xF8,0x00 +}; + + +/*休眠模式*/ +static unsigned char f_sleepmode_EN[] = { +'S','l','e','e','p',' ','M','o','d','e',0x00 +}; + + +/*休眠模式*/ +static unsigned char f_sleepmode_TC[] = { +0x00,0x80,0x60,0xF8,0x07,0x10,0x10,0x10,0xD0,0xFF,0xD0,0x10,0x10,0x10,0x10,0x00, +0x01,0x00,0x00,0xFF,0x10,0x08,0x04,0x03,0x00,0xFF,0x00,0x03,0x04,0x08,0x10,0x00, +0x00,0xFC,0x24,0x24,0x24,0xFC,0x00,0xFE,0x22,0x22,0xE2,0x22,0x22,0x3E,0x00,0x00, +0x00,0x3F,0x11,0x11,0x11,0x3F,0x00,0xFF,0x41,0x21,0x07,0x19,0x21,0x41,0xF1,0x00, +0x10,0x10,0xD0,0xFF,0x90,0x14,0xE4,0xAF,0xA4,0xA4,0xA4,0xAF,0xE4,0x04,0x00,0x00, +0x04,0x03,0x00,0xFF,0x00,0x89,0x4B,0x2A,0x1A,0x0E,0x1A,0x2A,0x4B,0x88,0x80,0x00, +0x10,0x10,0x90,0x90,0x90,0x90,0x90,0x10,0x10,0xFF,0x10,0x10,0x11,0x16,0x10,0x00, +0x00,0x20,0x60,0x20,0x3F,0x10,0x10,0x10,0x00,0x03,0x0C,0x10,0x20,0x40,0xF8,0x00 +}; + +/*三十分钟*/ +static unsigned char f_30min[] = { +0x00,0x04,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x04,0x00,0x00, +0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00, +0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xFF,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x80,0x40,0x20,0x90,0x88,0x86,0x80,0x80,0x80,0x83,0x8C,0x10,0x20,0x40,0x80,0x00, +0x00,0x80,0x40,0x20,0x18,0x07,0x00,0x40,0x80,0x40,0x3F,0x00,0x00,0x00,0x00,0x00, +0x20,0x10,0x2C,0xE7,0x24,0x24,0x00,0xF0,0x10,0x10,0xFF,0x10,0x10,0xF0,0x00,0x00, +0x01,0x01,0x01,0x7F,0x21,0x11,0x00,0x07,0x02,0x02,0xFF,0x02,0x02,0x07,0x00,0x00, +}; + +/*一小时*/ +static unsigned char f_1hour[] = { +0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x20,0x40,0x80,0x00,0x00, +0x08,0x04,0x03,0x00,0x00,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,0x01,0x0E,0x00, +0x00,0xFC,0x84,0x84,0x84,0xFC,0x00,0x10,0x10,0x10,0x10,0x10,0xFF,0x10,0x10,0x00, +0x00,0x3F,0x10,0x10,0x10,0x3F,0x00,0x00,0x01,0x06,0x40,0x80,0x7F,0x00,0x00,0x00 +}; + +/*二小时*/ +static unsigned char f_2hour[] = { +0x02,0xE2,0x22,0x22,0x22,0xFE,0x22,0x22,0x22,0xFE,0x22,0x22,0x22,0xE2,0x02,0x00, +0x00,0xFF,0x00,0x08,0x06,0x01,0x16,0x08,0x06,0x01,0x02,0x4C,0x80,0x7F,0x00,0x00, +0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x20,0x40,0x80,0x00,0x00, +0x08,0x04,0x03,0x00,0x00,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,0x01,0x0E,0x00, +0x00,0xFC,0x84,0x84,0x84,0xFC,0x00,0x10,0x10,0x10,0x10,0x10,0xFF,0x10,0x10,0x00, +0x00,0x3F,0x10,0x10,0x10,0x3F,0x00,0x00,0x01,0x06,0x40,0x80,0x7F,0x00,0x00,0x00 +}; + +/*不休眠*/ +static unsigned char f_never[] = { +0x00,0x02,0x02,0x02,0x02,0x82,0x42,0xF2,0x0E,0x42,0x82,0x02,0x02,0x02,0x00,0x00, +0x10,0x08,0x04,0x02,0x01,0x00,0x00,0xFF,0x00,0x00,0x00,0x01,0x02,0x0C,0x00,0x00, +0x00,0x80,0x60,0xF8,0x07,0x10,0x10,0x10,0xD0,0xFF,0xD0,0x10,0x10,0x10,0x10,0x00, +0x01,0x00,0x00,0xFF,0x10,0x08,0x04,0x03,0x00,0xFF,0x00,0x03,0x04,0x08,0x10,0x00, +0x00,0xFC,0x24,0x24,0x24,0xFC,0x00,0xFE,0x22,0x22,0xE2,0x22,0x22,0x3E,0x00,0x00, +0x00,0x3F,0x11,0x11,0x11,0x3F,0x00,0xFF,0x41,0x21,0x07,0x19,0x21,0x41,0xF1,0x00 +}; + +/*不休眠*/ +static unsigned char f_never_EN[] = { +'N','e','v','e','r',0x00 +}; + +/*不休眠*/ +static unsigned char f_never_TC[] = { +0x00,0x02,0x02,0x02,0x02,0x82,0x42,0xF2,0x0E,0x42,0x82,0x02,0x02,0x02,0x00,0x00, +0x10,0x08,0x04,0x02,0x01,0x00,0x00,0xFF,0x00,0x00,0x00,0x01,0x02,0x0C,0x00,0x00, +0x00,0x80,0x60,0xF8,0x07,0x10,0x10,0x10,0xD0,0xFF,0xD0,0x10,0x10,0x10,0x10,0x00, +0x01,0x00,0x00,0xFF,0x10,0x08,0x04,0x03,0x00,0xFF,0x00,0x03,0x04,0x08,0x10,0x00, +0x00,0xFC,0x24,0x24,0x24,0xFC,0x00,0xFE,0x22,0x22,0xE2,0x22,0x22,0x3E,0x00,0x00, +0x00,0x3F,0x11,0x11,0x11,0x3F,0x00,0xFF,0x41,0x21,0x07,0x19,0x21,0x41,0xF1,0x00 +}; + +/*返回*/ +static unsigned char f_return[] = { +0x40,0x40,0x42,0xCC,0x00,0x00,0xFC,0x24,0xA4,0x24,0x22,0x22,0xA3,0x62,0x00,0x00, +0x00,0x40,0x20,0x1F,0x20,0x58,0x47,0x50,0x48,0x45,0x42,0x45,0x48,0x50,0x40,0x00, +0x00,0x00,0xFE,0x02,0x02,0xF2,0x12,0x12,0x12,0xF2,0x02,0x02,0xFE,0x00,0x00,0x00, +0x00,0x00,0x7F,0x20,0x20,0x27,0x24,0x24,0x24,0x27,0x20,0x20,0x7F,0x00,0x00,0x00 +}; + +/*返回*/ +static unsigned char f_return_EN[] = { +'R','e','t','u','r','n',0x00 +}; + +/*返回*/ +static unsigned char f_return_TC[] = { +0x40,0x40,0x42,0xCC,0x00,0x00,0xFC,0x24,0xA4,0x24,0x22,0x22,0xA3,0x62,0x00,0x00, +0x00,0x40,0x20,0x1F,0x20,0x58,0x47,0x50,0x48,0x45,0x42,0x45,0x48,0x50,0x40,0x00, +0x00,0x00,0xFE,0x02,0x02,0xF2,0x12,0x12,0x12,0xF2,0x02,0x02,0xFE,0x00,0x00,0x00, +0x00,0x00,0x7F,0x20,0x20,0x27,0x24,0x24,0x24,0x27,0x20,0x20,0x7F,0x00,0x00,0x00 +}; + +/*关机*/ +static unsigned char f_powerof[] = { +0x00,0x00,0x10,0x11,0x16,0x10,0x10,0xF0,0x10,0x10,0x14,0x13,0x10,0x00,0x00,0x00, +0x81,0x81,0x41,0x41,0x21,0x11,0x0D,0x03,0x0D,0x11,0x21,0x41,0x41,0x81,0x81,0x00, +0x10,0x10,0xD0,0xFF,0x90,0x10,0x00,0xFE,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00, +0x04,0x03,0x00,0xFF,0x00,0x83,0x60,0x1F,0x00,0x00,0x00,0x3F,0x40,0x40,0x78,0x00 +}; + +/*关机*/ +static unsigned char f_powerof_EN[] = { +'P', 'o', 'w', 'e', 'r', ' ', 'O', 'F', 'F',0x00 +}; + +/*关机*/ +static unsigned char f_powerof_TC[] = { +0x00,0xFF,0x15,0xD5,0xB5,0x9F,0x40,0x00,0xC0,0xBF,0x95,0x55,0x15,0xFF,0x00,0x00, +0x00,0xFF,0x00,0x1A,0x93,0x52,0x3F,0x00,0xFE,0x13,0x12,0x5B,0x80,0x7F,0x00,0x00, +0x10,0x10,0xD0,0xFF,0x90,0x00,0x6C,0xDB,0x6C,0x00,0xFF,0x00,0x6C,0xDB,0x6C,0x00, +0x04,0x03,0x00,0xFF,0x00,0x81,0x71,0x0F,0x11,0x21,0x81,0x4F,0x31,0x4D,0xF1,0x00 +}; + + +/*托盘位置*/ +static unsigned char f_trayposition[] = { +0x10,0x10,0x10,0xFF,0x10,0x90,0x04,0x04,0x04,0xFC,0x82,0x82,0x83,0x82,0x80,0x00, +0x04,0x44,0x82,0x7F,0x01,0x00,0x01,0x01,0x01,0x3F,0x40,0x40,0x40,0x40,0x78,0x00, +0x20,0x20,0x20,0xFC,0x24,0x26,0xA5,0x2C,0x34,0x24,0x24,0xFC,0x20,0x20,0x20,0x00, +0x40,0x42,0x7D,0x44,0x44,0x7C,0x44,0x45,0x44,0x7D,0x46,0x45,0x7C,0x40,0x40,0x00, +0x00,0x80,0x60,0xF8,0x07,0x10,0x90,0x10,0x11,0x16,0x10,0x10,0xD0,0x10,0x00,0x00, +0x01,0x00,0x00,0xFF,0x40,0x40,0x41,0x5E,0x40,0x40,0x70,0x4E,0x41,0x40,0x40,0x00, +0x00,0x17,0x15,0xD5,0x55,0x57,0x55,0x7D,0x55,0x57,0x55,0xD5,0x15,0x17,0x00,0x00, +0x40,0x40,0x40,0x7F,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x7F,0x40,0x40,0x40,0x00 +}; + +/*托盘位置*/ +static unsigned char f_trayposition_EN[] = { +'T','r','a','y',' ','P','o','s','i','t','i','o','n',0x00 +}; + +/*托盘位置*/ +static unsigned char f_trayposition_TC[] = { +0x10,0x10,0x10,0xFF,0x10,0x90,0x04,0x04,0x04,0xFC,0x82,0x82,0x83,0x82,0x80,0x00, +0x04,0x44,0x82,0x7F,0x01,0x00,0x01,0x01,0x01,0x3F,0x40,0x40,0x40,0x40,0x78,0x00, +0x10,0x90,0x7E,0x13,0x5A,0x12,0xFE,0x10,0x08,0x37,0x51,0x91,0x77,0x08,0x08,0x00, +0x42,0x41,0x7C,0x44,0x45,0x7E,0x45,0x44,0x44,0x7E,0x45,0x44,0x7D,0x42,0x42,0x00, +0x00,0x80,0x60,0xF8,0x07,0x10,0x90,0x10,0x11,0x16,0x10,0x10,0xD0,0x10,0x00,0x00, +0x01,0x00,0x00,0xFF,0x40,0x40,0x41,0x5E,0x40,0x40,0x70,0x4E,0x41,0x40,0x40,0x00, +0x00,0x17,0x15,0xD5,0x55,0x57,0x55,0x7D,0x55,0x57,0x55,0xD5,0x15,0x17,0x00,0x00, +0x40,0x40,0x40,0x7F,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x7F,0x40,0x40,0x40,0x00 +}; + +/*设备已锁定*/ +static unsigned char f_deviceLock[] = { +0x40,0x40,0x42,0xCC,0x00,0x40,0xA0,0x9E,0x82,0x82,0x82,0x9E,0xA0,0x20,0x20,0x00, +0x00,0x00,0x00,0x3F,0x90,0x88,0x40,0x43,0x2C,0x10,0x28,0x46,0x41,0x80,0x80,0x00,/*"设",0*/ +0x80,0x90,0x90,0x48,0x4C,0x57,0x24,0x24,0x24,0x54,0x4C,0x44,0x80,0x80,0x80,0x00, +0x00,0x00,0x00,0xFF,0x49,0x49,0x49,0x7F,0x49,0x49,0x49,0xFF,0x00,0x00,0x00,0x00,/*"备",1*/ +0x00,0x00,0xE2,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE,0x00,0x00,0x00,0x00, +0x00,0x00,0x3F,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x78,0x00,0x00,/*"已",2*/ +0x20,0x10,0x2C,0xE7,0x24,0x24,0x00,0xE2,0x2C,0x20,0xBF,0x20,0x28,0xE6,0x00,0x00, +0x01,0x01,0x01,0x7F,0x21,0x11,0x80,0x4F,0x20,0x10,0x0F,0x10,0x20,0x4F,0x80,0x00,/*"锁",3*/ +0x10,0x0C,0x44,0x44,0x44,0x44,0x45,0xC6,0x44,0x44,0x44,0x44,0x44,0x14,0x0C,0x00, +0x80,0x40,0x20,0x1E,0x20,0x40,0x40,0x7F,0x44,0x44,0x44,0x44,0x44,0x40,0x40,0x00,/*"定",4*/ +}; + +/*设备已锁定*/ +static unsigned char f_deviceLock_EN[] = { +'D','e','v','i','c','e',' ','L','o','c','k','e','d',0x00 +}; + +/*设备已锁定*/ +static unsigned char f_deviceLock_TC[] = { +0x08,0xA8,0xA9,0xAE,0xA8,0xA8,0x48,0xA0,0x9E,0x82,0x82,0x82,0x9E,0xA0,0x20,0x00, +0x00,0x7E,0x22,0x22,0x22,0x7E,0x80,0x80,0x43,0x2C,0x10,0x28,0x44,0x83,0x80,0x00, +0x00,0x80,0x60,0xF8,0x07,0x20,0x24,0xA4,0xFF,0xA4,0xA4,0xA4,0xBF,0xA4,0x24,0x00, +0x01,0x00,0x00,0xFF,0x00,0x02,0x01,0xFF,0x0A,0x0A,0x7F,0x0A,0x8A,0xFF,0x00,0x00, +0x00,0x00,0xE2,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE,0x00,0x00,0x00,0x00, +0x00,0x00,0x3F,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x78,0x00,0x00, +0x20,0x10,0x2C,0xE3,0x24,0x08,0x00,0xF2,0x94,0x90,0x9F,0x90,0x94,0xF2,0x00,0x00, +0x45,0xD9,0x41,0x3F,0x29,0x25,0x00,0x9F,0x52,0x12,0x12,0x12,0x52,0x9F,0x00,0x00, +0x10,0x0C,0x44,0x44,0x44,0x44,0x45,0xC6,0x44,0x44,0x44,0x44,0x44,0x14,0x0C,0x00, +0x80,0x40,0x20,0x1E,0x20,0x40,0x40,0x7F,0x44,0x44,0x44,0x44,0x44,0x40,0x40,0x00 +}; + + +/*耗材查询*/ +static unsigned char f_scannum[] ={ +0x88,0xA8,0xA8,0xFF,0xA8,0xA8,0x88,0x00,0x44,0x44,0xFC,0x22,0x23,0x22,0x00,0x00, +0x20,0x18,0x06,0xFF,0x02,0x0C,0x00,0x04,0x04,0x04,0x7F,0x82,0x82,0x82,0xF2,0x00,/*"耗",0*/ +0x10,0x10,0x10,0xD0,0xFF,0x90,0x10,0x00,0x10,0x10,0x10,0xD0,0xFF,0x10,0x10,0x00, +0x08,0x04,0x03,0x00,0xFF,0x00,0x03,0x00,0x08,0x04,0x43,0x80,0x7F,0x00,0x00,0x00,/*"材",1*/ +0x40,0x44,0x24,0xA4,0x94,0x8C,0x84,0xFF,0x84,0x8C,0x94,0xA4,0x24,0x44,0x40,0x00, +0x40,0x40,0x40,0x5F,0x4A,0x4A,0x4A,0x4A,0x4A,0x4A,0x4A,0x5F,0x40,0x40,0x40,0x00,/*"查",2*/ +0x40,0x40,0x42,0xCC,0x00,0x20,0xD0,0x4C,0x4B,0x48,0xC8,0x08,0x08,0xF8,0x00,0x00, +0x00,0x00,0x00,0x7F,0x20,0x10,0x1F,0x12,0x12,0x12,0x5F,0x80,0x40,0x3F,0x00,0x00,/*"询",3*/ +}; + +/*耗材查询*/ +static unsigned char f_scannum_EN[] ={ +'Q','u','e','r','y',0x00 +}; + + +/*耗材查询*/ +static unsigned char f_scannum_TC[] ={ +0x88,0xA8,0xA8,0xFF,0xA8,0xA8,0x88,0x00,0x44,0x44,0xFC,0x22,0x23,0x22,0x00,0x00, +0x20,0x18,0x06,0xFF,0x02,0x0C,0x00,0x04,0x04,0x04,0x7F,0x82,0x82,0x82,0xF2,0x00, +0x10,0x10,0x10,0xD0,0xFF,0x90,0x10,0x00,0x10,0x10,0x10,0xD0,0xFF,0x10,0x10,0x00, +0x08,0x04,0x03,0x00,0xFF,0x00,0x03,0x00,0x08,0x04,0x43,0x80,0x7F,0x00,0x00,0x00, +0x40,0x44,0x24,0xA4,0x94,0x8C,0x84,0xFF,0x84,0x8C,0x94,0xA4,0x24,0x44,0x40,0x00, +0x40,0x40,0x40,0x5F,0x4A,0x4A,0x4A,0x4A,0x4A,0x4A,0x4A,0x5F,0x40,0x40,0x40,0x00, +0x08,0xA8,0xA9,0xAA,0xA8,0x08,0x10,0xEC,0x27,0x24,0xE4,0x04,0x04,0xFC,0x00,0x00, +0x00,0x7E,0x22,0x22,0x7E,0x00,0x00,0x1F,0x09,0x09,0x4F,0x80,0x40,0x3F,0x00,0x00 +}; + +/*历史张数*/ +static unsigned char f_history_num[] ={ +0x00,0x00,0xFE,0x02,0x42,0x42,0x42,0x42,0xFA,0x42,0x42,0x42,0x42,0xC2,0x02,0x00, +0x80,0x60,0x1F,0x80,0x40,0x20,0x18,0x06,0x01,0x00,0x40,0x80,0x40,0x3F,0x00,0x00,/*"历",0*/ +0x00,0x00,0xF8,0x88,0x88,0x88,0x88,0xFF,0x88,0x88,0x88,0x88,0xF8,0x00,0x00,0x00, +0x80,0x80,0x81,0x44,0x48,0x30,0x10,0x2F,0x20,0x40,0x40,0x40,0x81,0x80,0x80,0x00,/*"史",1*/ +0x02,0xE2,0x22,0x22,0x3E,0x80,0x80,0xFF,0x80,0xA0,0x90,0x88,0x86,0x80,0x80,0x00, +0x00,0x43,0x82,0x42,0x3E,0x00,0x00,0xFF,0x40,0x21,0x06,0x08,0x10,0x20,0x40,0x00,/*"张",2*/ +0x90,0x52,0x34,0x10,0xFF,0x10,0x34,0x52,0x80,0x70,0x8F,0x08,0x08,0xF8,0x08,0x00, +0x82,0x9A,0x56,0x63,0x22,0x52,0x8E,0x00,0x80,0x40,0x33,0x0C,0x33,0x40,0x80,0x00/*"数",3*/ +}; + +/*历史张数*/ +static unsigned char f_history_num_EN[] ={ +'H','i','s','t',' ','C','t','.',0x00 +}; + +/*历史张数*/ +static unsigned char f_history_num_TC[] ={ +0x00,0x00,0xFF,0x29,0xA9,0xF9,0xA5,0x25,0x01,0x29,0xA9,0xF9,0xA5,0x25,0x21,0x00, +0x40,0x30,0x4F,0x41,0x40,0x7B,0x40,0x41,0x7E,0x49,0x48,0x4B,0x48,0x41,0x42,0x00, +0x00,0x00,0xF8,0x88,0x88,0x88,0x88,0xFF,0x88,0x88,0x88,0x88,0xF8,0x00,0x00,0x00, +0x80,0x80,0x81,0x44,0x48,0x30,0x10,0x2F,0x20,0x40,0x40,0x40,0x81,0x80,0x80,0x00, +0x02,0xE2,0x22,0x22,0x3E,0x80,0x80,0x80,0xFE,0xAA,0xAA,0xAA,0xAA,0x82,0x80,0x00, +0x00,0x43,0x82,0x42,0x3E,0x00,0x00,0xFF,0x40,0x21,0x06,0x08,0x14,0x22,0x40,0x00, +0x08,0xBE,0xAA,0xAA,0xFF,0xAA,0xAA,0xBE,0x08,0x20,0xD8,0x17,0x10,0xF0,0x10,0x00, +0x88,0xAB,0xBA,0xAE,0x4B,0x4A,0xAA,0x9B,0x80,0x40,0x37,0x08,0x36,0x41,0x80,0x00 +}; + +/*滚轴张数*/ +static unsigned char f_roller_num[] ={ +0x10,0x60,0x02,0x8C,0x00,0x24,0x94,0xCC,0xA5,0x96,0xC4,0x8C,0x14,0x24,0x00,0x00, +0x04,0x04,0x7E,0x01,0x20,0x10,0x08,0xFC,0x42,0x24,0x08,0x15,0x22,0x40,0x40,0x00,/*"滚",0*/ +0xC8,0xB8,0x8F,0xE8,0x88,0x88,0x00,0xF0,0x10,0x10,0xFF,0x10,0x10,0xF0,0x00,0x00, +0x08,0x18,0x08,0xFF,0x04,0x04,0x00,0xFF,0x42,0x42,0x7F,0x42,0x42,0xFF,0x00,0x00,/*"轴",1*/ +0x02,0xE2,0x22,0x22,0x3E,0x80,0x80,0xFF,0x80,0xA0,0x90,0x88,0x86,0x80,0x80,0x00, +0x00,0x43,0x82,0x42,0x3E,0x00,0x00,0xFF,0x40,0x21,0x06,0x08,0x10,0x20,0x40,0x00,/*"张",2*/ +0x90,0x52,0x34,0x10,0xFF,0x10,0x34,0x52,0x80,0x70,0x8F,0x08,0x08,0xF8,0x08,0x00, +0x82,0x9A,0x56,0x63,0x22,0x52,0x8E,0x00,0x80,0x40,0x33,0x0C,0x33,0x40,0x80,0x00/*"数",3*/ +}; + +/*滚轴张数*/ +static unsigned char f_roller_num_EN[] ={ +'R','o','l','l','e','r',' ','C','t','.',0x00 +}; + +/*滚轴张数*/ +static unsigned char f_roller_num_TC[] ={ +0x10,0x60,0x02,0x8C,0x00,0x24,0x14,0xEC,0x25,0x26,0x24,0xEC,0x14,0x24,0x00,0x00, +0x04,0x04,0x7E,0x01,0x20,0x10,0x08,0xFD,0x43,0x25,0x09,0x15,0x22,0x40,0x40,0x00, +0x08,0xE8,0xA8,0xFF,0xA8,0xE8,0x08,0xF0,0x10,0x10,0xFF,0x10,0x10,0xF0,0x00,0x00, +0x08,0x0B,0x0A,0xFF,0x0A,0x0B,0x08,0xFF,0x42,0x42,0x7F,0x42,0x42,0xFF,0x00,0x00, +0x08,0xA8,0xA9,0xAE,0xA8,0xA8,0x48,0x40,0x40,0x40,0xFF,0x40,0x40,0x40,0x40,0x00, +0x00,0x7E,0x22,0x22,0x22,0x7E,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00, +0x08,0xBE,0xAA,0xAA,0xFF,0xAA,0xAA,0xBE,0x08,0x20,0xD8,0x17,0x10,0xF0,0x10,0x00, +0x88,0xAB,0xBA,0xAE,0x4B,0x4A,0xAA,0x9B,0x80,0x40,0x37,0x08,0x36,0x41,0x80,0x00 +}; + +/*滚轴清零*/ +static unsigned char f_clrea_roller[] ={ +0x10,0x60,0x02,0x8C,0x00,0x24,0x94,0xCC,0xA5,0x96,0xC4,0x8C,0x14,0x24,0x00,0x00, +0x04,0x04,0x7E,0x01,0x20,0x10,0x08,0xFC,0x42,0x24,0x08,0x15,0x22,0x40,0x40,0x00,/*"滚",0*/ +0xC8,0xB8,0x8F,0xE8,0x88,0x88,0x00,0xF0,0x10,0x10,0xFF,0x10,0x10,0xF0,0x00,0x00, +0x08,0x18,0x08,0xFF,0x04,0x04,0x00,0xFF,0x42,0x42,0x7F,0x42,0x42,0xFF,0x00,0x00,/*"轴",1*/ +0x10,0x60,0x02,0x8C,0x00,0x44,0x54,0x54,0x54,0x7F,0x54,0x54,0x54,0x44,0x40,0x00, +0x04,0x04,0x7E,0x01,0x00,0x00,0xFF,0x15,0x15,0x15,0x55,0x95,0x7F,0x00,0x00,0x00,/*"清",2*/ +0x10,0x0C,0x05,0x55,0x55,0x55,0x85,0x7F,0x85,0x55,0x55,0x55,0x05,0x14,0x0C,0x00, +0x04,0x04,0x02,0x0A,0x09,0x29,0x2A,0x4C,0x48,0xA9,0x19,0x02,0x02,0x04,0x04,0x00,/*"零",3*/ +}; + +/*滚轴清零*/ +static unsigned char f_clrea_roller_EN[] ={ +'R','e','s','e','t',' ','C','o','u','n','t','e','r',0x00 +}; + +/*滚轴清零*/ +static unsigned char f_clrea_roller_TC[] ={ +0x10,0x60,0x02,0x8C,0x00,0x24,0x14,0xEC,0x25,0x26,0x24,0xEC,0x14,0x24,0x00,0x00, +0x04,0x04,0x7E,0x01,0x20,0x10,0x08,0xFD,0x43,0x25,0x09,0x15,0x22,0x40,0x40,0x00, +0x08,0xE8,0xA8,0xFF,0xA8,0xE8,0x08,0xF0,0x10,0x10,0xFF,0x10,0x10,0xF0,0x00,0x00, +0x08,0x0B,0x0A,0xFF,0x0A,0x0B,0x08,0xFF,0x42,0x42,0x7F,0x42,0x42,0xFF,0x00,0x00, +0x10,0x60,0x02,0x8C,0x00,0x44,0x54,0x54,0x54,0x7F,0x54,0x54,0x54,0x44,0x40,0x00, +0x04,0x04,0x7E,0x01,0x00,0x00,0xFF,0x15,0x15,0x15,0x55,0x95,0x7F,0x00,0x00,0x00, +0x10,0x0C,0x05,0x55,0x55,0x55,0x85,0x7F,0x85,0x55,0x55,0x55,0x05,0x14,0x0C,0x00, +0x04,0x04,0x02,0x0A,0x09,0x29,0x2A,0x4C,0x48,0xA9,0x19,0x02,0x02,0x04,0x04,0x00 +}; + +/*是否确认?*/ +static unsigned char f_is_sure[] ={ +0x00,0x00,0x00,0x7F,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x7F,0x00,0x00,0x00,0x00, +0x81,0x41,0x21,0x1D,0x21,0x41,0x81,0xFF,0x89,0x89,0x89,0x89,0x89,0x81,0x81,0x00,/*"是",0*/ +0x00,0x02,0x82,0x82,0x42,0x22,0x12,0xFA,0x06,0x22,0x22,0x42,0x42,0x82,0x00,0x00, +0x01,0x01,0x00,0xFC,0x44,0x44,0x44,0x45,0x44,0x44,0x44,0xFC,0x00,0x00,0x01,0x00,/*"否",1*/ +0x04,0x84,0xE4,0x5C,0x44,0xC4,0x20,0x10,0xE8,0x27,0x24,0xE4,0x34,0x2C,0xE0,0x00, +0x02,0x01,0x7F,0x10,0x10,0x3F,0x80,0x60,0x1F,0x09,0x09,0x3F,0x49,0x89,0x7F,0x00,/*"确",2*/ +0x40,0x40,0x42,0xCC,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x3F,0x90,0x48,0x20,0x18,0x07,0x00,0x07,0x18,0x20,0x40,0x80,0x00,/*"认",3*/ +0x00,0x00,0x38,0x34,0x02,0x82,0xC2,0x7C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x37,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"?",4*/ +}; + +/*是否确认?*/ +static unsigned char f_is_sure_EN[] ={ +'C','o','n','f','i','r','m','?',0x00 +}; + +/*是否确认?*/ +static unsigned char f_is_sure_TC[] ={ +0x00,0x00,0x00,0x7F,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x7F,0x00,0x00,0x00,0x00, +0x81,0x41,0x21,0x1D,0x21,0x41,0x81,0xFF,0x89,0x89,0x89,0x89,0x89,0x81,0x81,0x00, +0x00,0x02,0x82,0x82,0x42,0x22,0x12,0xFA,0x06,0x22,0x22,0x42,0x42,0x82,0x00,0x00, +0x01,0x01,0x00,0xFC,0x44,0x44,0x44,0x45,0x44,0x44,0x44,0xFC,0x00,0x00,0x01,0x00, +0x04,0xE4,0x5C,0x44,0xC4,0x00,0x8C,0xE4,0x3C,0x27,0x2C,0xF4,0x24,0x24,0x2C,0x00, +0x01,0x3F,0x10,0x10,0x3F,0x01,0x00,0xFF,0x49,0x49,0x49,0x7F,0x49,0x49,0x49,0x00, +0x08,0xA8,0xA9,0xAA,0xA8,0x08,0x22,0x9A,0x62,0x1E,0x02,0x42,0x82,0x7E,0x00,0x00, +0x00,0x7E,0x22,0x22,0x3E,0x40,0x39,0x00,0x3C,0x41,0x46,0x40,0x70,0x04,0x38,0x00, +0x00,0x00,0x38,0x34,0x02,0x82,0xC2,0x7C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x37,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +}; + +/*"是"*/ +static unsigned char f_yes[] ={ +0x00,0x00,0x00,0x7F,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x7F,0x00,0x00,0x00,0x00, +0x81,0x41,0x21,0x1D,0x21,0x41,0x81,0xFF,0x89,0x89,0x89,0x89,0x89,0x81,0x81,0x00,/*"是",0*/ +}; + +/*"是"*/ +static unsigned char f_yes_EN[] ={ +'Y','e','s',0x00 +}; + +/*"是"*/ +static unsigned char f_yes_TC[] ={ +0x00,0x00,0x00,0x7F,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x7F,0x00,0x00,0x00,0x00, +0x81,0x41,0x21,0x1D,0x21,0x41,0x81,0xFF,0x89,0x89,0x89,0x89,0x89,0x81,0x81,0x00,/*"是",0*/ +}; + +/*"否"*/ +static unsigned char f_no[] ={ +0x00,0x02,0x82,0x82,0x42,0x22,0x12,0xFA,0x06,0x22,0x22,0x42,0x42,0x82,0x00,0x00, +0x01,0x01,0x00,0xFC,0x44,0x44,0x44,0x45,0x44,0x44,0x44,0xFC,0x00,0x00,0x01,0x00,/*"否",1*/ +}; + + +/*"否"*/ +static unsigned char f_no_EN[] ={ +'N','o',0x00 +}; + + +/*"否"*/ +static unsigned char f_no_TC[] ={ +0x00,0x02,0x82,0x82,0x42,0x22,0x12,0xFA,0x06,0x22,0x22,0x42,0x42,0x82,0x00,0x00, +0x01,0x01,0x00,0xFC,0x44,0x44,0x44,0x45,0x44,0x44,0x44,0xFC,0x00,0x00,0x01,0x00,/*"否",1*/ +}; + +/*"语言"*/ +static unsigned char f_language[]={ +0x40,0x42,0xCC,0x00,0x00,0x82,0x92,0x92,0xF2,0x9E,0x92,0x92,0xF2,0x82,0x80,0x00, +0x00,0x00,0x7F,0x20,0x10,0x00,0xFC,0x44,0x44,0x44,0x44,0x44,0xFC,0x00,0x00,0x00,/*"语",0*/ +0x04,0x04,0x24,0x24,0x24,0x24,0x25,0x26,0x24,0x24,0x24,0x24,0x24,0x04,0x04,0x00, +0x00,0x00,0xF9,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0xF9,0x00,0x00,0x00,/*"言",1*/ +}; + +/*"语言"*/ +static unsigned char f_language_EN[]={ +'L','a','n','g','u','a','g','e',0x00 +}; + +/*"語言"*/ +static unsigned char f_language_TC[]={ +0x08,0xA8,0xA9,0xAA,0xA8,0x08,0x82,0x92,0xF2,0x9E,0x92,0x92,0xF2,0x82,0x80,0x00, +0x00,0x7E,0x22,0x22,0x7E,0x00,0x00,0xFC,0x44,0x44,0x44,0x44,0xFC,0x00,0x00,0x00,/*"語",0*/ +0x04,0x04,0x24,0x24,0x24,0x24,0x25,0x26,0x24,0x24,0x24,0x24,0x24,0x04,0x04,0x00, +0x00,0x00,0xF9,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0xF9,0x00,0x00,0x00,/*"言",1*/ +}; + +/*"简体中文"*/ +static unsigned char f_language_chinese[]={ +0x08,0x04,0xC3,0x12,0x26,0x8A,0xA2,0xAA,0xA4,0xA3,0x22,0x26,0xEA,0x02,0x02,0x00, +0x00,0x00,0xFF,0x00,0x00,0x3F,0x24,0x24,0x24,0x3F,0x00,0x80,0xFF,0x00,0x00,0x00,/*"简",0*/ +0x00,0x80,0x60,0xF8,0x07,0x10,0x10,0x10,0xD0,0xFF,0xD0,0x10,0x10,0x10,0x00,0x00, +0x01,0x00,0x00,0xFF,0x10,0x08,0x04,0x0B,0x08,0xFF,0x08,0x0B,0x04,0x08,0x10,0x00,/*"体",1*/ +0x00,0x00,0xF0,0x10,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x10,0xF0,0x00,0x00,0x00, +0x00,0x00,0x0F,0x04,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x0F,0x00,0x00,0x00,/*"中",2*/ +0x08,0x08,0x08,0x38,0xC8,0x08,0x09,0x0E,0x08,0x08,0xC8,0x38,0x08,0x08,0x08,0x00, +0x80,0x80,0x40,0x40,0x20,0x11,0x0A,0x04,0x0A,0x11,0x20,0x40,0x40,0x80,0x80,0x00,/*"文",3*/ +}; + +/*"english"*/ +static unsigned char f_language_english[]={ +'E','n','g','L','i','s','h',0x00 +}; + +/*"繁體中文"*/ +static unsigned char f_language_chinese_traditional[]={ +0x28,0xE4,0xBB,0xAA,0xFA,0xAA,0xFA,0xA2,0x10,0x08,0xB7,0x44,0xBC,0x04,0x04,0x00, +0x00,0x00,0x90,0x54,0x16,0x55,0x9C,0x74,0x12,0x11,0x50,0x98,0x30,0x01,0x01,0x00,/*"繁",0*/ +0x60,0xBE,0xAA,0xBA,0xA2,0xBE,0x60,0xBE,0xAA,0xBF,0xAA,0xBF,0xAA,0xBE,0x00,0x00, +0x00,0xFF,0x0A,0x4A,0x8A,0x7F,0x40,0x4E,0x5A,0x6A,0x4A,0x6A,0x5A,0x4E,0x40,0x00,/*"體",1*/ +0x00,0x00,0xF0,0x10,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x10,0xF0,0x00,0x00,0x00, +0x00,0x00,0x0F,0x04,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x0F,0x00,0x00,0x00,/*"中",2*/ +0x08,0x08,0x08,0x38,0xC8,0x08,0x09,0x0E,0x08,0x08,0xC8,0x38,0x08,0x08,0x08,0x00, +0x80,0x80,0x40,0x40,0x20,0x11,0x0A,0x04,0x0A,0x11,0x20,0x40,0x40,0x80,0x80,0x00,/*"文",3*/ +}; + +static unsigned char f_null[] ={ +0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00, +0x00,0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00, +0x00,0x70,0x08,0x08,0x08,0x08,0xF0,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00, +0x00,0x30,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x18,0x20,0x21,0x21,0x22,0x1C,0x00, +0x00,0x00,0x80,0x40,0x30,0xF8,0x00,0x00,0x00,0x06,0x05,0x24,0x24,0x3F,0x24,0x24, +0x00,0xF8,0x88,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x20,0x20,0x20,0x11,0x0E,0x00, +0x00,0xE0,0x10,0x88,0x88,0x90,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x20,0x1F,0x00, +0x00,0x18,0x08,0x08,0x88,0x68,0x18,0x00,0x00,0x00,0x00,0x3E,0x01,0x00,0x00,0x00, +0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00, +0x00,0xF0,0x08,0x08,0x08,0x10,0xE0,0x00,0x00,0x01,0x12,0x22,0x22,0x11,0x0F,0x00, +0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x19,0x24,0x24,0x12,0x3F,0x20,0x00, +0x10,0xF0,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00, +0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00, +0x00,0x00,0x80,0x80,0x80,0x90,0xF0,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20, +0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x24,0x24,0x24,0x24,0x17,0x00, +0x00,0x80,0x80,0xE0,0x90,0x90,0x20,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00 +}; + diff --git a/display/LCDDisplay.cpp b/display/LCDDisplay.cpp new file mode 100644 index 0000000..f6eb7aa --- /dev/null +++ b/display/LCDDisplay.cpp @@ -0,0 +1,189 @@ +#include "LCDDisplay.h" +#include "Lcd.h" +#include +#include +#include +#include "stringex.hpp" +#include + +using namespace std; + +LCDDisplay::LCDDisplay(int language) +{ + if(language >=0 && language < 3) + m_language = (LCDDisplay::Language)language; + else + m_language = LCDDisplay::Language::Chinese; + lcd.reset(new Lcd()); + lcd->Lcd_Initial_Lcd(false); + map_Display = {map_Display_CN,map_Display_TC,map_Display_EN}; + // lcd->Lcd_Clear_screen(); + // lcd->Lcd_Display_Graphic_16x16(map_Display[DisType::Dis_Init].page, map_Display[DisType::Dis_Init].col, map_Display[DisType::Dis_Init].str.data(),map_Display[DisType::Dis_Init].str.size()/32); +} + +LCDDisplay::~LCDDisplay() +{ + lcd->Lcd_Clear_screen(); + lcd.reset(); +} + +void LCDDisplay::DisplayState(DisType ds, unsigned int pagenum,ClearScreen clearscree) +{ + if(clearscree == ClearScreen::All) + lcd->Lcd_Clear_screen(); + if(clearscree == ClearScreen::TOP) + lcd->Lcd_Clear_Half_Screen(true); + if(clearscree == ClearScreen::BOT) + lcd->Lcd_Clear_Half_Screen(false); + if (map_Display[m_language_map[m_language]].count(ds) > 0) + { + m_status = ds; + StopWatch sw; + auto dsinfo = map_Display[m_language_map[m_language]][ds]; + if (ds == DisType::Dis_Welcome)//show logo + { + lcd->Lcd_Display_Graphic_128x64(dsinfo.page, dsinfo.col, dsinfo.str.data()); + } + else if(ds == DisType::Dis_Language_Chinese || ds == DisType::Dis_Language_Chinese_Traditional) + { + lcd->Lcd_Display_Graphic_16x16(dsinfo.page, dsinfo.col, dsinfo.str.data(), dsinfo.str.size() / 32); + } + else if(ds == DisType::Dis_Language_English) + lcd->Lcd_Display_String_8x16(dsinfo.page, dsinfo.col, (const char*)dsinfo.str.data()); + else + { + if(m_language == Language::English) + lcd->Lcd_Display_String_8x16(dsinfo.page, dsinfo.col, (const char*)dsinfo.str.data()); + else + lcd->Lcd_Display_Graphic_16x16(dsinfo.page, dsinfo.col, dsinfo.str.data(), dsinfo.str.size() / 32); + //lcd->Lcd_Display_String_8x16(dsinfo.page, dsinfo.col, (const char*)dsinfo.str.data()); + //if (ds == DisType::Dis_Scan || ds == DisType::Dis_Set_Count) //扫描或者计数 更新下半部分内容 + //{ + //lcd->Lcd_Clear_Half_Screen(false); + //lcd->Lcd_Display_String_8x16(3, 96, "0"); + //lcd->Lcd_Display_Graphic_16x16(map_Display[DisType::Dis_Scan_Page].page, map_Display[DisType::Dis_Scan_Page].col, map_Display[DisType::Dis_Scan_Page].str.data(), map_Display[DisType::Dis_Scan_Page].str.size() / 32); + //} + } + + switch (ds) + { + case DisType::Dis_Count_Page: + case DisType::Dis_Scan_Page: + { + //std::string val = std::to_string(pagenum); + //auto offsetdot = bitnum(pagenum) - 1; + std::string val = string_format("%04d",pagenum); + int offsetdot = val.length(); + //printf("\n val = %s lenght = %d",val.c_str(),val.size()); + lcd->Lcd_Display_String_8x16(3, 112 - offsetdot * 8, val.c_str()); //8 -> 一个数字所占点个数宽度 + lcd->Lcd_Display_Graphic_16x16(map_Display[m_language_map[m_language]][DisType::Dis_Scan_Page].page, map_Display[m_language_map[m_language]][DisType::Dis_Scan_Page].col, + map_Display[m_language_map[m_language]][DisType::Dis_Scan_Page].str.data(), map_Display[m_language_map[m_language]][DisType::Dis_Scan_Page].str.size() / 32); + break; + } + case DisType::Dis_Err_JamIn: + { + if(pagenum == 1) + lcd->Lcd_Display_String_8x16(3, 56, "P a 1 0 1"); //8 -> 一个数字所占点个数宽度 + else if(pagenum == 2) + lcd->Lcd_Display_String_8x16(3, 56, "P a 1 0 2"); + else if(pagenum == 3) + lcd->Lcd_Display_String_8x16(3, 56, "P a 1 0 3"); + break; + } + case DisType::Dis_Err_AqrImgTimeout: + lcd->Lcd_Display_String_8x16(3, 56, "G p 0 0 1"); + break; + case DisType::Dis_Err_CoverOpen: + lcd->Lcd_Display_String_8x16(3, 56, "C o 0 0 1"); + break; + case DisType::Dis_Err_PaperScrew: + lcd->Lcd_Display_String_8x16(3, 56, "S K 0 0 1"); + break; + case DisType::Dis_Err_DoubleFeed: + lcd->Lcd_Display_String_8x16(3, 56, "D b 0 0 1"); + break; + case DisType::Dis_Err_NoPaper: + lcd->Lcd_Display_String_8x16(3, 56, "N o 0 0 1"); + break; + case DisType::Dis_Err_Stable: + lcd->Lcd_Display_String_8x16(3, 56, "S T 0 0 1"); + break; + case DisType::Dis_Err_FeedError: + lcd->Lcd_Display_String_8x16(3, 56, "P f 0 0 1"); + break; + case DisType::Dis_Err_DogEar: + lcd->Lcd_Display_String_8x16(3, 56, "Z J 0 0 1"); + break; + case DisType::Dis_Err_Size: + lcd->Lcd_Display_String_8x16(3, 56, "C C 0 0 1"); + break; + case DisType::Dis_Set_Get_History_ScanNum: + { + std::string val = std::to_string(pagenum); + int offsetdot = 8 > val.length() ? val.length() : 8; + lcd->Lcd_Display_String_8x16(3, 128 - offsetdot * 8, val.c_str()); //8 -> 一个数字所占点个数宽度 + break; + } + case DisType::Dis_Set_Get_Roller_ScanNum: + { + std::string val = std::to_string(pagenum); + int offsetdot = 8 > val.length() ? val.length() : 8; + lcd->Lcd_Display_String_8x16(3, 128 - offsetdot * 8, val.c_str()); //8 -> 一个数字所占点个数宽度 + break; + } + default: + break; + } + } + else + { + switch (ds){ + case DisType::Dis_Set_SleepMode_5M: + lcd->Lcd_Display_String_8x16(3, 112, "5M"); + break; + case DisType::Dis_Set_SleepMode_10M: + lcd->Lcd_Display_String_8x16(3, 104, "10M"); + break; + case DisType::Dis_Set_SleepMode_20M: + lcd->Lcd_Display_String_8x16(3, 104, "20M"); + break; + case DisType::Dis_Set_SleepMode_30M: + lcd->Lcd_Display_String_8x16(3, 104, "30M"); + break; + case DisType::Dis_Set_SleepMode_1H: + lcd->Lcd_Display_String_8x16(3, 112, "1H"); + break; + case DisType::Dis_Set_SleepMode_2H: + lcd->Lcd_Display_String_8x16(3, 112, "2H"); + break; + case DisType::Dis_Set_SleepMode_4H: + lcd->Lcd_Display_String_8x16(3, 112, "4H"); + break; + default: + m_status= DisType::Dis_Unkown; + break; + } + } +} + +int LCDDisplay::bitnum(unsigned int num) +{ + int count = 0; + do + { + num = num / 10; + count++; + } while (num > 0); + return count; +} + +DisType LCDDisplay::GetCurrentStatus() const +{ + return m_status; +} + +void LCDDisplay::set_language(Language language) +{ + if(language != m_language) + m_language = language; +} \ No newline at end of file diff --git a/display/LCDDisplay.h b/display/LCDDisplay.h new file mode 100644 index 0000000..5dcb7e2 --- /dev/null +++ b/display/LCDDisplay.h @@ -0,0 +1,205 @@ +#pragma once +#include +#include +#include "Displaydef.h" + +class Lcd; + +class LCDDisplay +{ +private: + /* data */ +public: + enum Language + { + Chinese, + TraditionalChinese, + English, + }; + + LCDDisplay(int language); + ~LCDDisplay(); + void set_language(Language language); + void DisplayState(DisType ds,unsigned int pagenum,ClearScreen clearscree); + DisType GetCurrentStatus() const; + +private: + + int bitnum(unsigned int num); + +private: + std::vector> map_Display; + std::shared_ptr lcd; + Language m_language; + DisType m_status; + + std::map m_language_map{ + {Language::Chinese,0}, + {Language::TraditionalChinese,1}, + {Language::English,2}, + }; + + + std::map map_Display_CN={ + {DisType::Dis_Welcome,{1,1,DisDrawtype::DD_All,std::vector(f_logo,f_logo+sizeof(f_logo))}}, + {DisType::Dis_Init,{1,1,DisDrawtype::DD_All,std::vector(f_welcome,f_welcome+sizeof(f_welcome))}}, + {DisType::Dis_Idel,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_ready,f_ready+sizeof(f_ready))}}, + {DisType::Dis_Scan,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_scan,f_scan+sizeof(f_scan))}}, + {DisType::Dis_Set_ClearPaperPass,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_clearpaperpass,f_clearpaperpass+sizeof(f_clearpaperpass))}}, + {DisType::Dis_Set_Count,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_countmode,f_countmode+sizeof(f_countmode))}}, + {DisType::Dis_Err_DoubleFeed,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_doublefeed,f_doublefeed+sizeof(f_doublefeed))}}, + {DisType::Dis_Err_Stable,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_stable,f_stable+sizeof(f_stable))}}, + {DisType::Dis_Err_CoverOpen,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_coveropen,f_coveropen+sizeof(f_coveropen))}}, + {DisType::Dis_Err_JamIn,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_paperjam,f_paperjam+sizeof(f_paperjam))}}, + {DisType::Dis_Err_JamOut,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_paperjam,f_paperjam+sizeof(f_paperjam))}}, + {DisType::Dis_Err_HandModeJam,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_handmodepaperjam,f_handmodepaperjam+sizeof(f_handmodepaperjam))}}, + {DisType::Dis_Err_PaperScrew,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_paperscrew,f_paperscrew+sizeof(f_paperscrew))}}, + {DisType::Dis_Err_FeedError,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_feederror,f_feederror+sizeof(f_feederror))}}, + {DisType::Dis_Err_AqrImgTimeout,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_aqrimgtimeout,f_aqrimgtimeout+sizeof(f_aqrimgtimeout))}}, + {DisType::Dis_Err_DogEar,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_dogear,f_dogear+sizeof(f_dogear))}}, + {DisType::Dis_Err_Size,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_size,f_size+sizeof(f_size))}}, + {DisType::Dis_Set_PollPaperIntensity,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_pollpaperintensity,f_pollpaperintensity+sizeof(f_pollpaperintensity))}}, + {DisType::Dis_Set_PollPI_High,{3,96,DisDrawtype::DD_BotRight,std::vector(f_intensityHigh,f_intensityHigh+sizeof(f_intensityHigh))}}, + {DisType::Dis_Set_PollPI_Mid,{3,96,DisDrawtype::DD_BotRight,std::vector(f_intensityMid,f_intensityMid+sizeof(f_intensityMid))}}, + {DisType::Dis_Set_PollPI_Low,{3,96,DisDrawtype::DD_BotRight,std::vector(f_intensityLow,f_intensityLow+sizeof(f_intensityLow))}}, + + {DisType::Dis_Set_TrayPosition,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_trayposition,f_trayposition+sizeof(f_trayposition))}}, + {DisType::Dis_Set_TrayPosition_High,{3,96,DisDrawtype::DD_BotRight,std::vector(f_intensityHigh,f_intensityHigh+sizeof(f_intensityHigh))}}, + {DisType::Dis_Set_TrayPosition_Mid,{3,96,DisDrawtype::DD_BotRight,std::vector(f_intensityMid,f_intensityMid+sizeof(f_intensityMid))}}, + {DisType::Dis_Set_TrayPosition_Low,{3,96,DisDrawtype::DD_BotRight,std::vector(f_traypositionLow,f_traypositionLow+sizeof(f_traypositionLow))}}, + + {DisType::Dis_Count_Page,{3,112,DisDrawtype::DD_BotRight,std::vector(f_page,f_page+sizeof(f_page))}}, + {DisType::Dis_Scan_Page,{3,112,DisDrawtype::DD_BotRight,std::vector(f_page,f_page+sizeof(f_page))}}, + {DisType::Dis_Err_NoPaper,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_nopaper,f_nopaper+sizeof(f_nopaper))}}, + {DisType::Dis_Set_SleepMode,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_sleepmode,f_sleepmode+sizeof(f_sleepmode))}}, + // {DisType::Dis_Set_SleepMode_30M,{3,64,DisDrawtype::DD_BotRight,std::vector(f_30min,f_30min+sizeof(f_30min))}}, + // {DisType::Dis_Set_SleepMode_1H,{3,80,DisDrawtype::DD_BotRight,std::vector(f_1hour,f_1hour+sizeof(f_1hour))}}, + // {DisType::Dis_Set_SleepMode_2H,{3,80,DisDrawtype::DD_BotRight,std::vector(f_2hour,f_2hour+sizeof(f_2hour))}}, + {DisType::Dis_Set_SleepMode_NEVER,{3,80,DisDrawtype::DD_BotRight,std::vector(f_never,f_never+sizeof(f_never))}}, + {DisType::Dis_Set_Return,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_return,f_return+sizeof(f_return))}}, + {DisType::Dis_Set_Poweroff,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_powerof,f_powerof+sizeof(f_powerof))}}, + {DisType::Dis_HandMode,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_handmode,f_handmode+sizeof(f_handmode))}}, + {DisType::Dis_Set_Item_Return,{3,96,DisDrawtype::DD_BotRight,std::vector(f_return,f_return+sizeof(f_return))}}, + {DisType::Dis_Device_Lock,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_deviceLock,f_deviceLock+sizeof(f_deviceLock))}}, + {DisType::Dis_Set_ScanNum_Option,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_scannum,f_scannum+sizeof(f_scannum))}}, + {DisType::Dis_Set_Get_History_ScanNum,{3,1,DisDrawtype::DD_BotRight,std::vector(f_history_num,f_history_num+sizeof(f_history_num))}}, + {DisType::Dis_Set_Get_Roller_ScanNum,{3,1,DisDrawtype::DD_BotRight,std::vector(f_roller_num,f_roller_num+sizeof(f_roller_num))}}, + {DisType::Dis_Set_Clear_Roller_ScanNum,{3,64,DisDrawtype::DD_BotRight,std::vector(f_clrea_roller,f_clrea_roller+sizeof(f_clrea_roller))}}, + {DisType::Dis_Set_Is_Sure,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_is_sure,f_is_sure+sizeof(f_is_sure))}}, + {DisType::Dis_Set_YES,{3,112,DisDrawtype::DD_BotRight,std::vector(f_yes,f_yes+sizeof(f_yes))}}, + {DisType::Dis_Set_No,{3,112,DisDrawtype::DD_BotRight,std::vector(f_no,f_no+sizeof(f_no))}}, + {DisType::Dis_Language,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_language,f_language+sizeof(f_language))}}, + {DisType::Dis_Language_Chinese,{3,64,DisDrawtype::DD_BotRight,std::vector(f_language_chinese,f_language_chinese+sizeof(f_language_chinese))}}, + {DisType::Dis_Language_Chinese_Traditional,{3,64,DisDrawtype::DD_BotRight,std::vector(f_language_chinese_traditional,f_language_chinese_traditional+sizeof(f_language_chinese_traditional))}}, + {DisType::Dis_Language_English,{3,64,DisDrawtype::DD_BotRight,std::vector(f_language_english,f_language_english+sizeof(f_language_english))}}, +}; + + + std::map map_Display_EN={ + {DisType::Dis_Welcome,{1,1,DisDrawtype::DD_All,std::vector(f_logo,f_logo+sizeof(f_logo))}}, + {DisType::Dis_Init,{1,1,DisDrawtype::DD_All,std::vector(f_welcome_EN,f_welcome_EN+sizeof(f_welcome_EN))}}, + {DisType::Dis_Idel,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_ready_EN,f_ready_EN+sizeof(f_ready_EN))}}, + {DisType::Dis_Scan,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_scan_EN,f_scan_EN+sizeof(f_scan_EN))}}, + {DisType::Dis_Set_ClearPaperPass,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_clearpaperpass_EN,f_clearpaperpass_EN+sizeof(f_clearpaperpass_EN))}}, + {DisType::Dis_Set_Count,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_countmode_EN,f_countmode_EN+sizeof(f_countmode_EN))}}, + {DisType::Dis_Err_DoubleFeed,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_doublefeed_EN,f_doublefeed_EN+sizeof(f_doublefeed_EN))}}, + {DisType::Dis_Err_Stable,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_stable_EN,f_stable_EN+sizeof(f_stable_EN))}}, + {DisType::Dis_Err_CoverOpen,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_coveropen_EN,f_coveropen_EN+sizeof(f_coveropen_EN))}}, + {DisType::Dis_Err_JamIn,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_paperjam_EN,f_paperjam_EN+sizeof(f_paperjam_EN))}}, + {DisType::Dis_Err_JamOut,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_paperjam_EN,f_paperjam_EN+sizeof(f_paperjam_EN))}}, + {DisType::Dis_Err_HandModeJam,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_handmodepaperjam_EN,f_handmodepaperjam_EN+sizeof(f_handmodepaperjam_EN))}}, + {DisType::Dis_Err_PaperScrew,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_paperscrew_EN,f_paperscrew_EN+sizeof(f_paperscrew_EN))}}, + {DisType::Dis_Err_FeedError,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_feederror_EN,f_feederror_EN+sizeof(f_feederror_EN))}}, + {DisType::Dis_Err_AqrImgTimeout,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_aqrimgtimeout_EN,f_aqrimgtimeout_EN+sizeof(f_aqrimgtimeout_EN))}}, + {DisType::Dis_Err_DogEar,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_dogear_EN,f_dogear_EN+sizeof(f_dogear_EN))}}, + {DisType::Dis_Err_Size,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_size,f_size+sizeof(f_size))}}, + {DisType::Dis_Set_PollPaperIntensity,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_pollpaperintensity_EN,f_pollpaperintensity_EN+sizeof(f_pollpaperintensity_EN))}}, + {DisType::Dis_Set_PollPI_High,{3,96,DisDrawtype::DD_BotRight,std::vector(f_intensityHigh_EN,f_intensityHigh_EN+sizeof(f_intensityHigh_EN))}}, + {DisType::Dis_Set_PollPI_Mid,{3,96,DisDrawtype::DD_BotRight,std::vector(f_intensityMid_EN,f_intensityMid_EN+sizeof(f_intensityMid_EN))}}, + {DisType::Dis_Set_PollPI_Low,{3,96,DisDrawtype::DD_BotRight,std::vector(f_intensityLow_EN,f_intensityLow_EN+sizeof(f_intensityLow_EN))}}, + + {DisType::Dis_Set_TrayPosition,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_trayposition_EN,f_trayposition_EN+sizeof(f_trayposition_EN))}}, + {DisType::Dis_Set_TrayPosition_High,{3,96,DisDrawtype::DD_BotRight,std::vector(f_intensityHigh_EN,f_intensityHigh_EN+sizeof(f_intensityHigh_EN))}}, + {DisType::Dis_Set_TrayPosition_Mid,{3,96,DisDrawtype::DD_BotRight,std::vector(f_intensityMid_EN,f_intensityMid_EN+sizeof(f_intensityMid_EN))}}, + {DisType::Dis_Set_TrayPosition_Low,{3,96,DisDrawtype::DD_BotRight,std::vector(f_traypositionLow_EN,f_traypositionLow_EN+sizeof(f_traypositionLow_EN))}}, + + {DisType::Dis_Count_Page,{3,112,DisDrawtype::DD_BotRight,std::vector(f_page_EN,f_page_EN+sizeof(f_page_EN))}}, + {DisType::Dis_Scan_Page,{3,112,DisDrawtype::DD_BotRight,std::vector(f_page_EN,f_page_EN+sizeof(f_page_EN))}}, + {DisType::Dis_Err_NoPaper,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_nopaper_EN,f_nopaper_EN+sizeof(f_nopaper_EN))}}, + {DisType::Dis_Set_SleepMode,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_sleepmode_EN,f_sleepmode_EN+sizeof(f_sleepmode_EN))}}, + // {DisType::Dis_Set_SleepMode_30M,{3,64,DisDrawtype::DD_BotRight,std::vector(f_30min,f_30min+sizeof(f_30min))}}, + // {DisType::Dis_Set_SleepMode_1H,{3,80,DisDrawtype::DD_BotRight,std::vector(f_1hour,f_1hour+sizeof(f_1hour))}}, + // {DisType::Dis_Set_SleepMode_2H,{3,80,DisDrawtype::DD_BotRight,std::vector(f_2hour,f_2hour+sizeof(f_2hour))}}, + {DisType::Dis_Set_SleepMode_NEVER,{3,80,DisDrawtype::DD_BotRight,std::vector(f_never_EN,f_never_EN+sizeof(f_never_EN))}}, + {DisType::Dis_Set_Return,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_return_EN,f_return_EN+sizeof(f_return_EN))}}, + {DisType::Dis_Set_Poweroff,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_powerof_EN,f_powerof_EN+sizeof(f_powerof_EN))}}, + {DisType::Dis_HandMode,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_handmode_EN,f_handmode_EN+sizeof(f_handmode_EN))}}, + {DisType::Dis_Set_Item_Return,{3,80,DisDrawtype::DD_BotRight,std::vector(f_return_EN,f_return_EN+sizeof(f_return_EN))}}, + {DisType::Dis_Device_Lock,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_deviceLock_EN,f_deviceLock_EN+sizeof(f_deviceLock_EN))}}, + {DisType::Dis_Set_ScanNum_Option,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_scannum_EN,f_scannum_EN+sizeof(f_scannum_EN))}}, + {DisType::Dis_Set_Get_History_ScanNum,{3,1,DisDrawtype::DD_BotRight,std::vector(f_history_num_EN,f_history_num_EN+sizeof(f_history_num_EN))}}, + {DisType::Dis_Set_Get_Roller_ScanNum,{3,1,DisDrawtype::DD_BotRight,std::vector(f_roller_num_EN,f_roller_num_EN+sizeof(f_roller_num_EN))}}, + {DisType::Dis_Set_Clear_Roller_ScanNum,{3,40,DisDrawtype::DD_BotRight,std::vector(f_clrea_roller_EN,f_clrea_roller_EN+sizeof(f_clrea_roller_EN))}}, + {DisType::Dis_Set_Is_Sure,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_is_sure_EN,f_is_sure_EN+sizeof(f_is_sure_EN))}}, + {DisType::Dis_Set_YES,{3,104,DisDrawtype::DD_BotRight,std::vector(f_yes_EN,f_yes_EN+sizeof(f_yes_EN))}}, + {DisType::Dis_Set_No,{3,112,DisDrawtype::DD_BotRight,std::vector(f_no_EN,f_no_EN+sizeof(f_no_EN))}}, + {DisType::Dis_Language,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_language_EN,f_language_EN+sizeof(f_language_EN))}}, + {DisType::Dis_Language_Chinese,{3,64,DisDrawtype::DD_BotRight,std::vector(f_language_chinese,f_language_chinese+sizeof(f_language_chinese))}}, + {DisType::Dis_Language_Chinese_Traditional,{3,64,DisDrawtype::DD_BotRight,std::vector(f_language_chinese_traditional,f_language_chinese_traditional+sizeof(f_language_chinese_traditional))}}, + {DisType::Dis_Language_English,{3,64,DisDrawtype::DD_BotRight,std::vector(f_language_english,f_language_english+sizeof(f_language_english))}}, +}; + + std::map map_Display_TC={ + {DisType::Dis_Welcome,{1,1,DisDrawtype::DD_All,std::vector(f_logo,f_logo+sizeof(f_logo))}}, + {DisType::Dis_Init,{1,1,DisDrawtype::DD_All,std::vector(f_welcome_TC,f_welcome_TC+sizeof(f_welcome_TC))}}, + {DisType::Dis_Idel,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_ready_TC,f_ready_TC+sizeof(f_ready_TC))}}, + {DisType::Dis_Scan,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_scan_TC,f_scan_TC+sizeof(f_scan_TC))}}, + {DisType::Dis_Set_ClearPaperPass,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_clearpaperpass_TC,f_clearpaperpass_TC+sizeof(f_clearpaperpass_TC))}}, + {DisType::Dis_Set_Count,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_countmode_TC,f_countmode_TC+sizeof(f_countmode_TC))}}, + {DisType::Dis_Err_DoubleFeed,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_doublefeed_TC,f_doublefeed_TC+sizeof(f_doublefeed_TC))}}, + {DisType::Dis_Err_Stable,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_stable_TC,f_stable_TC+sizeof(f_stable_TC))}}, + {DisType::Dis_Err_CoverOpen,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_coveropen_TC,f_coveropen_TC+sizeof(f_coveropen_TC))}}, + {DisType::Dis_Err_JamIn,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_paperjam_TC,f_paperjam_TC+sizeof(f_paperjam_TC))}}, + {DisType::Dis_Err_JamOut,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_paperjam_TC,f_paperjam_TC+sizeof(f_paperjam_TC))}}, + {DisType::Dis_Err_HandModeJam,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_handmodepaperjam_TC,f_handmodepaperjam_TC+sizeof(f_handmodepaperjam_TC))}}, + {DisType::Dis_Err_PaperScrew,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_paperscrew_TC,f_paperscrew_TC+sizeof(f_paperscrew_TC))}}, + {DisType::Dis_Err_FeedError,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_feederror_TC,f_feederror_TC+sizeof(f_feederror_TC))}}, + {DisType::Dis_Err_AqrImgTimeout,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_aqrimgtimeout_TC,f_aqrimgtimeout_TC+sizeof(f_aqrimgtimeout_TC))}}, + {DisType::Dis_Err_DogEar,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_dogear_TC,f_dogear_TC+sizeof(f_dogear_TC))}}, + {DisType::Dis_Err_Size,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_size,f_size+sizeof(f_size))}}, + {DisType::Dis_Set_PollPaperIntensity,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_pollpaperintensity_TC,f_pollpaperintensity_TC+sizeof(f_pollpaperintensity_TC))}}, + {DisType::Dis_Set_PollPI_High,{3,96,DisDrawtype::DD_BotRight,std::vector(f_intensityHigh_TC,f_intensityHigh_TC+sizeof(f_intensityHigh_TC))}}, + {DisType::Dis_Set_PollPI_Mid,{3,96,DisDrawtype::DD_BotRight,std::vector(f_intensityMid_TC,f_intensityMid_TC+sizeof(f_intensityMid_TC))}}, + {DisType::Dis_Set_PollPI_Low,{3,96,DisDrawtype::DD_BotRight,std::vector(f_intensityLow_TC,f_intensityLow_TC+sizeof(f_intensityLow_TC))}}, + + {DisType::Dis_Set_TrayPosition,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_trayposition_TC,f_trayposition_TC+sizeof(f_trayposition_TC))}}, + {DisType::Dis_Set_TrayPosition_High,{3,96,DisDrawtype::DD_BotRight,std::vector(f_intensityHigh_TC,f_intensityHigh_TC+sizeof(f_intensityHigh_TC))}}, + {DisType::Dis_Set_TrayPosition_Mid,{3,96,DisDrawtype::DD_BotRight,std::vector(f_intensityMid_TC,f_intensityMid_TC+sizeof(f_intensityMid_TC))}}, + {DisType::Dis_Set_TrayPosition_Low,{3,96,DisDrawtype::DD_BotRight,std::vector(f_traypositionLow_TC,f_traypositionLow_TC+sizeof(f_traypositionLow_TC))}}, + + {DisType::Dis_Count_Page,{3,112,DisDrawtype::DD_BotRight,std::vector(f_page_TC,f_page_TC+sizeof(f_page_TC))}}, + {DisType::Dis_Scan_Page,{3,112,DisDrawtype::DD_BotRight,std::vector(f_page_TC,f_page_TC+sizeof(f_page_TC))}}, + {DisType::Dis_Err_NoPaper,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_nopaper_TC,f_nopaper_TC+sizeof(f_nopaper_TC))}}, + {DisType::Dis_Set_SleepMode,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_sleepmode_TC,f_sleepmode_TC+sizeof(f_sleepmode_TC))}}, + // {DisType::Dis_Set_SleepMode_30M,{3,64,DisDrawtype::DD_BotRight,std::vector(f_30min,f_30min+sizeof(f_30min))}}, + // {DisType::Dis_Set_SleepMode_1H,{3,80,DisDrawtype::DD_BotRight,std::vector(f_1hour,f_1hour+sizeof(f_1hour))}}, + // {DisType::Dis_Set_SleepMode_2H,{3,80,DisDrawtype::DD_BotRight,std::vector(f_2hour,f_2hour+sizeof(f_2hour))}}, + {DisType::Dis_Set_SleepMode_NEVER,{3,80,DisDrawtype::DD_BotRight,std::vector(f_never_TC,f_never_TC+sizeof(f_never_TC))}}, + {DisType::Dis_Set_Return,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_return_TC,f_return_TC+sizeof(f_return_TC))}}, + {DisType::Dis_Set_Poweroff,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_powerof_TC,f_powerof_TC+sizeof(f_powerof_TC))}}, + {DisType::Dis_HandMode,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_handmode_TC,f_handmode_TC+sizeof(f_handmode_TC))}}, + {DisType::Dis_Set_Item_Return,{3,96,DisDrawtype::DD_BotRight,std::vector(f_return_TC,f_return_TC+sizeof(f_return_TC))}}, + {DisType::Dis_Device_Lock,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_deviceLock_TC,f_deviceLock_TC+sizeof(f_deviceLock_TC))}}, + {DisType::Dis_Set_ScanNum_Option,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_scannum_TC,f_scannum_TC+sizeof(f_scannum_TC))}}, + {DisType::Dis_Set_Get_History_ScanNum,{3,1,DisDrawtype::DD_BotRight,std::vector(f_history_num_TC,f_history_num_TC+sizeof(f_history_num_TC))}}, + {DisType::Dis_Set_Get_Roller_ScanNum,{3,1,DisDrawtype::DD_BotRight,std::vector(f_roller_num_TC,f_roller_num_TC+sizeof(f_roller_num_TC))}}, + {DisType::Dis_Set_Clear_Roller_ScanNum,{3,64,DisDrawtype::DD_BotRight,std::vector(f_clrea_roller_TC,f_clrea_roller_TC+sizeof(f_clrea_roller_TC))}}, + {DisType::Dis_Set_Is_Sure,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_is_sure_TC,f_is_sure_TC+sizeof(f_is_sure_TC))}}, + {DisType::Dis_Set_YES,{3,112,DisDrawtype::DD_BotRight,std::vector(f_yes_TC,f_yes_TC+sizeof(f_yes_TC))}}, + {DisType::Dis_Set_No,{3,112,DisDrawtype::DD_BotRight,std::vector(f_no_TC,f_no_TC+sizeof(f_no_TC))}}, + {DisType::Dis_Language,{1,1,DisDrawtype::DD_TopLeft,std::vector(f_language_TC,f_language_TC+sizeof(f_language_TC))}}, + {DisType::Dis_Language_Chinese,{3,64,DisDrawtype::DD_BotRight,std::vector(f_language_chinese,f_language_chinese+sizeof(f_language_chinese))}}, + {DisType::Dis_Language_Chinese_Traditional,{3,64,DisDrawtype::DD_BotRight,std::vector(f_language_chinese_traditional,f_language_chinese_traditional+sizeof(f_language_chinese_traditional))}}, + {DisType::Dis_Language_English,{3,64,DisDrawtype::DD_BotRight,std::vector(f_language_english,f_language_english+sizeof(f_language_english))}}, +}; +}; diff --git a/display/Lcd.cpp b/display/Lcd.cpp new file mode 100644 index 0000000..4e74a9b --- /dev/null +++ b/display/Lcd.cpp @@ -0,0 +1,780 @@ +#include "Lcd.h" +#include +#include +#include +#include "DevUtil.h" + +using namespace std; + +#define IOEXPORTPATH "/sys/class/gpio/export" +#define DELAY_US(t) this_thread::sleep_for(chrono::microseconds((t))) +#define DELAY_MS(t) this_thread::sleep_for(chrono::milliseconds((t))) + +static unsigned char ascii_table_8x16[95][16] = { + + /*-- 文字: --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /*-- 文字: ! --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x30, 0x00, 0x00, 0x00, + + /*-- 文字: " --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x10, 0x0C, 0x06, 0x10, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /*-- 文字: # --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x40, 0xC0, 0x78, 0x40, 0xC0, 0x78, 0x40, 0x00, 0x04, 0x3F, 0x04, 0x04, 0x3F, 0x04, 0x04, 0x00, + + /*-- 文字: $ --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x70, 0x88, 0xFC, 0x08, 0x30, 0x00, 0x00, 0x00, 0x18, 0x20, 0xFF, 0x21, 0x1E, 0x00, 0x00, + + /*-- 文字: % --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0xF0, 0x08, 0xF0, 0x00, 0xE0, 0x18, 0x00, 0x00, 0x00, 0x21, 0x1C, 0x03, 0x1E, 0x21, 0x1E, 0x00, + + /*-- 文字: & --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0xF0, 0x08, 0x88, 0x70, 0x00, 0x00, 0x00, 0x1E, 0x21, 0x23, 0x24, 0x19, 0x27, 0x21, 0x10, + + /*-- 文字: ' --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x10, 0x16, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /*-- 文字: ( --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x00, 0xE0, 0x18, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x07, 0x18, 0x20, 0x40, 0x00, + + /*-- 文字: ) --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x02, 0x04, 0x18, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x18, 0x07, 0x00, 0x00, 0x00, + + /*-- 文字: * --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x40, 0x40, 0x80, 0xF0, 0x80, 0x40, 0x40, 0x00, 0x02, 0x02, 0x01, 0x0F, 0x01, 0x02, 0x02, 0x00, + + /*-- 文字: + --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x1F, 0x01, 0x01, 0x01, 0x00, + + /*-- 文字: , --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xB0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, + + /*-- 文字: - --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + + /*-- 文字: . --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + + /*-- 文字: / --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x18, 0x04, 0x00, 0x60, 0x18, 0x06, 0x01, 0x00, 0x00, 0x00, + + /*-- 文字: 0 --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x10, 0x0F, 0x00, + + /*-- 文字: 1 --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x10, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, + + /*-- 文字: 2 --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x70, 0x08, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, 0x30, 0x28, 0x24, 0x22, 0x21, 0x30, 0x00, + + /*-- 文字: 3 --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x30, 0x08, 0x88, 0x88, 0x48, 0x30, 0x00, 0x00, 0x18, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00, + + /*-- 文字: 4 --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0xC0, 0x20, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x07, 0x04, 0x24, 0x24, 0x3F, 0x24, 0x00, + + /*-- 文字: 5 --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0xF8, 0x08, 0x88, 0x88, 0x08, 0x08, 0x00, 0x00, 0x19, 0x21, 0x20, 0x20, 0x11, 0x0E, 0x00, + + /*-- 文字: 6 --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0xE0, 0x10, 0x88, 0x88, 0x18, 0x00, 0x00, 0x00, 0x0F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00, + + /*-- 文字: 7 --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x38, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, + + /*-- 文字: 8 --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x70, 0x88, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, 0x1C, 0x22, 0x21, 0x21, 0x22, 0x1C, 0x00, + + /*-- 文字: 9 --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x00, 0x31, 0x22, 0x22, 0x11, 0x0F, 0x00, + + /*-- 文字: : --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, + + /*-- 文字: ; --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, + + /*-- 文字: < --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, + + /*-- 文字: = --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, + + /*-- 文字: > --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, + + /*-- 文字: ? --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x70, 0x48, 0x08, 0x08, 0x08, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x30, 0x36, 0x01, 0x00, 0x00, + + /*-- 文字: @ --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0xC0, 0x30, 0xC8, 0x28, 0xE8, 0x10, 0xE0, 0x00, 0x07, 0x18, 0x27, 0x24, 0x23, 0x14, 0x0B, 0x00, + + /*-- 文字: A --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0xC0, 0x38, 0xE0, 0x00, 0x00, 0x00, 0x20, 0x3C, 0x23, 0x02, 0x02, 0x27, 0x38, 0x20, + + /*-- 文字: B --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x08, 0xF8, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00, + + /*-- 文字: C --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0xC0, 0x30, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x07, 0x18, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00, + + /*-- 文字: D --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x08, 0xF8, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00, + + /*-- 文字: E --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x23, 0x20, 0x18, 0x00, + + /*-- 文字: F --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, + + /*-- 文字: G --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0xC0, 0x30, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x07, 0x18, 0x20, 0x20, 0x22, 0x1E, 0x02, 0x00, + + /*-- 文字: H --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08, 0x20, 0x3F, 0x21, 0x01, 0x01, 0x21, 0x3F, 0x20, + + /*-- 文字: I --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, + + /*-- 文字: J --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00, 0x00, + + /*-- 文字: K --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x08, 0xF8, 0x88, 0xC0, 0x28, 0x18, 0x08, 0x00, 0x20, 0x3F, 0x20, 0x01, 0x26, 0x38, 0x20, 0x00, + + /*-- 文字: L --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x08, 0xF8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x20, 0x30, 0x00, + + /*-- 文字: M --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x08, 0xF8, 0xF8, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x20, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x20, 0x00, + + /*-- 文字: N --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x08, 0xF8, 0x30, 0xC0, 0x00, 0x08, 0xF8, 0x08, 0x20, 0x3F, 0x20, 0x00, 0x07, 0x18, 0x3F, 0x00, + + /*-- 文字: O --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00, + + /*-- 文字: P --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x08, 0xF8, 0x08, 0x08, 0x08, 0x08, 0xF0, 0x00, 0x20, 0x3F, 0x21, 0x01, 0x01, 0x01, 0x00, 0x00, + + /*-- 文字: Q --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x0F, 0x18, 0x24, 0x24, 0x38, 0x50, 0x4F, 0x00, + + /*-- 文字: R --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x08, 0xF8, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x03, 0x0C, 0x30, 0x20, + + /*-- 文字: S --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x70, 0x88, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x38, 0x20, 0x21, 0x21, 0x22, 0x1C, 0x00, + + /*-- 文字: T --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x18, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x18, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00, + + /*-- 文字: U --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00, + + /*-- 文字: V --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x08, 0x78, 0x88, 0x00, 0x00, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x07, 0x38, 0x0E, 0x01, 0x00, 0x00, + + /*-- 文字: W --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0xF8, 0x08, 0x00, 0xF8, 0x00, 0x08, 0xF8, 0x00, 0x03, 0x3C, 0x07, 0x00, 0x07, 0x3C, 0x03, 0x00, + + /*-- 文字: X --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x08, 0x18, 0x68, 0x80, 0x80, 0x68, 0x18, 0x08, 0x20, 0x30, 0x2C, 0x03, 0x03, 0x2C, 0x30, 0x20, + + /*-- 文字: Y --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x08, 0x38, 0xC8, 0x00, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00, + + /*-- 文字: Z --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x10, 0x08, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00, 0x20, 0x38, 0x26, 0x21, 0x20, 0x20, 0x18, 0x00, + + /*-- 文字: [ --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x00, 0xFE, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x40, 0x40, 0x40, 0x00, + + /*-- 文字: \ --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x38, 0xC0, 0x00, + + /*-- 文字: ] --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x02, 0x02, 0x02, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x7F, 0x00, 0x00, 0x00, + + /*-- 文字: ^ --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x04, 0x02, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /*-- 文字: _ --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + + /*-- 文字: ` --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /*-- 文字: a --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x19, 0x24, 0x22, 0x22, 0x22, 0x3F, 0x20, + + /*-- 文字: b --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x08, 0xF8, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00, + + /*-- 文字: c --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0x20, 0x11, 0x00, + + /*-- 文字: d --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x00, 0x80, 0x80, 0x88, 0xF8, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0x10, 0x3F, 0x20, + + /*-- 文字: e --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x22, 0x22, 0x22, 0x13, 0x00, + + /*-- 文字: f --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x80, 0x80, 0xF0, 0x88, 0x88, 0x88, 0x18, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, + + /*-- 文字: g --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x6B, 0x94, 0x94, 0x94, 0x93, 0x60, 0x00, + + /*-- 文字: h --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x08, 0xF8, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20, + + /*-- 文字: i --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x80, 0x98, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, + + /*-- 文字: j --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x00, 0x80, 0x98, 0x98, 0x00, 0x00, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00, + + /*-- 文字: k --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x08, 0xF8, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x20, 0x3F, 0x24, 0x02, 0x2D, 0x30, 0x20, 0x00, + + /*-- 文字: l --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x08, 0x08, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, + + /*-- 文字: m --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x3F, 0x20, 0x00, 0x3F, + + /*-- 文字: n --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20, + + /*-- 文字: o --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00, + + /*-- 文字: p --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xA1, 0x20, 0x20, 0x11, 0x0E, 0x00, + + /*-- 文字: q --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0xA0, 0xFF, 0x80, + + /*-- 文字: r --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x20, 0x20, 0x3F, 0x21, 0x20, 0x00, 0x01, 0x00, + + /*-- 文字: s --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x33, 0x24, 0x24, 0x24, 0x24, 0x19, 0x00, + + /*-- 文字: t --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x80, 0x80, 0xE0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x00, 0x00, + + /*-- 文字: u --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x10, 0x3F, 0x20, + + /*-- 文字: v --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0E, 0x30, 0x08, 0x06, 0x01, 0x00, + + /*-- 文字: w --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x80, 0x80, 0x00, 0x80, 0x00, 0x80, 0x80, 0x80, 0x0F, 0x30, 0x0C, 0x03, 0x0C, 0x30, 0x0F, 0x00, + + /*-- 文字: x --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x31, 0x2E, 0x0E, 0x31, 0x20, 0x00, + + /*-- 文字: y --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x81, 0x8E, 0x70, 0x18, 0x06, 0x01, 0x00, + + /*-- 文字: z --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x21, 0x30, 0x2C, 0x22, 0x21, 0x30, 0x00, + + /*-- 文字: { --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x00, 0x00, 0x80, 0x7C, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x40, 0x40, + + /*-- 文字: | --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + + /*-- 文字: } --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x02, 0x02, 0x7C, 0x80, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x3F, 0x00, 0x00, 0x00, 0x00, + + /*-- 文字: ~ --*/ + /*-- Comic Sans MS12; 此字体下对应的点阵为:宽x高=8x16 --*/ + 0x00, 0x06, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + +}; + +static unsigned char ascii_table_5x8[95][5] = { + /*全体ASCII 列表:5x8点阵*/ + 0x00, 0x00, 0x00, 0x00, 0x00, //space + 0x00, 0x00, 0x4f, 0x00, 0x00, //! + 0x00, 0x07, 0x00, 0x07, 0x00, //" + 0x14, 0x7f, 0x14, 0x7f, 0x14, //# + 0x24, 0x2a, 0x7f, 0x2a, 0x12, //$ + 0x23, 0x13, 0x08, 0x64, 0x62, //% + 0x36, 0x49, 0x55, 0x22, 0x50, //& + 0x00, 0x05, 0x07, 0x00, 0x00, //] + 0x00, 0x1c, 0x22, 0x41, 0x00, //( + 0x00, 0x41, 0x22, 0x1c, 0x00, //) + 0x14, 0x08, 0x3e, 0x08, 0x14, //* + 0x08, 0x08, 0x3e, 0x08, 0x08, //+ + 0x00, 0x50, 0x30, 0x00, 0x00, //, + 0x08, 0x08, 0x08, 0x08, 0x08, //- + 0x00, 0x60, 0x60, 0x00, 0x00, //. + 0x20, 0x10, 0x08, 0x04, 0x02, /// + 0x3e, 0x51, 0x49, 0x45, 0x3e, //0 + 0x00, 0x42, 0x7f, 0x40, 0x00, //1 + 0x42, 0x61, 0x51, 0x49, 0x46, //2 + 0x21, 0x41, 0x45, 0x4b, 0x31, //3 + 0x18, 0x14, 0x12, 0x7f, 0x10, //4 + 0x27, 0x45, 0x45, 0x45, 0x39, //5 + 0x3c, 0x4a, 0x49, 0x49, 0x30, //6 + 0x01, 0x71, 0x09, 0x05, 0x03, //7 + 0x36, 0x49, 0x49, 0x49, 0x36, //8 + 0x06, 0x49, 0x49, 0x29, 0x1e, //9 + 0x00, 0x36, 0x36, 0x00, 0x00, //: + 0x00, 0x56, 0x36, 0x00, 0x00, //; + 0x08, 0x14, 0x22, 0x41, 0x00, //< + 0x14, 0x14, 0x14, 0x14, 0x14, //= + 0x00, 0x41, 0x22, 0x14, 0x08, //> + 0x02, 0x01, 0x51, 0x09, 0x06, //? + 0x32, 0x49, 0x79, 0x41, 0x3e, //@ + 0x7e, 0x11, 0x11, 0x11, 0x7e, //A + 0x7f, 0x49, 0x49, 0x49, 0x36, //B + 0x3e, 0x41, 0x41, 0x41, 0x22, //C + 0x7f, 0x41, 0x41, 0x22, 0x1c, //D + 0x7f, 0x49, 0x49, 0x49, 0x41, //E + 0x7f, 0x09, 0x09, 0x09, 0x01, //F + 0x3e, 0x41, 0x49, 0x49, 0x7a, //G + 0x7f, 0x08, 0x08, 0x08, 0x7f, //H + 0x00, 0x41, 0x7f, 0x41, 0x00, //I + 0x20, 0x40, 0x41, 0x3f, 0x01, //J + 0x7f, 0x08, 0x14, 0x22, 0x41, //K + 0x7f, 0x40, 0x40, 0x40, 0x40, //L + 0x7f, 0x02, 0x0c, 0x02, 0x7f, //M + 0x7f, 0x04, 0x08, 0x10, 0x7f, //N + 0x3e, 0x41, 0x41, 0x41, 0x3e, //O + 0x7f, 0x09, 0x09, 0x09, 0x06, //P + 0x3e, 0x41, 0x51, 0x21, 0x5e, //Q + 0x7f, 0x09, 0x19, 0x29, 0x46, //R + 0x46, 0x49, 0x49, 0x49, 0x31, //S + 0x01, 0x01, 0x7f, 0x01, 0x01, //T + 0x3f, 0x40, 0x40, 0x40, 0x3f, //U + 0x1f, 0x20, 0x40, 0x20, 0x1f, //V + 0x3f, 0x40, 0x38, 0x40, 0x3f, //W + 0x63, 0x14, 0x08, 0x14, 0x63, //X + 0x07, 0x08, 0x70, 0x08, 0x07, //Y + 0x61, 0x51, 0x49, 0x45, 0x43, //Z + 0x00, 0x7f, 0x41, 0x41, 0x00, //[ + 0x02, 0x04, 0x08, 0x10, 0x20, //\ +0x00,0x41,0x41,0x7f,0x00,//] + 0x04, 0x02, 0x01, 0x02, 0x04, //^ + 0x40, 0x40, 0x40, 0x40, 0x40, //_ + 0x01, 0x02, 0x04, 0x00, 0x00, //` + 0x20, 0x54, 0x54, 0x54, 0x78, //a + 0x7f, 0x48, 0x48, 0x48, 0x30, //b + 0x38, 0x44, 0x44, 0x44, 0x44, //c + 0x30, 0x48, 0x48, 0x48, 0x7f, //d + 0x38, 0x54, 0x54, 0x54, 0x58, //e + 0x00, 0x08, 0x7e, 0x09, 0x02, //f + 0x48, 0x54, 0x54, 0x54, 0x3c, //g + 0x7f, 0x08, 0x08, 0x08, 0x70, //h + 0x00, 0x00, 0x7a, 0x00, 0x00, //i + 0x20, 0x40, 0x40, 0x3d, 0x00, //j + 0x7f, 0x20, 0x28, 0x44, 0x00, //k + 0x00, 0x41, 0x7f, 0x40, 0x00, //l + 0x7c, 0x04, 0x38, 0x04, 0x7c, //m + 0x7c, 0x08, 0x04, 0x04, 0x78, //n + 0x38, 0x44, 0x44, 0x44, 0x38, //o + 0x7c, 0x14, 0x14, 0x14, 0x08, //p + 0x08, 0x14, 0x14, 0x14, 0x7c, //q + 0x7c, 0x08, 0x04, 0x04, 0x08, //r + 0x48, 0x54, 0x54, 0x54, 0x24, //s + 0x04, 0x04, 0x3f, 0x44, 0x24, //t + 0x3c, 0x40, 0x40, 0x40, 0x3c, //u + 0x1c, 0x20, 0x40, 0x20, 0x1c, //v + 0x3c, 0x40, 0x30, 0x40, 0x3c, //w + 0x44, 0x28, 0x10, 0x28, 0x44, //x + 0x04, 0x48, 0x30, 0x08, 0x04, //y + 0x44, 0x64, 0x54, 0x4c, 0x44, //z + 0x08, 0x36, 0x41, 0x41, 0x00, //{ + 0x00, 0x00, 0x77, 0x00, 0x00, //| + 0x00, 0x41, 0x41, 0x36, 0x08, //} + 0x04, 0x02, 0x02, 0x02, 0x01, //~ +}; + + +Lcd::Lcd() : spi_sck(51), spi_sda(72), spi_cs(154), spi_reset(150), spi_rs(156),COM_BOOT0(153) + +{ + printf("Lcd()\n"); + write_dev(IOEXPORTPATH,51); + write_dev(IOEXPORTPATH,72); + write_dev(IOEXPORTPATH,154); + write_dev(IOEXPORTPATH,150); + write_dev(IOEXPORTPATH,156); + write_dev(IOEXPORTPATH,153); + + COM_BOOT0.setDirection(Gpio::out); + spi_sck.setDirection(Gpio::out); + spi_sda.setDirection(Gpio::out); + spi_cs.setDirection(Gpio::out); + spi_reset.setDirection(Gpio::out); + spi_rs.setDirection(Gpio::out); + + COM_BOOT0.setValue(Gpio::Low); + spi_sck.setValue(Gpio::High); + spi_sda.setValue(Gpio::High); + spi_cs.setValue(Gpio::High); + spi_reset.setValue(Gpio::High); + spi_rs.setValue(Gpio::High); +} + +/*=======写指令========*/ +void Lcd::Lcd_Transfer_Command(int data1) +{ + spi_cs.setValue(Gpio::Low); + spi_rs.setValue(Gpio::Low); + for (int i = 0; i < 8; i++) + { + spi_sck.setValue(Gpio::Low); + + if (data1 & 0x80) + spi_sda.setValue(Gpio::High); + else + spi_sda.setValue(Gpio::Low); + spi_sck.setValue(Gpio::High); + data1 = data1 <<= 1; + } + spi_cs.setValue(Gpio::High); +} + +/*--------写数据------------*/ +void Lcd::Lcd_Transfer_data(int data1) +{ + spi_cs.setValue(Gpio::Low); + spi_rs.setValue(Gpio::High); + for (int i = 0; i < 8; i++) + { + spi_sck.setValue(Gpio::Low); + if (data1 & 0x80) + spi_sda.setValue(Gpio::High); + else + spi_sda.setValue(Gpio::Low); + spi_sck.setValue(Gpio::High); + data1 = data1 <<= 1; + } + spi_cs.setValue(Gpio::High); +} + +/*LCD模块初始化*/ +void Lcd::Lcd_Initial_Lcd(bool biglcd) +{ + spi_cs.setValue(Gpio::Low); + spi_reset.setValue(Gpio::Low); /*低电平复位*/ + DELAY_MS(20); + spi_reset.setValue(Gpio::High); /*复位完毕*/ + DELAY_MS(20); + Lcd_Transfer_Command(0xe2); /*软复位*/ + DELAY_MS(50); + Lcd_Transfer_Command(0x2c); /*升压步聚1*/ + DELAY_MS(50); + Lcd_Transfer_Command(0x2e); /*升压步聚2*/ + DELAY_MS(50); + Lcd_Transfer_Command(0x2f); /*升压步聚3*/ + DELAY_MS(50); + Lcd_Transfer_Command(biglcd?0x21:0x24); /*0X24粗调对比度,可设置范围0x20~0x27*/ + Lcd_Transfer_Command(0x81); /*微调对比度*/ + Lcd_Transfer_Command(biglcd?0x28:0x15); /*45微调对比度的值,可设置范围0x00~0x3f 1f*/ // 0~63 + Lcd_Transfer_Command(0xa2); /*1/9偏压比(bias)0xa2 ,1/7bias 0xa3*/ + Lcd_Transfer_Command(0xc8); /*行扫描顺序:从上到下*/ //原 c0 字体倒置 CF ///////////////////////////////////////////////////////////// + Lcd_Transfer_Command(0xa0); /*列扫描顺序:从左到右*/ //原 a1 字体倒置 A0 //////////////////////////////////////////////// + Lcd_Transfer_Command(0x40); /*起始行:第一行开始*/ + Lcd_Transfer_Command(0xaf); /*开显示*/ + spi_cs.setValue(Gpio::High); +} + +void Lcd::Lcd_Address(unsigned char page, unsigned char column) +{ + spi_cs.setValue(Gpio::Low); + column = column - 1; + page = page - 1; + Lcd_Transfer_Command(0xb0 + page); //设置页地址。每页是8行。一个画面的64行被分成8个页。我们平常所说的第1页,在LCD驱动IC里是第0页,所以在这里减去1*/ + Lcd_Transfer_Command(((column >> 4) & 0x0f) + 0x10); //设置列地址的高4位 + Lcd_Transfer_Command(column & 0x0f); //设置列地址的低4位 +} + +/*全屏清屏*/ +void Lcd::Lcd_Clear_screen() +{ + unsigned char i, j; + spi_cs.setValue(Gpio::Low); + for (i = 0; i < 4; i++) + { + Lcd_Address(1 + i, 1); + for (j = 0; j < 132; j++) + { + Lcd_Transfer_data(0x00); + } + } + spi_cs.setValue(Gpio::High); +} + +//===显示测试画面:例如全显示,隔行显示,隔列显示,雪花显示===== +void Lcd::Lcd_Test_Display(unsigned char data1, unsigned char data2) +{ + int i, j; + for (j = 0; j < 8; j++) + { + spi_cs.setValue(Gpio::Low); + Lcd_Address(j + 1, 1); + for (i = 0; i < 128; i++) + { + Lcd_Transfer_data(data1); + Lcd_Transfer_data(data2); + } + } +} + +/*显示128x64点阵图像*/ +void Lcd::Lcd_Display_Graphic_128x64(unsigned char page, unsigned char column, unsigned char *dp) +{ + int i, j; + for (j = 0; j < 8; j++) + { + spi_cs.setValue(Gpio::Low); + Lcd_Address(page + j, column); + for (i = 0; i < 128; i++) + { + Lcd_Transfer_data(*dp); + dp++; + } + } +} + +/*显示32x32点阵图像、汉字、生僻字或32x32点阵的其他图标*/ +void Lcd::Lcd_Display_graphic_32x32(unsigned char page, unsigned char column, unsigned char *dp) +{ + unsigned char i, j; + spi_cs.setValue(Gpio::Low); + for (j = 0; j < 4; j++) + { + Lcd_Address(page + j, column); + for (i = 0; i < 31; i++) + { + Lcd_Transfer_data(*dp); /*写数据到LCD,每写完一个8位的数据后列地址自动加1*/ + dp++; + } + } +} + +/*显示16x16点阵图像、汉字、生僻字或16x16点阵的其他图标*/ +void Lcd::Lcd_Display_Graphic_16x16_2(unsigned char reverse, unsigned char page, unsigned char column, unsigned char *dp) +{ + unsigned char i, j; + + spi_cs.setValue(Gpio::Low); + for (j = 0; j < 2; j++) + { + Lcd_Address(page + j, column); + for (i = 0; i < 16; i++) + { + if (reverse == 1) + Lcd_Transfer_data(*dp); /*写数据到LCD,每写完一个8位的数据后列地址自动加1*/ + else + Lcd_Transfer_data(~*dp); /*写数据到LCD,每写完一个8位的数据后列地址自动加1*/ + dp++; + } + } + spi_cs.setValue(Gpio::High); +} + +/*显示16x16点阵图像、汉字、生僻字或16x16点阵的其他图标*/ +void Lcd::Lcd_Display_Graphic_16x16(unsigned char page, unsigned char column, unsigned char *dp, unsigned int wordcount) +{ + unsigned char i, j, k; + spi_cs.setValue(Gpio::Low); + for (k = 0; k < wordcount; k++) + { + for (j = 0; j < 2; j++) + { + Lcd_Address(page + j, column + 16 * k); + for (i = 0; i < 16; i++) + { + Lcd_Transfer_data(*dp); /*写数据到LCD,每写完一个8位的数据后列地址自动加1*/ + dp++; + } + } + } + spi_cs.setValue(Gpio::High); +} + +/*显示8x16点阵图像、ASCII, 或8x16点阵的自造字符、其他图标*/ +void Lcd::Lcd_Display_Graphic_8x16(unsigned char page, unsigned char column, unsigned char *dp) +{ + unsigned char i, j; + spi_cs.setValue(Gpio::Low); + for (j = 0; j < 2; j++) + { + Lcd_Address(page + j, column); + for (i = 0; i < 8; i++) + { + Lcd_Transfer_data(*dp); /*写数据到LCD,每写完一个8位的数据后列地址自动加1*/ + dp++; + } + } + spi_cs.setValue(Gpio::High); +} + +void Lcd::Lcd_Display_String_8x16(unsigned int page, unsigned int column, const char *text) +{ + unsigned int i = 0, j, k, n; + spi_cs.setValue(Gpio::Low); + while (text[i] > 0x00) + { + if ((text[i] >= 0x20) && (text[i] <= 0x7e)) + { + j = text[i] - 0x20; + for (n = 0; n < 2; n++) + { + Lcd_Address(page + n, column); + for (k = 0; k < 8; k++) + { + Lcd_Transfer_data(ascii_table_8x16[j][k + 8 * n]); /*显示5x7的ASCII字到LCD上,y为页地址,x为列地址,最后为数据*/ + } + } + i++; + column += 8; + } + else + i++; + } +} + +void Lcd::Lcd_Display_String_5x8(unsigned int page, unsigned int column, const char *text) +{ + unsigned int i = 0, j, k; + spi_cs.setValue(Gpio::Low); + while (text[i] > 0x00) + { + if ((text[i] >= 0x20) && (text[i] < 0x7e)) + { + j = text[i] - 0x20; + Lcd_Address(page, column); + for (k = 0; k < 5; k++) + { + Lcd_Transfer_data(ascii_table_5x8[j][k]); /*显示5x7的ASCII字到LCD上,y为页地址,x为列地址,最后为数据*/ + } + i++; + column += 6; + } + else + i++; + } +} + +void Lcd::Lcd_Clear_Half_Screen(bool top) +{ + int pageindex = top ? 0 : 2; + int pagemaxindex = top ? 2 : 4; + spi_cs.setValue(Gpio::Low); + for (int i = pageindex; i < pagemaxindex; i++) + { + Lcd_Address(1 + i, 1); + for (int j = 0; j < 132; j++) + { + Lcd_Transfer_data(0x00); + } + } + spi_cs.setValue(Gpio::High); +} diff --git a/display/Lcd.h b/display/Lcd.h new file mode 100644 index 0000000..7028e3b --- /dev/null +++ b/display/Lcd.h @@ -0,0 +1,61 @@ +#pragma once +#include +#include +#include +#include +#include +#include "Gpio.h" + +class Lcd +{ +private: + Gpio spi_sck; + Gpio spi_sda; + Gpio spi_cs; + Gpio spi_reset; + Gpio spi_rs; + Gpio COM_BOOT0; + +public: + Lcd(); + /*=======写指令========*/ + void Lcd_Transfer_Command(int data1); + + /*--------写数据------------*/ + void Lcd_Transfer_data(int data1); + + /*LCD模块初始化*/ + void Lcd_Initial_Lcd(bool biglcd); + + void Lcd_Address(unsigned char page, unsigned char column); + + /*全屏清屏*/ + void Lcd_Clear_screen(); + + void Lcd_Clear_Half_Screen(bool top); + + //===显示测试画面:例如全显示,隔行显示,隔列显示,雪花显示===== + void Lcd_Test_Display(unsigned char data1, unsigned char data2); + + /*显示128x64点阵图像*/ + void Lcd_Display_Graphic_128x64(unsigned char page, unsigned char column, unsigned char *dp); + + /*显示32x32点阵图像、汉字、生僻字或32x32点阵的其他图标*/ + void Lcd_Display_graphic_32x32(unsigned char page, unsigned char column, unsigned char *dp); + + /*显示16x16点阵图像、汉字、生僻字或16x16点阵的其他图标*/ + void Lcd_Display_Graphic_16x16_2(unsigned char reverse,unsigned char page,unsigned char column,unsigned char *dp); + + /*显示16x16点阵图像、汉字、生僻字或16x16点阵的其他图标*/ + void Lcd_Display_Graphic_16x16(unsigned char page, unsigned char column, unsigned char *dp,unsigned int wordcount); + + /*显示8x16点阵图像、ASCII, 或8x16点阵的自造字符、其他图标*/ + void Lcd_Display_Graphic_8x16(unsigned char page, unsigned char column,unsigned char *dp); + + void Lcd_Display_String_8x16(unsigned int page, unsigned int column, const char *text); + + void Lcd_Display_String_5x8(unsigned int page, unsigned int column, const char *text); + +}; + + diff --git a/fpgaupdate/CMakeLists.txt b/fpgaupdate/CMakeLists.txt new file mode 100644 index 0000000..2862ba7 --- /dev/null +++ b/fpgaupdate/CMakeLists.txt @@ -0,0 +1,21 @@ +project(fpgaupdate) +add_compile_options(-std=c++14) +#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -O2") +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -O2") + +aux_source_directory(${PROJECT_SOURCE_DIR} DIR_SRCS) +file(GLOB DIR_HEADS "${PROJECT_SOURCE_DIR}/*.h" "${PROJECT_SOURCE_DIR}/*.hpp") +set(DIR_SRCS ${DIR_SRCS} ${DIR_HEADS}) + +add_library(${PROJECT_NAME} STATIC ${DIR_SRCS}) + +# target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR} +# ${PROJECT_SOURCE_DIR}/../3rdparty/nick +# ${PROJECT_SOURCE_DIR}/../ImageProcess +# ${PROJECT_SOURCE_DIR}/../3rdparty/opencv/include +# ${PROJECT_SOURCE_DIR}/../3rdparty/tiff/include +# ${PROJECT_SOURCE_DIR}/../../../sdk/include +# ${PROJECT_SOURCE_DIR}/../wrapper +# ) + +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../bin) \ No newline at end of file diff --git a/fpgaupdate/fpgacontrol.cpp b/fpgaupdate/fpgacontrol.cpp new file mode 100644 index 0000000..b10b7d8 --- /dev/null +++ b/fpgaupdate/fpgacontrol.cpp @@ -0,0 +1,121 @@ +#include "fpgacontrol.h" +#include "libmtd.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MTD_NODE "/dev/mtd0" +#define FPGAFILEPATH "/etc/fpgaupdatefile.bin" + +fpgacontrol::fpgacontrol() : m_fpgafile_fd(0), + m_updateEnable(false) +{ + // printf("fpga version : %d \n", fpgaversion); +} + +fpgacontrol::~fpgacontrol() +{ +} + +bool fpgacontrol::ifneedupdatefpga() +{ + if ((access(FPGAFILEPATH, F_OK)) != -1) + { + m_updateEnable = true; + printf("found %s file ,will update fpga later!\n", FPGAFILEPATH); + } + else + { + m_updateEnable = false; + printf("%s file do not exist!\n", FPGAFILEPATH); + } + return m_updateEnable; +} + +bool fpgacontrol::updatefpga() +{ + if (!m_updateEnable) + { + printf("checked don't need to update fpga\n"); + return false; + } + return updatefpgafirmware(FPGAFILEPATH); +} + +bool fpgacontrol::updatefpgafirmware(std::string fpgafirmpath) +{ + system("echo 68 > /sys/class/gpio/export"); + system("echo out > /sys/class/gpio/gpio68/direction"); + system("echo 0 > /sys/class/gpio/gpio68/value"); + if ((m_fpgafile_fd = open(MTD_NODE, O_RDWR)) <= 0) + { + printf("update fpga error,on open mtd node!\n"); + return false; + } + + libmtd_t desc; + desc = libmtd_open(); + if (NULL == desc) + { + printf("libmtd_open error...\n"); + return false; + } + mtd_dev_info dev_info; + mtd_get_dev_info(desc, MTD_NODE, &dev_info); + printf("mtd_num = %x\n", dev_info.mtd_num); + printf("major = %x\n", dev_info.major); + printf("minor = %x\n", dev_info.minor); + printf("type_str = %s\n", dev_info.type_str); + printf("name = %s\n", dev_info.name); + printf("size = %d\n", dev_info.size); + printf("eb_cnt = %d\n", dev_info.eb_cnt); + printf("eb_size = %d\n", dev_info.eb_size); + printf("min_io_size = %d\n", dev_info.min_io_size); + printf("subpage_size = %d\n", dev_info.subpage_size); + printf("oob_size = %d\n", dev_info.oob_size); + printf("region_cnt = %d\n", dev_info.region_cnt); + printf("writable = %d\n", dev_info.writable); + printf("bb_allowed = %d\n", dev_info.bb_allowed); + for (int i = 0; i < dev_info.eb_cnt; i++) + { + if (mtd_erase(desc, &dev_info, m_fpgafile_fd, i) != 0) + { + printf("mtd_erase error...........\n"); + if (desc) + { + libmtd_close(desc); + desc = NULL; + } + if (m_fpgafile_fd) + { + close(m_fpgafile_fd); + m_fpgafile_fd = NULL; + } + // system("echo 1 > /sys/class/gpio/gpio221/value"); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + return false; + } + } + + int ret = mtd_write_img(&dev_info, m_fpgafile_fd, 0, 0, fpgafirmpath.c_str()); + libmtd_close(desc); + if (ret < 0) + { + printf("mtd_write_img failed...........\n"); + return false; + } + else + { + printf("mtd_write_img success...........\n"); + std::string rmcmd = "rm -f /etc/fpgaupdatefile.bin"; + system(rmcmd.c_str()); + return true; + } +} \ No newline at end of file diff --git a/fpgaupdate/fpgacontrol.h b/fpgaupdate/fpgacontrol.h new file mode 100644 index 0000000..6aa19a5 --- /dev/null +++ b/fpgaupdate/fpgacontrol.h @@ -0,0 +1,23 @@ +#pragma once +#include + +class FpgaComm; + +class fpgacontrol +{ +private: + /* data */ +public: + fpgacontrol(); + ~fpgacontrol(); + bool ifneedupdatefpga(); + bool updatefpga(); + +private: + bool updatefpgafirmware(std::string fpgafirmpath); + +private: + int m_fpgaversion; + int m_fpgafile_fd; + bool m_updateEnable; +}; diff --git a/fpgaupdate/libmtd.c b/fpgaupdate/libmtd.c new file mode 100644 index 0000000..ba014d9 --- /dev/null +++ b/fpgaupdate/libmtd.c @@ -0,0 +1,1525 @@ +/* + * Copyright (c) International Business Machines Corp., 2006 + * Copyright (C) 2009 Nokia Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Artem Bityutskiy + * + * MTD library. + */ + +/* Imported from mtd-utils by dehrenberg */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "libmtd.h" + +#include "libmtd_int.h" +#include "libmtd_common.h" + +/** + * mkpath - compose full path from 2 given components. + * @path: the first component + * @name: the second component + * + * This function returns the resulting path in case of success and %NULL in + * case of failure. + */ +static char *mkpath(const char *path, const char *name) +{ + char *n; + size_t len1 = strlen(path); + size_t len2 = strlen(name); + + n = xmalloc(len1 + len2 + 6); + + memcpy(n, path, len1); + if (n[len1 - 1] != '/') + n[len1++] = '/'; + + memcpy(n + len1, name, len2 + 1); + return n; +} + +/** + * read_data - read data from a file. + * @file: the file to read from + * @buf: the buffer to read to + * @buf_len: buffer length + * + * This function returns number of read bytes in case of success and %-1 in + * case of failure. Note, if the file contains more then @buf_len bytes of + * date, this function fails with %EINVAL error code. + */ +static int read_data(const char *file, void *buf, int buf_len) +{ + int fd, rd, tmp, tmp1; + + fd = open(file, O_RDONLY | O_CLOEXEC); + if (fd == -1) + return -1; + + rd = read(fd, buf, buf_len); + if (rd == -1) + { + sys_errmsg("cannot read \"%s\"", file); + goto out_error; + } + + if (rd == buf_len) + { + errmsg("contents of \"%s\" is too long", file); + errno = EINVAL; + goto out_error; + } + + ((char *)buf)[rd] = '\0'; + + /* Make sure all data is read */ + tmp1 = read(fd, &tmp, 1); + if (tmp1 == 1) + { + sys_errmsg("cannot read \"%s\"", file); + goto out_error; + } + if (tmp1) + { + errmsg("file \"%s\" contains too much data (> %d bytes)", + file, buf_len); + errno = EINVAL; + goto out_error; + } + + if (close(fd)) + { + sys_errmsg("close failed on \"%s\"", file); + return -1; + } + + return rd; + +out_error: + close(fd); + return -1; +} + +/** + * read_major - read major and minor numbers from a file. + * @file: name of the file to read from + * @major: major number is returned here + * @minor: minor number is returned here + * + * This function returns % in case of success, and %-1 in case of failure. + */ +static int read_major(const char *file, int *major, int *minor) +{ + int ret; + char buf[50]; + + ret = read_data(file, buf, 50); + if (ret < 0) + return ret; + + ret = sscanf(buf, "%d:%d\n", major, minor); + if (ret != 2) + { + errno = EINVAL; + return errmsg("\"%s\" does not have major:minor format", file); + } + + if (*major < 0 || *minor < 0) + { + errno = EINVAL; + return errmsg("bad major:minor %d:%d in \"%s\"", + *major, *minor, file); + } + + return 0; +} + +/** + * dev_get_major - get major and minor numbers of an MTD device. + * @lib: libmtd descriptor + * @mtd_num: MTD device number + * @major: major number is returned here + * @minor: minor number is returned here + * + * This function returns zero in case of success and %-1 in case of failure. + */ +static int dev_get_major(struct libmtd *lib, int mtd_num, int *major, int *minor) +{ + char file[strlen(lib->mtd_dev) + 50]; + + sprintf(file, lib->mtd_dev, mtd_num); + return read_major(file, major, minor); +} + +/** + * dev_read_data - read data from an MTD device's sysfs file. + * @patt: file pattern to read from + * @mtd_num: MTD device number + * @buf: buffer to read to + * @buf_len: buffer length + * + * This function returns number of read bytes in case of success and %-1 in + * case of failure. + */ +static int dev_read_data(const char *patt, int mtd_num, void *buf, int buf_len) +{ + char file[strlen(patt) + 100]; + + sprintf(file, patt, mtd_num); + return read_data(file, buf, buf_len); +} + +/** + * read_hex_ll - read a hex 'long long' value from a file. + * @file: the file to read from + * @value: the result is stored here + * + * This function reads file @file and interprets its contents as hexadecimal + * 'long long' integer. If this is not true, it fails with %EINVAL error code. + * Returns %0 in case of success and %-1 in case of failure. + */ +static int read_hex_ll(const char *file, long long *value) +{ + int fd, rd; + char buf[50]; + + fd = open(file, O_RDONLY | O_CLOEXEC); + if (fd == -1) + return -1; + + rd = read(fd, buf, sizeof(buf)); + if (rd == -1) + { + sys_errmsg("cannot read \"%s\"", file); + goto out_error; + } + if (rd == sizeof(buf)) + { + errmsg("contents of \"%s\" is too long", file); + errno = EINVAL; + goto out_error; + } + buf[rd] = '\0'; + + if (sscanf(buf, "%llx\n", value) != 1) + { + errmsg("cannot read integer from \"%s\"\n", file); + errno = EINVAL; + goto out_error; + } + + if (*value < 0) + { + errmsg("negative value %lld in \"%s\"", *value, file); + errno = EINVAL; + goto out_error; + } + + if (close(fd)) + return sys_errmsg("close failed on \"%s\"", file); + + return 0; + +out_error: + close(fd); + return -1; +} + +/** + * read_pos_ll - read a positive 'long long' value from a file. + * @file: the file to read from + * @value: the result is stored here + * + * This function reads file @file and interprets its contents as a positive + * 'long long' integer. If this is not true, it fails with %EINVAL error code. + * Returns %0 in case of success and %-1 in case of failure. + */ +static int read_pos_ll(const char *file, long long *value) +{ + int fd, rd; + char buf[50]; + + fd = open(file, O_RDONLY | O_CLOEXEC); + if (fd == -1) + return -1; + + rd = read(fd, buf, 50); + if (rd == -1) + { + sys_errmsg("cannot read \"%s\"", file); + goto out_error; + } + if (rd == 50) + { + errmsg("contents of \"%s\" is too long", file); + errno = EINVAL; + goto out_error; + } + + if (sscanf(buf, "%lld\n", value) != 1) + { + errmsg("cannot read integer from \"%s\"\n", file); + errno = EINVAL; + goto out_error; + } + + if (*value < 0) + { + errmsg("negative value %lld in \"%s\"", *value, file); + errno = EINVAL; + goto out_error; + } + + if (close(fd)) + return sys_errmsg("close failed on \"%s\"", file); + + return 0; + +out_error: + close(fd); + return -1; +} + +/** + * read_hex_int - read an 'int' value from a file. + * @file: the file to read from + * @value: the result is stored here + * + * This function is the same as 'read_pos_ll()', but it reads an 'int' + * value, not 'long long'. + */ +static int read_hex_int(const char *file, int *value) +{ + long long res; + + if (read_hex_ll(file, &res)) + return -1; + + /* Make sure the value has correct range */ + if (res > INT_MAX || res < INT_MIN) + { + errmsg("value %lld read from file \"%s\" is out of range", + res, file); + errno = EINVAL; + return -1; + } + + *value = res; + return 0; +} + +/** + * read_pos_int - read a positive 'int' value from a file. + * @file: the file to read from + * @value: the result is stored here + * + * This function is the same as 'read_pos_ll()', but it reads an 'int' + * value, not 'long long'. + */ +static int read_pos_int(const char *file, int *value) +{ + long long res; + + if (read_pos_ll(file, &res)) + return -1; + + /* Make sure the value is not too big */ + if (res > INT_MAX) + { + errmsg("value %lld read from file \"%s\" is out of range", + res, file); + errno = EINVAL; + return -1; + } + + *value = res; + return 0; +} + +/** + * dev_read_hex_int - read an hex 'int' value from an MTD device sysfs file. + * @patt: file pattern to read from + * @mtd_num: MTD device number + * @value: the result is stored here + * + * This function returns %0 in case of success and %-1 in case of failure. + */ +static int dev_read_hex_int(const char *patt, int mtd_num, int *value) +{ + char file[strlen(patt) + 50]; + + sprintf(file, patt, mtd_num); + return read_hex_int(file, value); +} + +/** + * dev_read_pos_int - read a positive 'int' value from an MTD device sysfs file. + * @patt: file pattern to read from + * @mtd_num: MTD device number + * @value: the result is stored here + * + * This function returns %0 in case of success and %-1 in case of failure. + */ +static int dev_read_pos_int(const char *patt, int mtd_num, int *value) +{ + char file[strlen(patt) + 50]; + + sprintf(file, patt, mtd_num); + return read_pos_int(file, value); +} + +/** + * dev_read_pos_ll - read a positive 'long long' value from an MTD device sysfs file. + * @patt: file pattern to read from + * @mtd_num: MTD device number + * @value: the result is stored here + * + * This function returns %0 in case of success and %-1 in case of failure. + */ +static int dev_read_pos_ll(const char *patt, int mtd_num, long long *value) +{ + char file[strlen(patt) + 50]; + + sprintf(file, patt, mtd_num); + return read_pos_ll(file, value); +} + +/** + * type_str2int - convert MTD device type to integer. + * @str: MTD device type string to convert + * + * This function converts MTD device type string @str, read from sysfs, into an + * integer. + */ +static int type_str2int(const char *str) +{ + if (!strcmp(str, "nand")) + return MTD_NANDFLASH; + if (!strcmp(str, "mlc-nand")) + return MTD_MLCNANDFLASH; + if (!strcmp(str, "nor")) + return MTD_NORFLASH; + if (!strcmp(str, "rom")) + return MTD_ROM; + if (!strcmp(str, "absent")) + return MTD_ABSENT; + if (!strcmp(str, "dataflash")) + return MTD_DATAFLASH; + if (!strcmp(str, "ram")) + return MTD_RAM; + if (!strcmp(str, "ubi")) + return MTD_UBIVOLUME; + return -1; +} + +/** + * dev_node2num - find UBI device number by its character device node. + * @lib: MTD library descriptor + * @node: name of the MTD device node + * @mtd_num: MTD device number is returned here + * + * This function returns %0 in case of success and %-1 in case of failure. + */ +static int dev_node2num(struct libmtd *lib, const char *node, int *mtd_num) +{ + struct stat st; + int i, mjr, mnr; + struct mtd_info info; + + if (stat(node, &st)) + return sys_errmsg("cannot get information about \"%s\"", node); + + if (!S_ISCHR(st.st_mode)) + { + errmsg("\"%s\" is not a character device", node); + errno = EINVAL; + return -1; + } + + mjr = major(st.st_rdev); + mnr = minor(st.st_rdev); + + if (mtd_get_info((libmtd_t *)lib, &info)) + return -1; + + for (i = info.lowest_mtd_num; i <= info.highest_mtd_num; i++) + { + int mjr1, mnr1, ret; + + ret = dev_get_major(lib, i, &mjr1, &mnr1); + if (ret) + { + if (errno == ENOENT) + continue; + if (!errno) + break; + return -1; + } + + if (mjr1 == mjr && mnr1 == mnr) + { + errno = 0; + *mtd_num = i; + return 0; + } + } + + errno = ENODEV; + return -1; +} + +/** + * sysfs_is_supported - check whether the MTD sub-system supports MTD. + * @lib: MTD library descriptor + * + * The Linux kernel MTD subsystem gained MTD support starting from kernel + * 2.6.30 and libmtd tries to use sysfs interface if possible, because the NAND + * sub-page size is available there (and not available at all in pre-sysfs + * kernels). + * + * Very old kernels did not have "/sys/class/mtd" directory. Not very old + * kernels (e.g., 2.6.29) did have "/sys/class/mtd/mtdX" directories, by there + * were no files there, e.g., the "name" file was not present. So all we can do + * is to check for a "/sys/class/mtd/mtdX/name" file. But this is not a + * reliable check, because if this is a new system with no MTD devices - we'll + * treat it as a pre-sysfs system. + */ +static int sysfs_is_supported(struct libmtd *lib) +{ + int fd, num = -1; + DIR *sysfs_mtd; + char file[strlen(lib->mtd_name) + 10]; + + sysfs_mtd = opendir(lib->sysfs_mtd); + if (!sysfs_mtd) + { + if (errno == ENOENT) + { + errno = 0; + return 0; + } + return sys_errmsg("cannot open \"%s\"", lib->sysfs_mtd); + } + + /* + * First of all find an "mtdX" directory. This is needed because there + * may be, for example, mtd1 but no mtd0. + */ + while (1) + { + int ret, mtd_num; + char tmp_buf[256]; + struct dirent *dirent; + + dirent = readdir(sysfs_mtd); + if (!dirent) + break; + + if (strlen(dirent->d_name) >= 255) + { + errmsg("invalid entry in %s: \"%s\"", + lib->sysfs_mtd, dirent->d_name); + errno = EINVAL; + closedir(sysfs_mtd); + return -1; + } + + ret = sscanf(dirent->d_name, MTD_NAME_PATT "%s", + &mtd_num, tmp_buf); + if (ret == 1) + { + num = mtd_num; + break; + } + } + + if (closedir(sysfs_mtd)) + return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_mtd); + + if (num == -1) + /* No mtd device, treat this as pre-sysfs system */ + return 0; + + sprintf(file, lib->mtd_name, num); + fd = open(file, O_RDONLY | O_CLOEXEC); + if (fd == -1) + return 0; + + if (close(fd)) + { + sys_errmsg("close failed on \"%s\"", file); + return -1; + } + + return 1; +} + +libmtd_t libmtd_open(void) +{ + struct libmtd *lib; + + lib = xzalloc(sizeof(*lib)); + + lib->offs64_ioctls = OFFS64_IOCTLS_UNKNOWN; + + lib->sysfs_mtd = mkpath("/sys", SYSFS_MTD); + if (!lib->sysfs_mtd) + goto out_error; + + lib->mtd = mkpath(lib->sysfs_mtd, MTD_NAME_PATT); + if (!lib->mtd) + goto out_error; + + lib->mtd_name = mkpath(lib->mtd, MTD_NAME); + if (!lib->mtd_name) + goto out_error; + + if (!sysfs_is_supported(lib)) + { + free(lib->mtd); + free(lib->sysfs_mtd); + free(lib->mtd_name); + lib->mtd_name = lib->mtd = lib->sysfs_mtd = NULL; + return lib; + } + + lib->mtd_dev = mkpath(lib->mtd, MTD_DEV); + if (!lib->mtd_dev) + goto out_error; + + lib->mtd_type = mkpath(lib->mtd, MTD_TYPE); + if (!lib->mtd_type) + goto out_error; + + lib->mtd_eb_size = mkpath(lib->mtd, MTD_EB_SIZE); + if (!lib->mtd_eb_size) + goto out_error; + + lib->mtd_size = mkpath(lib->mtd, MTD_SIZE); + if (!lib->mtd_size) + goto out_error; + + lib->mtd_min_io_size = mkpath(lib->mtd, MTD_MIN_IO_SIZE); + if (!lib->mtd_min_io_size) + goto out_error; + + lib->mtd_subpage_size = mkpath(lib->mtd, MTD_SUBPAGE_SIZE); + if (!lib->mtd_subpage_size) + goto out_error; + + lib->mtd_oob_size = mkpath(lib->mtd, MTD_OOB_SIZE); + if (!lib->mtd_oob_size) + goto out_error; + + lib->mtd_region_cnt = mkpath(lib->mtd, MTD_REGION_CNT); + if (!lib->mtd_region_cnt) + goto out_error; + + lib->mtd_flags = mkpath(lib->mtd, MTD_FLAGS); + if (!lib->mtd_flags) + goto out_error; + + lib->sysfs_supported = 1; + return lib; + +out_error: + libmtd_close((libmtd_t)lib); + return NULL; +} + +void libmtd_close(libmtd_t desc) +{ + struct libmtd *lib = (struct libmtd *)desc; + + free(lib->mtd_flags); + free(lib->mtd_region_cnt); + free(lib->mtd_oob_size); + free(lib->mtd_subpage_size); + free(lib->mtd_min_io_size); + free(lib->mtd_size); + free(lib->mtd_eb_size); + free(lib->mtd_type); + free(lib->mtd_dev); + free(lib->mtd_name); + free(lib->mtd); + free(lib->sysfs_mtd); + free(lib); +} + +int mtd_dev_present(libmtd_t desc, int mtd_num) +{ + struct stat st; + struct libmtd *lib = (struct libmtd *)desc; + + if (!lib->sysfs_supported) + { + return legacy_dev_present(mtd_num) == 1; + } + else + { + char file[strlen(lib->mtd) + 10]; + + sprintf(file, lib->mtd, mtd_num); + return !stat(file, &st); + } +} + +int mtd_get_info(libmtd_t desc, struct mtd_info *info) +{ + DIR *sysfs_mtd; + struct dirent *dirent; + struct libmtd *lib = (struct libmtd *)desc; + + memset(info, 0, sizeof(struct mtd_info)); + + if (!lib->sysfs_supported) + return legacy_mtd_get_info(info); + + info->sysfs_supported = 1; + + /* + * We have to scan the MTD sysfs directory to identify how many MTD + * devices are present. + */ + sysfs_mtd = opendir(lib->sysfs_mtd); + if (!sysfs_mtd) + { + if (errno == ENOENT) + { + errno = ENODEV; + return -1; + } + return sys_errmsg("cannot open \"%s\"", lib->sysfs_mtd); + } + + info->lowest_mtd_num = INT_MAX; + while (1) + { + int mtd_num, ret; + char tmp_buf[256]; + + errno = 0; + dirent = readdir(sysfs_mtd); + if (!dirent) + break; + + if (strlen(dirent->d_name) >= 255) + { + errmsg("invalid entry in %s: \"%s\"", + lib->sysfs_mtd, dirent->d_name); + errno = EINVAL; + goto out_close; + } + + ret = sscanf(dirent->d_name, MTD_NAME_PATT "%s", + &mtd_num, tmp_buf); + if (ret == 1) + { + info->mtd_dev_cnt += 1; + if (mtd_num > info->highest_mtd_num) + info->highest_mtd_num = mtd_num; + if (mtd_num < info->lowest_mtd_num) + info->lowest_mtd_num = mtd_num; + } + } + + if (!dirent && errno) + { + sys_errmsg("readdir failed on \"%s\"", lib->sysfs_mtd); + goto out_close; + } + + if (closedir(sysfs_mtd)) + return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_mtd); + + if (info->lowest_mtd_num == INT_MAX) + info->lowest_mtd_num = 0; + + return 0; + +out_close: + closedir(sysfs_mtd); + return -1; +} + +int mtd_get_dev_info1(libmtd_t desc, int mtd_num, struct mtd_dev_info *mtd) +{ + int ret; + struct libmtd *lib = (struct libmtd *)desc; + + memset(mtd, 0, sizeof(struct mtd_dev_info)); + mtd->mtd_num = mtd_num; + + if (!mtd_dev_present(desc, mtd_num)) + { + errno = ENODEV; + return -1; + } + else if (!lib->sysfs_supported) + return legacy_get_dev_info1(mtd_num, mtd); + + if (dev_get_major(lib, mtd_num, &mtd->major, &mtd->minor)) + return -1; + + ret = dev_read_data(lib->mtd_name, mtd_num, &mtd->name, + MTD_NAME_MAX + 1); + if (ret < 0) + return -1; + ((char *)mtd->name)[ret - 1] = '\0'; + + ret = dev_read_data(lib->mtd_type, mtd_num, &mtd->type_str, + MTD_TYPE_MAX + 1); + if (ret < 0) + return -1; + ((char *)mtd->type_str)[ret - 1] = '\0'; + + if (dev_read_pos_int(lib->mtd_eb_size, mtd_num, &mtd->eb_size)) + return -1; + if (dev_read_pos_ll(lib->mtd_size, mtd_num, &mtd->size)) + return -1; + if (dev_read_pos_int(lib->mtd_min_io_size, mtd_num, &mtd->min_io_size)) + return -1; + if (dev_read_pos_int(lib->mtd_subpage_size, mtd_num, &mtd->subpage_size)) + return -1; + if (dev_read_pos_int(lib->mtd_oob_size, mtd_num, &mtd->oob_size)) + return -1; + if (dev_read_pos_int(lib->mtd_region_cnt, mtd_num, &mtd->region_cnt)) + return -1; + if (dev_read_hex_int(lib->mtd_flags, mtd_num, &ret)) + return -1; + mtd->writable = !!(ret & MTD_WRITEABLE); + + mtd->eb_cnt = mtd->size / mtd->eb_size; + mtd->type = type_str2int(mtd->type_str); + mtd->bb_allowed = !!(mtd->type == MTD_NANDFLASH || + mtd->type == MTD_MLCNANDFLASH); + + return 0; +} + +int mtd_get_dev_info(libmtd_t desc, const char *node, struct mtd_dev_info *mtd) +{ + int mtd_num; + struct libmtd *lib = (struct libmtd *)desc; + + if (!lib->sysfs_supported) + return legacy_get_dev_info(node, mtd); + + if (dev_node2num(lib, node, &mtd_num)) + return -1; + + return mtd_get_dev_info1(desc, mtd_num, mtd); +} + +static inline int mtd_ioctl_error(const struct mtd_dev_info *mtd, int eb, + const char *sreq) +{ + return sys_errmsg("%s ioctl failed for eraseblock %d (mtd%d)", + sreq, eb, mtd->mtd_num); +} + +static int mtd_valid_erase_block(const struct mtd_dev_info *mtd, int eb) +{ + printf("hello 2 \n"); + if (eb < 0 || eb >= mtd->eb_cnt) + { + printf("bad eraseblock number %d, mtd%d has %d eraseblocks", + eb, mtd->mtd_num, mtd->eb_cnt); + errno = EINVAL; + printf("hello 33333333333333333333333 \n"); + return -1; + } + return 0; +} + +static int mtd_xlock(const struct mtd_dev_info *mtd, int fd, int eb, int req, + const char *sreq) +{ + int ret; + struct erase_info_user ei; + + ret = mtd_valid_erase_block(mtd, eb); + if (ret) + return ret; + + ei.start = eb * mtd->eb_size; + ei.length = mtd->eb_size; + + ret = ioctl(fd, req, &ei); + if (ret < 0) + return mtd_ioctl_error(mtd, eb, sreq); + + return 0; +} +#define mtd_xlock(mtd, fd, eb, req) mtd_xlock(mtd, fd, eb, req, #req) + +int mtd_lock(const struct mtd_dev_info *mtd, int fd, int eb) +{ + return mtd_xlock(mtd, fd, eb, MEMLOCK); +} + +int mtd_unlock(const struct mtd_dev_info *mtd, int fd, int eb) +{ + return mtd_xlock(mtd, fd, eb, MEMUNLOCK); +} + +int mtd_erase(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb) +{ + int ret; + struct libmtd *lib = (struct libmtd *)desc; + struct erase_info_user64 ei64; + struct erase_info_user ei; + + ret = mtd_valid_erase_block(mtd, eb); + if (ret) + return ret; + + ei64.start = (__u64)eb * mtd->eb_size; + ei64.length = mtd->eb_size; + + if (lib->offs64_ioctls == OFFS64_IOCTLS_SUPPORTED || + lib->offs64_ioctls == OFFS64_IOCTLS_UNKNOWN) + { + ret = ioctl(fd, MEMERASE64, &ei64); + if (ret == 0) + return ret; + + if (errno != ENOTTY || + lib->offs64_ioctls != OFFS64_IOCTLS_UNKNOWN) + return mtd_ioctl_error(mtd, eb, "MEMERASE64"); + + /* + * MEMERASE64 support was added in kernel version 2.6.31, so + * probably we are working with older kernel and this ioctl is + * not supported. + */ + lib->offs64_ioctls = OFFS64_IOCTLS_NOT_SUPPORTED; + } + + if (ei64.start + ei64.length > 0xFFFFFFFF) + { + errmsg("this system can address only %u eraseblocks", + 0xFFFFFFFFU / mtd->eb_size); + errno = EINVAL; + return -1; + } + + ei.start = ei64.start; + ei.length = ei64.length; + ret = ioctl(fd, MEMERASE, &ei); + if (ret < 0) + return mtd_ioctl_error(mtd, eb, "MEMERASE"); + return 0; +} + +int mtd_regioninfo(int fd, int regidx, struct region_info_user *reginfo) +{ + int ret; + + if (regidx < 0) + { + errno = ENODEV; + return -1; + } + + reginfo->regionindex = regidx; + + ret = ioctl(fd, MEMGETREGIONINFO, reginfo); + if (ret < 0) + return sys_errmsg("%s ioctl failed for erase region %d", + "MEMGETREGIONINFO", regidx); + + return 0; +} + +int mtd_is_locked(const struct mtd_dev_info *mtd, int fd, int eb) +{ + int ret; + erase_info_t ei; + + ei.start = eb * mtd->eb_size; + ei.length = mtd->eb_size; + + ret = ioctl(fd, MEMISLOCKED, &ei); + if (ret < 0) + { + if (errno != ENOTTY && errno != EOPNOTSUPP) + return mtd_ioctl_error(mtd, eb, "MEMISLOCKED"); + else + errno = EOPNOTSUPP; + } + + return ret; +} + +/* Patterns to write to a physical eraseblock when torturing it */ +static uint8_t patterns[] = {0xa5, 0x5a, 0x0}; + +/** + * check_pattern - check if buffer contains only a certain byte pattern. + * @buf: buffer to check + * @patt: the pattern to check + * @size: buffer size in bytes + * + * This function returns %1 in there are only @patt bytes in @buf, and %0 if + * something else was also found. + */ +static int check_pattern(const void *buf, uint8_t patt, int size) +{ + int i; + + for (i = 0; i < size; i++) + if (((const uint8_t *)buf)[i] != patt) + return 0; + return 1; +} + +int mtd_torture(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb) +{ + int err, i, patt_count; + void *buf; + + normsg("run torture test for PEB %d", eb); + patt_count = ARRAY_SIZE(patterns); + + buf = xmalloc(mtd->eb_size); + + for (i = 0; i < patt_count; i++) + { + err = mtd_erase(desc, mtd, fd, eb); + if (err) + goto out; + + /* Make sure the PEB contains only 0xFF bytes */ + err = mtd_read(mtd, fd, eb, 0, buf, mtd->eb_size); + if (err) + goto out; + + err = check_pattern(buf, 0xFF, mtd->eb_size); + if (err == 0) + { + errmsg("erased PEB %d, but a non-0xFF byte found", eb); + errno = EIO; + goto out; + } + + /* Write a pattern and check it */ + memset(buf, patterns[i], mtd->eb_size); + err = mtd_write(desc, mtd, fd, eb, 0, buf, mtd->eb_size, NULL, + 0, 0); + if (err) + goto out; + + memset(buf, ~patterns[i], mtd->eb_size); + err = mtd_read(mtd, fd, eb, 0, buf, mtd->eb_size); + if (err) + goto out; + + err = check_pattern(buf, patterns[i], mtd->eb_size); + if (err == 0) + { + errmsg("pattern %x checking failed for PEB %d", + patterns[i], eb); + errno = EIO; + goto out; + } + } + + err = 0; + normsg("PEB %d passed torture test, do not mark it a bad", eb); + +out: + free(buf); + return -1; +} + +int mtd_is_bad(const struct mtd_dev_info *mtd, int fd, int eb) +{ + int ret; + loff_t seek; + + ret = mtd_valid_erase_block(mtd, eb); + if (ret) + return ret; + + if (!mtd->bb_allowed) + return 0; + + seek = (loff_t)eb * mtd->eb_size; + ret = ioctl(fd, MEMGETBADBLOCK, &seek); + if (ret == -1) + return mtd_ioctl_error(mtd, eb, "MEMGETBADBLOCK"); + return ret; +} + +int mtd_mark_bad(const struct mtd_dev_info *mtd, int fd, int eb) +{ + int ret; + loff_t seek; + + if (!mtd->bb_allowed) + { + errno = EINVAL; + return -1; + } + + ret = mtd_valid_erase_block(mtd, eb); + if (ret) + return ret; + + seek = (loff_t)eb * mtd->eb_size; + ret = ioctl(fd, MEMSETBADBLOCK, &seek); + if (ret == -1) + return mtd_ioctl_error(mtd, eb, "MEMSETBADBLOCK"); + return 0; +} + +int mtd_read(const struct mtd_dev_info *mtd, int fd, int eb, int offs, + void *buf, int len) +{ + int ret, rd = 0; + off_t seek; + + ret = mtd_valid_erase_block(mtd, eb); + if (ret) + return ret; + + if (offs < 0 || offs + len > mtd->eb_size) + { + errmsg("bad offset %d or length %d, mtd%d eraseblock size is %d", + offs, len, mtd->mtd_num, mtd->eb_size); + errno = EINVAL; + return -1; + } + + /* Seek to the beginning of the eraseblock */ + seek = (off_t)eb * mtd->eb_size + offs; + if (lseek(fd, seek, SEEK_SET) != seek) + return sys_errmsg("cannot seek mtd%d to offset %" PRIdoff_t, + mtd->mtd_num, seek); + + while (rd < len) + { + ret = read(fd, buf, len); + if (ret < 0) + return sys_errmsg("cannot read %d bytes from mtd%d (eraseblock %d, offset %d)", + len, mtd->mtd_num, eb, offs); + rd += ret; + } + + return 0; +} + +static int legacy_auto_oob_layout(const struct mtd_dev_info *mtd, int fd, + int ooblen, void *oob) +{ + struct nand_oobinfo old_oobinfo; + int start, len; + uint8_t *tmp_buf; + + /* Read the current oob info */ + if (ioctl(fd, MEMGETOOBSEL, &old_oobinfo)) + return sys_errmsg("MEMGETOOBSEL failed"); + + tmp_buf = malloc(ooblen); + memcpy(tmp_buf, oob, ooblen); + + /* + * We use autoplacement and have the oobinfo with the autoplacement + * information from the kernel available + */ + if (old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE) + { + int i, tags_pos = 0; + for (i = 0; old_oobinfo.oobfree[i][1]; i++) + { + /* Set the reserved bytes to 0xff */ + start = old_oobinfo.oobfree[i][0]; + len = old_oobinfo.oobfree[i][1]; + memcpy(oob + start, tmp_buf + tags_pos, len); + tags_pos += len; + } + } + else + { + /* Set at least the ecc byte positions to 0xff */ + start = old_oobinfo.eccbytes; + len = mtd->oob_size - start; + memcpy(oob + start, tmp_buf + start, len); + } + free(tmp_buf); + + return 0; +} + +int mtd_write(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb, + int offs, void *data, int len, void *oob, int ooblen, + uint8_t mode) +{ + int ret; + off_t seek; + struct mtd_write_req ops; + + ret = mtd_valid_erase_block(mtd, eb); + if (ret) + return ret; + + if (offs < 0 || offs + len > mtd->eb_size) + { + errmsg("bad offset %d or length %d, mtd%d eraseblock size is %d", + offs, len, mtd->mtd_num, mtd->eb_size); + errno = EINVAL; + return -1; + } + if (offs % mtd->subpage_size) + { + errmsg("write offset %d is not aligned to mtd%d min. I/O size %d", + offs, mtd->mtd_num, mtd->subpage_size); + errno = EINVAL; + return -1; + } + if (len % mtd->subpage_size) + { + errmsg("write length %d is not aligned to mtd%d min. I/O size %d", + len, mtd->mtd_num, mtd->subpage_size); + errno = EINVAL; + return -1; + } + + /* Calculate seek address */ + seek = (off_t)eb * mtd->eb_size + offs; + + if (oob) + { + ops.start = seek; + ops.len = len; + ops.ooblen = ooblen; + ops.usr_data = (uint64_t)(unsigned long)data; + ops.usr_oob = (uint64_t)(unsigned long)oob; + ops.mode = mode; + + ret = ioctl(fd, MEMWRITE, &ops); + if (ret == 0) + return 0; + else if (errno != ENOTTY && errno != EOPNOTSUPP) + return mtd_ioctl_error(mtd, eb, "MEMWRITE"); + + /* Fall back to old OOB ioctl() if necessary */ + if (mode == MTD_OPS_AUTO_OOB) + if (legacy_auto_oob_layout(mtd, fd, ooblen, oob)) + return -1; + if (mtd_write_oob(desc, mtd, fd, seek, ooblen, oob) < 0) + return sys_errmsg("cannot write to OOB"); + } + if (data) + { + /* Seek to the beginning of the eraseblock */ + if (lseek(fd, seek, SEEK_SET) != seek) + return sys_errmsg("cannot seek mtd%d to offset %" PRIdoff_t, + mtd->mtd_num, seek); + ret = write(fd, data, len); + if (ret != len) + return sys_errmsg("cannot write %d bytes to mtd%d " + "(eraseblock %d, offset %d)", + len, mtd->mtd_num, eb, offs); + } + + return 0; +} + +static int do_oob_op(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, + uint64_t start, uint64_t length, void *data, unsigned int cmd64, + unsigned int cmd) +{ + int ret, oob_offs; + struct mtd_oob_buf64 oob64; + struct mtd_oob_buf oob; + unsigned long long max_offs; + const char *cmd64_str, *cmd_str; + struct libmtd *lib = (struct libmtd *)desc; + + if (cmd64 == MEMREADOOB64) + { + cmd64_str = "MEMREADOOB64"; + cmd_str = "MEMREADOOB"; + } + else + { + cmd64_str = "MEMWRITEOOB64"; + cmd_str = "MEMWRITEOOB"; + } + + max_offs = (unsigned long long)mtd->eb_cnt * mtd->eb_size; + if (start >= max_offs) + { + errmsg("bad page address %" PRIu64 ", mtd%d has %d eraseblocks (%llu bytes)", + start, mtd->mtd_num, mtd->eb_cnt, max_offs); + errno = EINVAL; + return -1; + } + + oob_offs = start & (mtd->min_io_size - 1); + if (oob_offs + length > mtd->oob_size || length == 0) + { + errmsg("Cannot write %" PRIu64 " OOB bytes to address %" PRIu64 " (OOB offset %u) - mtd%d OOB size is only %d bytes", + length, start, oob_offs, mtd->mtd_num, mtd->oob_size); + errno = EINVAL; + return -1; + } + + oob64.start = start; + oob64.length = length; + oob64.usr_ptr = (uint64_t)(unsigned long)data; + + if (lib->offs64_ioctls == OFFS64_IOCTLS_SUPPORTED || + lib->offs64_ioctls == OFFS64_IOCTLS_UNKNOWN) + { + ret = ioctl(fd, cmd64, &oob64); + if (ret == 0) + return ret; + + if (errno != ENOTTY || + lib->offs64_ioctls != OFFS64_IOCTLS_UNKNOWN) + { + sys_errmsg("%s ioctl failed for mtd%d, offset %" PRIu64 " (eraseblock %" PRIu64 ")", + cmd64_str, mtd->mtd_num, start, start / mtd->eb_size); + } + + /* + * MEMREADOOB64/MEMWRITEOOB64 support was added in kernel + * version 2.6.31, so probably we are working with older kernel + * and these ioctls are not supported. + */ + lib->offs64_ioctls = OFFS64_IOCTLS_NOT_SUPPORTED; + } + + if (oob64.start > 0xFFFFFFFFULL) + { + errmsg("this system can address only up to address %lu", + 0xFFFFFFFFUL); + errno = EINVAL; + return -1; + } + + oob.start = oob64.start; + oob.length = oob64.length; + oob.ptr = data; + + ret = ioctl(fd, cmd, &oob); + if (ret < 0) + sys_errmsg("%s ioctl failed for mtd%d, offset %" PRIu64 " (eraseblock %" PRIu64 ")", + cmd_str, mtd->mtd_num, start, start / mtd->eb_size); + return ret; +} + +int mtd_read_oob(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, + uint64_t start, uint64_t length, void *data) +{ + return do_oob_op(desc, mtd, fd, start, length, data, + MEMREADOOB64, MEMREADOOB); +} + +int mtd_write_oob(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, + uint64_t start, uint64_t length, void *data) +{ + return do_oob_op(desc, mtd, fd, start, length, data, + MEMWRITEOOB64, MEMWRITEOOB); +} + +int mtd_write_img(const struct mtd_dev_info *mtd, int fd, int eb, int offs, + const char *img_name) +{ + int tmp, ret, in_fd, len, written = 0; + off_t seek; + struct stat st; + char *buf; + printf("hello 1 \n"); + ret = mtd_valid_erase_block(mtd, eb); + printf("hello 3 \n"); + if (ret) + { + printf("hello 1 ret= %d\n", ret); + return ret; + } + + printf("hello 4 \n"); + if (offs < 0 || offs >= mtd->eb_size) + { + printf("bad offset %d, mtd%d eraseblock size is %d", + offs, mtd->mtd_num, mtd->eb_size); + errno = EINVAL; + return -1; + } + printf("hello 5 \n"); + if (offs % mtd->subpage_size) + { + printf("write offset %d is not aligned to mtd%d min. I/O size %d", + offs, mtd->mtd_num, mtd->subpage_size); + errno = EINVAL; + return -1; + } + + printf("hello 6 \n"); + in_fd = open(img_name, O_RDONLY | O_CLOEXEC); + if (in_fd == -1) + return printf("cannot open \"%s\"", img_name); + + printf("hello 7 \n"); + if (fstat(in_fd, &st)) + { + printf("cannot stat %s", img_name); + goto out_close; + } + printf("hello 8 \n"); + len = st.st_size; + printf("hello 8 len=%d \n", len); + if (len % mtd->subpage_size) + { + printf("size of \"%s\" is %d byte, which is not aligned to " + "mtd%d min. I/O size %d", + img_name, len, mtd->mtd_num, + mtd->subpage_size); + errno = EINVAL; + goto out_close; + } + printf("hello 9 \n"); + tmp = (offs + len + mtd->eb_size - 1) / mtd->eb_size; + if (eb + tmp > mtd->eb_cnt) + { + printf("\"%s\" image size is %d bytes, mtd%d size is %d " + "eraseblocks, the image does not fit if we write it " + "starting from eraseblock %d, offset %d", + img_name, len, mtd->mtd_num, mtd->eb_cnt, eb, offs); + errno = EINVAL; + goto out_close; + } + printf("hello 10 \n"); + /* Seek to the beginning of the eraseblock */ + seek = (off_t)eb * mtd->eb_size + offs; + if (lseek(fd, seek, SEEK_SET) != seek) + { + printf("cannot seek mtd%d to offset %" PRIdoff_t, + mtd->mtd_num, seek); + goto out_close; + } + + printf("hello 11 \n"); + buf = xmalloc(mtd->eb_size); + printf("hello 12 \n"); + while (written < len) + { + int rd = 0; + + do + { + ret = read(in_fd, buf, mtd->eb_size - offs - rd); + printf("hello 13 ret=%d \n", ret); + if (ret == -1) + { + printf("cannot read %s", img_name); + printf("hello 13 \n"); + goto out_free; + } + rd += ret; + } while (ret && rd < mtd->eb_size - offs); + + ret = write(fd, buf, rd); + printf("hello 14 ret=%d \n", ret); + if (ret != rd) + { + printf("cannot write %d bytes to mtd%d (eraseblock %d, offset %d)", + len, mtd->mtd_num, eb, offs); + printf("hello 14 \n"); + goto out_free; + } + + offs = 0; + eb += 1; + written += rd; + } + + free(buf); + close(in_fd); + return 0; + +out_free: + free(buf); +out_close: + close(in_fd); + return -1; +} + +int mtd_probe_node(libmtd_t desc, const char *node) +{ + struct stat st; + struct mtd_info info; + int i, mjr, mnr; + struct libmtd *lib = (struct libmtd *)desc; + + if (stat(node, &st)) + return sys_errmsg("cannot get information about \"%s\"", node); + + if (!S_ISCHR(st.st_mode)) + { + errmsg("\"%s\" is not a character device", node); + errno = EINVAL; + return -1; + } + + mjr = major(st.st_rdev); + mnr = minor(st.st_rdev); + + if (mtd_get_info((libmtd_t *)lib, &info)) + return -1; + + if (!lib->sysfs_supported) + return 0; + + for (i = info.lowest_mtd_num; i <= info.highest_mtd_num; i++) + { + int mjr1, mnr1, ret; + + ret = dev_get_major(lib, i, &mjr1, &mnr1); + if (ret) + { + if (errno == ENOENT) + continue; + if (!errno) + break; + return -1; + } + + if (mjr1 == mjr && mnr1 == mnr) + return 1; + } + + errno = 0; + return -1; +} diff --git a/fpgaupdate/libmtd.h b/fpgaupdate/libmtd.h new file mode 100644 index 0000000..9eb3a09 --- /dev/null +++ b/fpgaupdate/libmtd.h @@ -0,0 +1,358 @@ +/* + * Copyright (C) 2008, 2009 Nokia Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Artem Bityutskiy + * + * MTD library. + */ + +/* Imported from mtd-utils by dehrenberg */ + +#ifndef __LIBMTD_H__ +#define __LIBMTD_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +// Needed for uint8_t, uint64_t +#include + +/* Maximum MTD device name length */ +#define MTD_NAME_MAX 127 +/* Maximum MTD device type string length */ +#define MTD_TYPE_MAX 64 + + /* MTD library descriptor */ + typedef void *libmtd_t; + + /* Forward decls */ + struct region_info_user; + + /** + * @mtd_dev_cnt: count of MTD devices in system + * @lowest_mtd_num: lowest MTD device number in system + * @highest_mtd_num: highest MTD device number in system + * @sysfs_supported: non-zero if sysfs is supported by MTD + */ + struct mtd_info + { + int mtd_dev_cnt; + int lowest_mtd_num; + int highest_mtd_num; + unsigned int sysfs_supported : 1; + }; + + /** + * struct mtd_dev_info - information about an MTD device. + * @mtd_num: MTD device number + * @major: major number of corresponding character device + * @minor: minor number of corresponding character device + * @type: flash type (constants like %MTD_NANDFLASH defined in mtd-abi.h) + * @type_str: static R/O flash type string + * @name: device name + * @size: device size in bytes + * @eb_cnt: count of eraseblocks + * @eb_size: eraseblock size + * @min_io_size: minimum input/output unit size + * @subpage_size: sub-page size + * @oob_size: OOB size (zero if the device does not have OOB area) + * @region_cnt: count of additional erase regions + * @writable: zero if the device is read-only + * @bb_allowed: non-zero if the MTD device may have bad eraseblocks + */ + struct mtd_dev_info + { + int mtd_num; + int major; + int minor; + int type; + char type_str[MTD_TYPE_MAX + 1]; + char name[MTD_NAME_MAX + 1]; + long long size; + int eb_cnt; + int eb_size; + int min_io_size; + int subpage_size; + int oob_size; + int region_cnt; + unsigned int writable : 1; + unsigned int bb_allowed : 1; + }; + + /** + * libmtd_open - open MTD library. + * + * This function initializes and opens the MTD library and returns MTD library + * descriptor in case of success and %NULL in case of failure. In case of + * failure, errno contains zero if MTD is not present in the system, or + * contains the error code if a real error happened. + */ + libmtd_t libmtd_open(void); + + /** + * libmtd_close - close MTD library. + * @desc: MTD library descriptor + */ + void libmtd_close(libmtd_t desc); + + /** + * mtd_dev_present - check whether a MTD device is present. + * @desc: MTD library descriptor + * @mtd_num: MTD device number to check + * + * This function returns %1 if MTD device is present and %0 if not. + */ + int mtd_dev_present(libmtd_t desc, int mtd_num); + + /** + * mtd_get_info - get general MTD information. + * @desc: MTD library descriptor + * @info: the MTD device information is returned here + * + * This function fills the passed @info object with general MTD information and + * returns %0 in case of success and %-1 in case of failure. If MTD subsystem is + * not present in the system, errno is set to @ENODEV. + */ + int mtd_get_info(libmtd_t desc, struct mtd_info *info); + + /** + * mtd_get_dev_info - get information about an MTD device. + * @desc: MTD library descriptor + * @node: name of the MTD device node + * @mtd: the MTD device information is returned here + * + * This function gets information about MTD device defined by the @node device + * node file and saves this information in the @mtd object. Returns %0 in case + * of success and %-1 in case of failure. If MTD subsystem is not present in the + * system, or the MTD device does not exist, errno is set to @ENODEV. + */ + int mtd_get_dev_info(libmtd_t desc, const char *node, struct mtd_dev_info *mtd); + + /** + * mtd_get_dev_info1 - get information about an MTD device. + * @desc: MTD library descriptor + * @mtd_num: MTD device number to fetch information about + * @mtd: the MTD device information is returned here + * + * This function is identical to 'mtd_get_dev_info()' except that it accepts + * MTD device number, not MTD character device. + */ + int mtd_get_dev_info1(libmtd_t desc, int mtd_num, struct mtd_dev_info *mtd); + + /** + * mtd_lock - lock eraseblocks. + * @desc: MTD library descriptor + * @mtd: MTD device description object + * @fd: MTD device node file descriptor + * @eb: eraseblock to lock + * + * This function locks eraseblock @eb. Returns %0 in case of success and %-1 + * in case of failure. + */ + int mtd_lock(const struct mtd_dev_info *mtd, int fd, int eb); + + /** + * mtd_unlock - unlock eraseblocks. + * @desc: MTD library descriptor + * @mtd: MTD device description object + * @fd: MTD device node file descriptor + * @eb: eraseblock to lock + * + * This function unlocks eraseblock @eb. Returns %0 in case of success and %-1 + * in case of failure. + */ + int mtd_unlock(const struct mtd_dev_info *mtd, int fd, int eb); + + /** + * mtd_erase - erase an eraseblock. + * @desc: MTD library descriptor + * @mtd: MTD device description object + * @fd: MTD device node file descriptor + * @eb: eraseblock to erase + * + * This function erases eraseblock @eb of MTD device described by @fd. Returns + * %0 in case of success and %-1 in case of failure. + */ + int mtd_erase(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb); + + /** + * mtd_regioninfo - get information about an erase region. + * @fd: MTD device node file descriptor + * @regidx: index of region to look up + * @reginfo: the region information is returned here + * + * This function gets information about an erase region defined by the + * @regidx index and saves this information in the @reginfo object. + * Returns %0 in case of success and %-1 in case of failure. If the + * @regidx is not valid or unavailable, errno is set to @ENODEV. + */ + int mtd_regioninfo(int fd, int regidx, struct region_info_user *reginfo); + + /** + * mtd_is_locked - see if the specified eraseblock is locked. + * @mtd: MTD device description object + * @fd: MTD device node file descriptor + * @eb: eraseblock to check + * + * This function checks to see if eraseblock @eb of MTD device described + * by @fd is locked. Returns %0 if it is unlocked, %1 if it is locked, and + * %-1 in case of failure. If the ioctl is not supported (support was added in + * Linux kernel 2.6.36) or this particular device does not support it, errno is + * set to @ENOTSUPP. + */ + int mtd_is_locked(const struct mtd_dev_info *mtd, int fd, int eb); + + /** + * mtd_torture - torture an eraseblock. + * @desc: MTD library descriptor + * @mtd: MTD device description object + * @fd: MTD device node file descriptor + * @eb: eraseblock to torture + * + * This function tortures eraseblock @eb. Returns %0 in case of success and %-1 + * in case of failure. + */ + int mtd_torture(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb); + + /** + * mtd_is_bad - check if eraseblock is bad. + * @mtd: MTD device description object + * @fd: MTD device node file descriptor + * @eb: eraseblock to check + * + * This function checks if eraseblock @eb is bad. Returns %0 if not, %1 if yes, + * and %-1 in case of failure. + */ + int mtd_is_bad(const struct mtd_dev_info *mtd, int fd, int eb); + + /** + * mtd_mark_bad - mark an eraseblock as bad. + * @mtd: MTD device description object + * @fd: MTD device node file descriptor + * @eb: eraseblock to mark as bad + * + * This function marks eraseblock @eb as bad. Returns %0 in case of success and + * %-1 in case of failure. + */ + int mtd_mark_bad(const struct mtd_dev_info *mtd, int fd, int eb); + + /** + * mtd_read - read data from an MTD device. + * @mtd: MTD device description object + * @fd: MTD device node file descriptor + * @eb: eraseblock to read from + * @offs: offset withing the eraseblock to read from + * @buf: buffer to read data to + * @len: how many bytes to read + * + * This function reads @len bytes of data from eraseblock @eb and offset @offs + * of the MTD device defined by @mtd and stores the read data at buffer @buf. + * Returns %0 in case of success and %-1 in case of failure. + */ + int mtd_read(const struct mtd_dev_info *mtd, int fd, int eb, int offs, + void *buf, int len); + + /** + * mtd_write - write data to an MTD device. + * @desc: MTD library descriptor + * @mtd: MTD device description object + * @fd: MTD device node file descriptor + * @eb: eraseblock to write to + * @offs: offset withing the eraseblock to write to + * @data: data buffer to write + * @len: how many data bytes to write + * @oob: OOB buffer to write + * @ooblen: how many OOB bytes to write + * @mode: write mode (e.g., %MTD_OOB_PLACE, %MTD_OOB_RAW) + * + * This function writes @len bytes of data to eraseblock @eb and offset @offs + * of the MTD device defined by @mtd. Returns %0 in case of success and %-1 in + * case of failure. + * + * Can only write to a single page at a time if writing to OOB. + */ + int mtd_write(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb, + int offs, void *data, int len, void *oob, int ooblen, + uint8_t mode); + + /** + * mtd_read_oob - read out-of-band area. + * @desc: MTD library descriptor + * @mtd: MTD device description object + * @fd: MTD device node file descriptor + * @start: page-aligned start address + * @length: number of OOB bytes to read + * @data: read buffer + * + * This function reads @length OOB bytes starting from address @start on + * MTD device described by @fd. The address is specified as page byte offset + * from the beginning of the MTD device. This function returns %0 in case of + * success and %-1 in case of failure. + */ + int mtd_read_oob(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, + uint64_t start, uint64_t length, void *data); + + /** + * mtd_write_oob - write out-of-band area. + * @desc: MTD library descriptor + * @mtd: MTD device description object + * @fd: MTD device node file descriptor + * @start: page-aligned start address + * @length: number of OOB bytes to write + * @data: write buffer + * + * This function writes @length OOB bytes starting from address @start on + * MTD device described by @fd. The address is specified as page byte offset + * from the beginning of the MTD device. Returns %0 in case of success and %-1 + * in case of failure. + */ + int mtd_write_oob(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, + uint64_t start, uint64_t length, void *data); + + /** + * mtd_write_img - write a file to MTD device. + * @mtd: MTD device description object + * @fd: MTD device node file descriptor + * @eb: eraseblock to write to + * @offs: offset withing the eraseblock to write to + * @img_name: the file to write + * + * This function writes an image @img_name the MTD device defined by @mtd. @eb + * and @offs are the starting eraseblock and offset on the MTD device. Returns + * %0 in case of success and %-1 in case of failure. + */ + int mtd_write_img(const struct mtd_dev_info *mtd, int fd, int eb, int offs, + const char *img_name); + + /** + * mtd_probe_node - test MTD node. + * @desc: MTD library descriptor + * @node: the node to test + * + * This function tests whether @node is an MTD device node and returns %1 if it + * is, and %-1 if it is not (errno is %ENODEV in this case) or if an error + * occurred. + */ + int mtd_probe_node(libmtd_t desc, const char *node); + +#ifdef __cplusplus +} +#endif + +#endif /* __LIBMTD_H__ */ diff --git a/fpgaupdate/libmtd_common.h b/fpgaupdate/libmtd_common.h new file mode 100644 index 0000000..1784674 --- /dev/null +++ b/fpgaupdate/libmtd_common.h @@ -0,0 +1,247 @@ +/* + * Copyright (c) Artem Bityutskiy, 2007, 2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Imported from mtd-utils by dehrenberg */ + +#ifndef __MTD_UTILS_COMMON_H__ +#define __MTD_UTILS_COMMON_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef PROGRAM_NAME +#error "You must define PROGRAM_NAME before including this header" +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifndef MIN /* some C lib headers define this for us */ +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif +#define min(a, b) MIN(a, b) /* glue for linux kernel source */ +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + +#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1) +#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) + +#define min_t(t, x, y) ({ \ + typeof((x)) _x = (x); \ + typeof((y)) _y = (y); \ + (_x < _y) ? _x : _y; \ +}) + +#define max_t(t, x, y) ({ \ + typeof((x)) _x = (x); \ + typeof((y)) _y = (y); \ + (_x > _y) ? _x : _y; \ +}) + +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +/* define a print format specifier for off_t */ +#ifdef __USE_FILE_OFFSET64 +#define PRIxoff_t PRIx64 +#define PRIdoff_t PRId64 +#else +#define PRIxoff_t "l" PRIx32 +#define PRIdoff_t "l" PRId32 +#endif + +/* Verbose messages */ +#define bareverbose(verbose, fmt, ...) \ + do \ + { \ + if (verbose) \ + printf(fmt, ##__VA_ARGS__); \ + } while (0) +#define verbose(verbose, fmt, ...) \ + bareverbose(verbose, "%s: " fmt "\n", PROGRAM_NAME, ##__VA_ARGS__) + +/* Normal messages */ +#define normsg_cont(fmt, ...) \ + do \ + { \ + printf("%s: " fmt, PROGRAM_NAME, ##__VA_ARGS__); \ + } while (0) +#define normsg(fmt, ...) \ + do \ + { \ + normsg_cont(fmt "\n", ##__VA_ARGS__); \ + } while (0) + +/* Error messages */ +#define errmsg(fmt, ...) ({ \ + fprintf(stderr, "%s: error!: " fmt "\n", PROGRAM_NAME, ##__VA_ARGS__); \ + -1; \ +}) +#define errmsg_die(fmt, ...) \ + do \ + { \ + exit(errmsg(fmt, ##__VA_ARGS__)); \ + } while (0) + +/* System error messages */ +#define sys_errmsg(fmt, ...) ({ \ + int _err = errno; \ + errmsg(fmt, ##__VA_ARGS__); \ + fprintf(stderr, "%*serror %d (%s)\n", (int)sizeof(PROGRAM_NAME) + 1, \ + "", _err, strerror(_err)); \ + -1; \ +}) +#define sys_errmsg_die(fmt, ...) \ + do \ + { \ + exit(sys_errmsg(fmt, ##__VA_ARGS__)); \ + } while (0) + +/* Warnings */ +#define warnmsg(fmt, ...) \ + do \ + { \ + fprintf(stderr, "%s: warning!: " fmt "\n", PROGRAM_NAME, ##__VA_ARGS__); \ + } while (0) + +#if defined(__UCLIBC__) +/* uClibc versions before 0.9.34 don't have rpmatch() */ +#if __UCLIBC_MAJOR__ == 0 && \ + (__UCLIBC_MINOR__ < 9 || \ + (__UCLIBC_MINOR__ == 9 && __UCLIBC_SUBLEVEL__ < 34)) +#undef rpmatch +#define rpmatch __rpmatch + static inline int __rpmatch(const char *resp) + { + return (resp[0] == 'y' || resp[0] == 'Y') ? 1 : (resp[0] == 'n' || resp[0] == 'N') ? 0 + : -1; + } +#endif +#endif + + /** + * prompt the user for confirmation + */ + static inline bool prompt(const char *msg, bool def) + { + char *line = NULL; + size_t len; + bool ret = def; + + do + { + normsg_cont("%s (%c/%c) ", msg, def ? 'Y' : 'y', def ? 'n' : 'N'); + fflush(stdout); + + while (getline(&line, &len, stdin) == -1) + { + printf("failed to read prompt; assuming '%s'\n", + def ? "yes" : "no"); + break; + } + + if (strcmp("\n", line) != 0) + { + switch (rpmatch(line)) + { + case 0: + ret = false; + break; + case 1: + ret = true; + break; + case -1: + puts("unknown response; please try again"); + continue; + } + } + break; + } while (1); + + free(line); + + return ret; + } + + static inline int is_power_of_2(unsigned long long n) + { + return (n != 0 && ((n & (n - 1)) == 0)); + } + +/** + * simple_strtoX - convert a hex/dec/oct string into a number + * @snum: buffer to convert + * @error: set to 1 when buffer isn't fully consumed + * + * These functions are similar to the standard strtoX() functions, but they are + * a little bit easier to use if you want to convert full string of digits into + * the binary form. The typical usage: + * + * int error = 0; + * unsigned long num; + * + * num = simple_strtoul(str, &error); + * if (error || ... if needed, your check that num is not out of range ...) + * error_happened(); + */ +#define simple_strtoX(func, type) \ + static inline type simple_##func(const char *snum, int *error) \ + { \ + char *endptr; \ + type ret = func(snum, &endptr, 0); \ + \ + if (error && (!*snum || *endptr)) \ + { \ + errmsg("%s: unable to parse the number '%s'", #func, snum); \ + *error = 1; \ + } \ + \ + return ret; \ + } + simple_strtoX(strtol, long int) + simple_strtoX(strtoll, long long int) + simple_strtoX(strtoul, unsigned long int) + simple_strtoX(strtoull, unsigned long long int) + +/* Simple version-printing for utils */ +#define common_print_version() \ + do \ + { \ + printf("%s %s\n", PROGRAM_NAME, VERSION); \ + } while (0) + +#include "libmtd_xalloc.h" + +#ifdef __cplusplus +} +#endif + +#endif /* !__MTD_UTILS_COMMON_H__ */ diff --git a/fpgaupdate/libmtd_int.h b/fpgaupdate/libmtd_int.h new file mode 100644 index 0000000..557fbc5 --- /dev/null +++ b/fpgaupdate/libmtd_int.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) International Business Machines Corp., 2006 + * Copyright (C) 2009 Nokia Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Artem Bityutskiy + * + * MTD library. + */ + +/* Imported from mtd-utils by dehrenberg */ + +#ifndef __LIBMTD_INT_H__ +#define __LIBMTD_INT_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define PROGRAM_NAME "libmtd" + +#define SYSFS_MTD "class/mtd" +#define MTD_NAME_PATT "mtd%d" +#define MTD_DEV "dev" +#define MTD_NAME "name" +#define MTD_TYPE "type" +#define MTD_EB_SIZE "erasesize" +#define MTD_SIZE "size" +#define MTD_MIN_IO_SIZE "writesize" +#define MTD_SUBPAGE_SIZE "subpagesize" +#define MTD_OOB_SIZE "oobsize" +#define MTD_REGION_CNT "numeraseregions" +#define MTD_FLAGS "flags" + +#define OFFS64_IOCTLS_UNKNOWN 0 +#define OFFS64_IOCTLS_NOT_SUPPORTED 1 +#define OFFS64_IOCTLS_SUPPORTED 2 + + /** + * libmtd - MTD library description data structure. + * @sysfs_mtd: MTD directory in sysfs + * @mtd: MTD device sysfs directory pattern + * @mtd_dev: MTD device major/minor numbers file pattern + * @mtd_name: MTD device name file pattern + * @mtd_type: MTD device type file pattern + * @mtd_eb_size: MTD device eraseblock size file pattern + * @mtd_size: MTD device size file pattern + * @mtd_min_io_size: minimum I/O unit size file pattern + * @mtd_subpage_size: sub-page size file pattern + * @mtd_oob_size: MTD device OOB size file pattern + * @mtd_region_cnt: count of additional erase regions file pattern + * @mtd_flags: MTD device flags file pattern + * @sysfs_supported: non-zero if sysfs is supported by MTD + * @offs64_ioctls: %OFFS64_IOCTLS_SUPPORTED if 64-bit %MEMERASE64, + * %MEMREADOOB64, %MEMWRITEOOB64 MTD device ioctls are + * supported, %OFFS64_IOCTLS_NOT_SUPPORTED if not, and + * %OFFS64_IOCTLS_UNKNOWN if it is not known yet; + * + * Note, we cannot find out whether 64-bit ioctls are supported by MTD when we + * are initializing the library, because this requires an MTD device node. + * Indeed, we have to actually call the ioctl and check for %ENOTTY to find + * out whether it is supported or not. + * + * Thus, we leave %offs64_ioctls uninitialized in 'libmtd_open()', and + * initialize it later, when corresponding libmtd function is used, and when + * we actually have a device node and can invoke an ioctl command on it. + */ + struct libmtd + { + char *sysfs_mtd; + char *mtd; + char *mtd_dev; + char *mtd_name; + char *mtd_type; + char *mtd_eb_size; + char *mtd_size; + char *mtd_min_io_size; + char *mtd_subpage_size; + char *mtd_oob_size; + char *mtd_region_cnt; + char *mtd_flags; + unsigned int sysfs_supported : 1; + unsigned int offs64_ioctls : 2; + }; + + int legacy_libmtd_open(void); + int legacy_dev_present(int mtd_num); + int legacy_mtd_get_info(struct mtd_info *info); + int legacy_get_dev_info(const char *node, struct mtd_dev_info *mtd); + int legacy_get_dev_info1(int dev_num, struct mtd_dev_info *mtd); + +#ifdef __cplusplus +} +#endif + +#endif /* !__LIBMTD_INT_H__ */ diff --git a/fpgaupdate/libmtd_legacy.c b/fpgaupdate/libmtd_legacy.c new file mode 100644 index 0000000..719275c --- /dev/null +++ b/fpgaupdate/libmtd_legacy.c @@ -0,0 +1,404 @@ +/* + * Copyright (C) 2009 Nokia Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Artem Bityutskiy + * + * This file is part of the MTD library. Implements pre-2.6.30 kernels support, + * where MTD did not have sysfs interface. The main limitation of the old + * kernels was that the sub-page size was not exported to user-space, so it was + * not possible to get sub-page size. + */ + +/* Imported from mtd-utils by dehrenberg */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libmtd.h" +#include "libmtd_int.h" +#include "libmtd_common.h" + +#define MTD_PROC_FILE "/proc/mtd" +#define MTD_DEV_PATT "/dev/mtd%d" +#define MTD_DEV_MAJOR 90 + +#define PROC_MTD_FIRST "dev: size erasesize name\n" +#define PROC_MTD_FIRST_LEN (sizeof(PROC_MTD_FIRST) - 1) +#define PROC_MTD_MAX_LEN 4096 +#define PROC_MTD_PATT "mtd%d: %llx %x" + +/** + * struct proc_parse_info - /proc/mtd parsing information. + * @mtd_num: MTD device number + * @size: device size + * @eb_size: eraseblock size + * @name: device name + * @buf: contents of /proc/mtd + * @data_size: how much data was read into @buf + * @pos: next string in @buf to parse + */ +struct proc_parse_info +{ + int mtd_num; + long long size; + char name[MTD_NAME_MAX + 1]; + int eb_size; + char *buf; + int data_size; + char *next; +}; + +static int proc_parse_start(struct proc_parse_info *pi) +{ + int fd, ret; + + fd = open(MTD_PROC_FILE, O_RDONLY); + if (fd == -1) + return -1; + + pi->buf = xmalloc(PROC_MTD_MAX_LEN); + + ret = read(fd, pi->buf, PROC_MTD_MAX_LEN); + if (ret == -1) + { + sys_errmsg("cannot read \"%s\"", MTD_PROC_FILE); + goto out_free; + } + + if (ret < PROC_MTD_FIRST_LEN || + memcmp(pi->buf, PROC_MTD_FIRST, PROC_MTD_FIRST_LEN)) + { + errmsg("\"%s\" does not start with \"%s\"", MTD_PROC_FILE, + PROC_MTD_FIRST); + goto out_free; + } + + pi->data_size = ret; + pi->next = pi->buf + PROC_MTD_FIRST_LEN; + + close(fd); + return 0; + +out_free: + free(pi->buf); + close(fd); + return -1; +} + +static int proc_parse_next(struct proc_parse_info *pi) +{ + int ret, len, pos = pi->next - pi->buf; + char *p, *p1; + + if (pos >= pi->data_size) + { + free(pi->buf); + return 0; + } + + ret = sscanf(pi->next, PROC_MTD_PATT, &pi->mtd_num, &pi->size, + &pi->eb_size); + if (ret != 3) + return errmsg("\"%s\" pattern not found", PROC_MTD_PATT); + + p = memchr(pi->next, '\"', pi->data_size - pos); + if (!p) + return errmsg("opening \" not found"); + p += 1; + pos = p - pi->buf; + if (pos >= pi->data_size) + return errmsg("opening \" not found"); + + p1 = memchr(p, '\"', pi->data_size - pos); + if (!p1) + return errmsg("closing \" not found"); + pos = p1 - pi->buf; + if (pos >= pi->data_size) + return errmsg("closing \" not found"); + + len = p1 - p; + if (len > MTD_NAME_MAX) + return errmsg("too long mtd%d device name", pi->mtd_num); + + memcpy(pi->name, p, len); + pi->name[len] = '\0'; + + if (p1[1] != '\n') + return errmsg("opening \"\n\" not found"); + pi->next = p1 + 2; + return 1; +} + +/** + * legacy_libmtd_open - legacy version of 'libmtd_open()'. + * + * This function is just checks that MTD is present in the system. Returns + * zero in case of success and %-1 in case of failure. In case of failure, + * errno contains zero if MTD is not present in the system, or contains the + * error code if a real error happened. This is similar to the 'libmtd_open()' + * return conventions. + */ +int legacy_libmtd_open(void) +{ + int fd; + + fd = open(MTD_PROC_FILE, O_RDONLY); + if (fd == -1) + { + if (errno == ENOENT) + errno = 0; + return -1; + } + + close(fd); + return 0; +} + +/** + * legacy_dev_presentl - legacy version of 'mtd_dev_present()'. + * @info: the MTD device information is returned here + * + * When the kernel does not provide sysfs files for the MTD subsystem, + * fall-back to parsing the /proc/mtd file to determine whether an mtd device + * number @mtd_num is present. + */ +int legacy_dev_present(int mtd_num) +{ + int ret; + struct proc_parse_info pi; + + ret = proc_parse_start(&pi); + if (ret) + return -1; + + while (proc_parse_next(&pi)) + { + if (pi.mtd_num == mtd_num) + return 1; + } + + return 0; +} + +/** + * legacy_mtd_get_info - legacy version of 'mtd_get_info()'. + * @info: the MTD device information is returned here + * + * This function is similar to 'mtd_get_info()' and has the same conventions. + */ +int legacy_mtd_get_info(struct mtd_info *info) +{ + int ret; + struct proc_parse_info pi; + + ret = proc_parse_start(&pi); + if (ret) + return -1; + + info->lowest_mtd_num = INT_MAX; + while (proc_parse_next(&pi)) + { + info->mtd_dev_cnt += 1; + if (pi.mtd_num > info->highest_mtd_num) + info->highest_mtd_num = pi.mtd_num; + if (pi.mtd_num < info->lowest_mtd_num) + info->lowest_mtd_num = pi.mtd_num; + } + + return 0; +} + +/** + * legacy_get_dev_info - legacy version of 'mtd_get_dev_info()'. + * @node: name of the MTD device node + * @mtd: the MTD device information is returned here + * + * This function is similar to 'mtd_get_dev_info()' and has the same + * conventions. + */ +int legacy_get_dev_info(const char *node, struct mtd_dev_info *mtd) +{ + struct stat st; + struct mtd_info_user ui; + int fd, ret; + loff_t offs = 0; + struct proc_parse_info pi; + + if (stat(node, &st)) + { + sys_errmsg("cannot open \"%s\"", node); + if (errno == ENOENT) + normsg("MTD subsystem is old and does not support " + "sysfs, so MTD character device nodes have " + "to exist"); + } + + if (!S_ISCHR(st.st_mode)) + { + errno = EINVAL; + return errmsg("\"%s\" is not a character device", node); + } + + memset(mtd, '\0', sizeof(struct mtd_dev_info)); + mtd->major = major(st.st_rdev); + mtd->minor = minor(st.st_rdev); + + if (mtd->major != MTD_DEV_MAJOR) + { + errno = EINVAL; + return errmsg("\"%s\" has major number %d, MTD devices have " + "major %d", + node, mtd->major, MTD_DEV_MAJOR); + } + + mtd->mtd_num = mtd->minor / 2; + + fd = open(node, O_RDONLY); + if (fd == -1) + return sys_errmsg("cannot open \"%s\"", node); + + if (ioctl(fd, MEMGETINFO, &ui)) + { + sys_errmsg("MEMGETINFO ioctl request failed"); + goto out_close; + } + + ret = ioctl(fd, MEMGETBADBLOCK, &offs); + if (ret == -1) + { + if (errno != EOPNOTSUPP) + { + sys_errmsg("MEMGETBADBLOCK ioctl failed"); + goto out_close; + } + errno = 0; + mtd->bb_allowed = 0; + } + else + mtd->bb_allowed = 1; + + mtd->type = ui.type; + mtd->size = ui.size; + mtd->eb_size = ui.erasesize; + mtd->min_io_size = ui.writesize; + mtd->oob_size = ui.oobsize; + + if (mtd->min_io_size <= 0) + { + errmsg("mtd%d (%s) has insane min. I/O unit size %d", + mtd->mtd_num, node, mtd->min_io_size); + goto out_close; + } + if (mtd->eb_size <= 0 || mtd->eb_size < mtd->min_io_size) + { + errmsg("mtd%d (%s) has insane eraseblock size %d", + mtd->mtd_num, node, mtd->eb_size); + goto out_close; + } + if (mtd->size <= 0 || mtd->size < mtd->eb_size) + { + errmsg("mtd%d (%s) has insane size %lld", + mtd->mtd_num, node, mtd->size); + goto out_close; + } + mtd->eb_cnt = mtd->size / mtd->eb_size; + + switch (mtd->type) + { + case MTD_ABSENT: + errmsg("mtd%d (%s) is removable and is not present", + mtd->mtd_num, node); + goto out_close; + case MTD_RAM: + strcpy((char *)mtd->type_str, "ram"); + break; + case MTD_ROM: + strcpy((char *)mtd->type_str, "rom"); + break; + case MTD_NORFLASH: + strcpy((char *)mtd->type_str, "nor"); + break; + case MTD_NANDFLASH: + strcpy((char *)mtd->type_str, "nand"); + break; + case MTD_MLCNANDFLASH: + strcpy((char *)mtd->type_str, "mlc-nand"); + break; + case MTD_DATAFLASH: + strcpy((char *)mtd->type_str, "dataflash"); + break; + case MTD_UBIVOLUME: + strcpy((char *)mtd->type_str, "ubi"); + break; + default: + goto out_close; + } + + if (ui.flags & MTD_WRITEABLE) + mtd->writable = 1; + mtd->subpage_size = mtd->min_io_size; + + close(fd); + + /* + * Unfortunately, the device name is not available via ioctl, and + * we have to parse /proc/mtd to get it. + */ + ret = proc_parse_start(&pi); + if (ret) + return -1; + + while (proc_parse_next(&pi)) + { + if (pi.mtd_num == mtd->mtd_num) + { + strcpy((char *)mtd->name, pi.name); + return 0; + } + } + + errmsg("mtd%d not found in \"%s\"", mtd->mtd_num, MTD_PROC_FILE); + errno = ENOENT; + return -1; + +out_close: + close(fd); + return -1; +} + +/** + * legacy_get_dev_info1 - legacy version of 'mtd_get_dev_info1()'. + * @node: name of the MTD device node + * @mtd: the MTD device information is returned here + * + * This function is similar to 'mtd_get_dev_info1()' and has the same + * conventions. + */ +int legacy_get_dev_info1(int mtd_num, struct mtd_dev_info *mtd) +{ + char node[sizeof(MTD_DEV_PATT) + 20]; + + sprintf(node, MTD_DEV_PATT, mtd_num); + return legacy_get_dev_info(node, mtd); +} diff --git a/fpgaupdate/libmtd_xalloc.h b/fpgaupdate/libmtd_xalloc.h new file mode 100644 index 0000000..2d54fdb --- /dev/null +++ b/fpgaupdate/libmtd_xalloc.h @@ -0,0 +1,100 @@ +/* + * memory wrappers + * + * Copyright (c) Artem Bityutskiy, 2007, 2008 + * Copyright 2001, 2002 Red Hat, Inc. + * 2001 David A. Schleef + * 2002 Axis Communications AB + * 2001, 2002 Erik Andersen + * 2004 University of Szeged, Hungary + * 2006 KaiGai Kohei + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __MTD_UTILS_XALLOC_H__ +#define __MTD_UTILS_XALLOC_H__ + +#include +#include +#include + +/* + * Mark these functions as unused so that gcc does not emit warnings + * when people include this header but don't use every function. + */ + +__attribute__((unused)) static void *xmalloc(size_t size) +{ + void *ptr = malloc(size); + + if (ptr == NULL && size != 0) + sys_errmsg_die("out of memory"); + return ptr; +} + +__attribute__((unused)) static void *xcalloc(size_t nmemb, size_t size) +{ + void *ptr = calloc(nmemb, size); + + if (ptr == NULL && nmemb != 0 && size != 0) + sys_errmsg_die("out of memory"); + return ptr; +} + +__attribute__((unused)) static void *xzalloc(size_t size) +{ + return xcalloc(1, size); +} + +__attribute__((unused)) static void *xrealloc(void *ptr, size_t size) +{ + ptr = realloc(ptr, size); + if (ptr == NULL && size != 0) + sys_errmsg_die("out of memory"); + return ptr; +} + +__attribute__((unused)) static char *xstrdup(const char *s) +{ + char *t; + + if (s == NULL) + return NULL; + t = strdup(s); + if (t == NULL) + sys_errmsg_die("out of memory"); + return t; +} + +#ifdef _GNU_SOURCE + +__attribute__((unused)) static int xasprintf(char **strp, const char *fmt, ...) +{ + int cnt; + va_list ap; + + va_start(ap, fmt); + cnt = vasprintf(strp, fmt, ap); + va_end(ap); + + if (cnt == -1) + sys_errmsg_die("out of memory"); + + return cnt; +} +#endif + +#endif /* !__MTD_UTILS_XALLOC_H__ */ diff --git a/i2c_key/Makefile b/i2c_key/Makefile new file mode 100644 index 0000000..4f9d455 --- /dev/null +++ b/i2c_key/Makefile @@ -0,0 +1,6 @@ +ch455_key:ch455_key.cpp + g++ $^ -o $@ + +clean: + rm ch455_key + \ No newline at end of file diff --git a/i2c_key/ch455_key b/i2c_key/ch455_key new file mode 100644 index 0000000000000000000000000000000000000000..46666c299f41658d3fbfd3b9cf3183c6fafa71da GIT binary patch literal 19520 zcmeHPeRP!7nZGl`rvio$h5D5Vf&!9B!k0m88S+7hjX*@MW*Y?A*8LEvL3lddRw*LR;|ahK>N>>+edAqt4Z^nv<5s%Oi7l~`rp|h%8$EP z7IWxJ3KmRR?<>$FKR;_K(1MM+zI<`nqWx#e{ZQ5sX({Unm3Bm;-94p&Ks?yKY>6)s z^Hr#JlYNq{TYJ5%iNZQj<`lmOdBTWaTJmhgz)x;F*!k$;`&<6-)cw}a?^{f|d}+1M zOg!RT(RWU+xJS$s`^&inivK!DVXmn7Fc1Dl9-MBW(d;~vM}BV}{6rpnGVIR=&zU{~ zFj~Do$bHsoNvu z!~>kTJ2W3eJd%7E)2myoBqbz%Zg}(rTs~Fdefs&pc-KsYZ*kx!^z-$}GG&nEk6xhU z_dD>d+Rh;dUNB3^59)c1?QnUomUqEVb4naEaBW%|I&9!yP^RVIV+MYqfu{^yKe7~8 z`{PEvnMW!(lMGykPRbV;xcPjaW#H!X&1>NNTp>gA44j|EgqIumWCC=mG;lLMegi+3 zg+bRCxb8y9U2oueC`f#xflo8+G#mJN2HtMqG&VVP8TfPtL3<3`oNxLJe1;*v#lYzq z%xSBEpU)uZb_3T#Q*s9kTn|BsKWX6R_}OdV{7y#-XE(pF>#Rp4dxYpeyZNV24tlKD zq#^z16!=?(I6VE6y5WN3E0bP#@oU9i&#(9b@6>d+e;Dsyk|)a(P@Zj+&q2A$C{IJV z#V8k|e78})0OiMx@`WfLG|HEveB3C{M%nEessD16XB*`OC|4O}AIdF8c@fHY8|7sv zKW>z-M){yo{u0W^jdB&rZudz2t5Ke9l&?j($|$czxy2|qqI|bez5(UOjq)ax532Gd zqVLG1xPIpmyN5jf;p3Ny+C@f5#>HC+dd% zLhSpGbb2QBGxZ_xQ^M;>{sm|W=t?2p9>8le%7;r*b;GM5?-j+b<&!TF;^mT$tGAVW zyy|{j+r9_+yP;ckvTnEvdB4^@yZI+_oSi;b3~xhS&9keQ`(0wG^y^sNFz7z%OS6CY zTk!YaaCt>vWAkj!^3&(~htF<4D92_BzNhaIucXcs2hzpjz)-ROK?lsp zQ@o)2OVI3isW}|B8k@)WHSR@S1IRA}C9DtF-)pP_)TQPAPGbu-MsnZN7>yZKhk7RP zbAoh9?h!3_iPoihAJo_^P_Fko8ly2s7|CtX7{w&J4t@XKC6=dO5X)09_?H)7EN(sI z!F_z!;Bt!3Zp4S}+y;Fb*W?q~jcdDS5Ff6;Q)8!rksSHnuCaG0o_G0|i&@1RQmB*a zlXC;=9>Ux}G5npjMfNvoy_8}9dX4?Yu)khouK`o-om1*vsg~{e__~f)Ov>u zTVK@Ji@->a{H2&o8mHnw?OCE_egv7+X4M`n4Hc$z9s7Wj|JOp!b+MQsWk9_`EP&h$ zQ+Ah8_odqI6J(d-MDr+o!1H7#_rdvE=DU#Lm=|d5VZ+wB8cUKb_{j5l=3ZSXdU1c_ z^8TMREq!i*f_-d&nm2 z%khO6X8i8EA~_jy3%JhI70G9Gov(sYyhrN%v7DFFSJ88+uaKT)G?rz3{&~r#NuK6O zdhX#K`7hifl+V;PI4}7QWaK|W#j-tL5qJ8x z5pQL?x02@IDDmM-dIe-w81Y%*h!1!ipYMGp2KsE5=UOTof*JkDv$ncfsXDl z>BhR@1QHgOWQr>yRtLx#uN_nNs9LX7^0vm}URt(_MBDHqV?>THB?4GfuUWEmsdZyK zVu!tQ5zpuIk!cfejl>hSx24w(f6+U)d{GarGno8DI2enDvIR_jI2zJcS+9|NFsl={ zOAoT^AU~wHxv;KZ+A+wS?&?neCl7-(-~j9}>lZ{i20RZ(G>*hOlypp31`G zz;#O)r!~uYaCSb%LWXJB%SIjc>_}(Wi;?H72g|8)kibqj*dFsPUF7|e*BN=fbI5xw z7m1D{M?)4pl({hs`PM)OzR$GfR|<#PaCf*a@~jwy8cn=+o=T^Wf$jl43HlZ&Zho;4 zKUU{}mV;gcx&^ce^b{!O9kB%ulYY>G)9Lg+(Dk54LAQdw59)tEoi4&e@dW4+&`BRa zAM^yM4f^qi&BUIz0soi5;K|K_38Z0G;x2I^73a0ADG& z?r0R_dMwbB}e)Fz$!K71@+^49oQOBv1*!k$GDxIs%`GIZ@%&B zG=hq7$*BtQz&n2?5q>AGlhEBrD0G{kL2IG?xE4abUE$?BChQ!)@y$1+J>u`fWrM$6 z@wd8m6z-fJQUb(3it8l!TNJ-*$F!YOn+^T|BgvJCz9QTD8G(zc8$`L z?YhqJs{#Bo;5RG2w0ncW?*P9NnZV`FIuyrv{5_Ac%{y;-(Fom@BQNXv5X|!0~1p86J0)| z89YAM!=ibq2X_^pKQM)8=V%jmyut8bN25I|J}z@#7~+r~ zFZh1Q#wQ5AZ?f@;g2z`jK1uMn%*H1R9`D)sIhp$+8_%~tev066kS#woa~>ocpC))- z$;QtU^Y{ic7#^&2@wo;AMtr7=Lp;$K3=ck+@;qh0ke?xVe#*v+a883~&Jm6Wv&?{= zPexGMmwJKVc_tgrJtshXkC-J6>G75=&$H?XN?wc;@1;i&m8+E`cU-NJcy64Pd~Q6y z4EfRQvz>N+5U6U!UxK>DRKYmUqe?z^JSaT3f4}>w^`0vp;0a&X%XThyjE6Tr)y`DW z=kWgz+J7hhw#N55MhWhZyMT_)voaeB^Coca0A z_LZI7@qB}{lZz|)>Edy?+A{fOgkk$OB~kYoN=y~ zacQQsXrm=k@LnB|b|W)AeTD#XL*>a>{}8IA6jqING6eAW!i> zIb8wr+XAxKmmqOW9Wu#p3dk+i_+E|6ZwbI_G+v-zFq)+nzNcuM-`lu*RD22r@Bi20 zLgCYe{}M(N-3mLS^%u9x`Fv+P>#=#nO!@93mf!A>e-!n)FyA_HvN@VRyCF|sD4g^5 z`tcOc+na~}R@X{Rt}-u|`5o%8&EYCFz(Tg7LT=M-KXvAHHE6-s=nctCy? z!*@z8ak<8u&QpM2a#|IC%5mt~_=s^2o1~_*7Bj z==XatZVNI0@VvB9H|-TI&*y5n#dO${H=f3|OLAyp956AM<`*t4utgiQcJ#TN<^`4J@AI;Aa8V?*SgRYkN zRKfG)otk$;9{Kh>crS3TVVAQHY5V-U3U15vw;C^U%o|VVvHwqb>>tg82l9;bcXYiE z=(x3OfBuxGUQyPah|5E|INw*M&*$pXx^2AI(aTYUESyM;Sb=yv&})UGcDxs77XzJPE7aZD*$Wk; zWI@u-5)HP~X0Thry}n>q7fxSpup26tcSXX%@a>UA*upNagdOh=;_M``DlID#BO6+B zF@h8eV#84!M%xs)EYcQ@#c@1x)7s@YDjMy^q063zMHTQp+#2Zauq~+EVqsTPB-mRE zv4*8hJyqSUGS|qtie+khRsEuBt1(oCjc9Z>w4tKH*kwjuG*px;g!YAz$P!e9ZDw{P zC>tB0vzjR3z-k~Gf(xoSR4$K1gjLtDu4+{SRJvQNddu2W847nGj@^lf2zRuWQd@no z4T$3E##PtVTD5Cy=*X*uGvHS38V#0+OS6>ZYR*Xa0fZPC=sde4z)f;M? ztfo~}4Yig!i|Y3q=S8he6^j#L+oJtaH_)~~@_5r#_3LhIwCdNQAP=cJRhDq%g4PB* z)`g&iv2!fI$5^w)>(?P#*f59|V}qkQHJc@&PQ_+H@~o?cu@<6OY+8=dW7S7-_7_!I zp+wATN2uxauRLzc=Vh}@=)<~Mm}Rvj656Uhx0}VMeQjAl&H>zP?xu>RW+ZT0S&onT zb&WL$qj3~CTg}1=X5G(xp4TBjZpx07%{NEtjd2>O?Gy$?TnXs|#aTAw8RaYlUA+ul zU5B2o;SHpb^+8z5)P_*!oSCMx(b|qaZmfe6OmxeEs7^j-RYm&=vw%-M!L1HClR27Z z;6tSxe(SDp!uXR1r?YL1ayUHC0q{z?QK-RWHK%2C8a%sY!k6gnv;!@mc3jbR&f(;D zINl|E(HOQ!uBxgpwF7Osgc-=!(jCD+{16EVAC=kziFV-&^+sV&Q9G_Uw}s;g+PN#m zbio2Ij!A(Obgrwz7C!P`_;8jSe`RQV@tC~NeBpLI=eCES%O$0uCSRq&c^D3KMuMm{ z23z>!lNBgq=zihDW1tgLyMBOvPD1PF^oESrBbj&|ktwgQYqpf-JkiT=(b_TVH|Y#h zFL-9+_YlS^kTLabt-?wpOx7YpYx=CeUuT?@ zmdo*KllhLozwd9*IP3FzC{zA!05O@ee~k$7HK4Rc&-%P>%Jgcj$NsY%(_6r&HGeMi z`YKbu)+hf-#@YTmfKg0YpVwiTdbPt`KkIY*@74NMpp^JK22=j-LHZZqa_ZB%9#x?~ zM`XVH^yzgtUgv{|OwRuQHc(Ta*MFIAbp%}h+`+rLO8pLf{(ZyrEgBp~V*eTX8)VG- zc|Dma*TeEo{|B@_$Dh}onf`_bospdNKM5Yy&-%R1!Sp3Vm$J_Kp9N;>^Ex)uqik5) zan?TwoR%ioO0LhB#SXsQhBF@4vezhAEt z?k`vJ>?fOHJuZKM3}Ng)|4u%n_5CcUsZ;-tz{!6to{?sKo +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_SDA 43 // GPIO1_B3 +#define I2C_SCL 44 // GPIO1_B4 +#define I2C_INT 52 + +typedef unsigned char UINT8; +typedef unsigned short UINT16; + +#define STATUS_SUCCESS 0 +#define STATUS_FAILURE -1 + +#define CH455_GET_KEY 0x0700 // 获取按键,返回按键代码 +#define CH455_SYSOFF 0x0400 // 关闭显示、关闭键盘 + +#define CH455_I2C_ADDR 0x40 // CH455的地址 +#define CH455_I2C_MASK 0x3E // CH455的高字节命令掩码 + +#define CH455_BIT_ENABLE 0x01 +// #define CH455_BIT_ENABLE 0x03 // 开启/关闭位 +#define CH455_BIT_SLEEP 0x04 // 睡眠控制位 + +#define CH455_SYSON (CH455_SYSOFF | CH455_BIT_ENABLE) +#define CH455_SLEEPOFF CH455_SYSOFF // 关闭睡眠 +#define CH455_SLEEPON (CH455_SYSOFF | CH455_BIT_SLEEP) // 开启睡眠 + +static unsigned char TxBuf[24] = {0}; +static unsigned char RxBuf[24] = {0}; + +void CH455_I2c_Stop(void); +void CH455_I2C_WrByte(unsigned char IIC_Byte); + +void delay_us(int i) +{ + int j, k; + for (j = 0; j < i; j++) + for (k = 0; k < 10; k++) + ; +} + +void initGpio(int addr) +{ + // printf("开始创建GPIO%d节点\n", addr); + FILE *fp = fopen("/sys/class/gpio/export", "w"); + if (fp == NULL) + perror("export open filed"); + else + fprintf(fp, "%d", addr); + + fclose(fp); + // printf("结束创建GPIO%d节点\n", addr); +} + +// 设置为gpio方向 +void setGpioDirection(int addr, char *direction) +{ + // printf("设置第GPIO%d为out模式\n",addr); + char path[100] = {0}; + sprintf(path, "/sys/class/gpio/gpio%d/direction", addr); + FILE *fp = fopen(path, "w"); + if (fp == NULL) + perror("direction open filed"); + else + fprintf(fp, "%s", direction); + fclose(fp); + // printf("结束设置第GPIO%d为out模式\n",addr); +} + +// 设置gpio的电平 +void set_gpioValue(int addr, int value) +{ + // printf("设置GPIO%d为%d\n", addr, value); + char path[64]; + snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", addr); + FILE *fp = fopen(path, "w"); + if (fp == NULL) + perror("direction open filed"); + else + fprintf(fp, "%d", value); + fclose(fp); + // printf("结束设置GPIO%d位置为%d\n", addr, value); +} + +void IOWR_OUT(int addr, int val) +{ + initGpio(addr); + setGpioDirection(addr, "out"); + set_gpioValue(addr, val); +} + +void IOWR_IN(int addr, int val) +{ + initGpio(addr); + setGpioDirection(addr, "in"); + set_gpioValue(addr, val); +} + +// 读gpio节点状态 +int IORD(int addr) +{ + char path[64]; + char value_str[3]; + + snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", addr); + // printf("/sys/class/gpio/gpio%d/value", addr); + FILE *fp = fopen(path, "r"); + + // fd = open(path, O_RDONLY); + if (fp == NULL) + { + printf("Failed to open gpio value for reading!"); + return -1; + } + if (fread(value_str, sizeof(char), 3, fp) < 0) + { + perror("Failed to read value!"); + return -1; + } + + fclose(fp); + // printf("读取GPIO状态结束\n"); + return (atoi(value_str)); +} + +// 开始位 +void CH455_I2c_Start(void) +{ + IOWR_OUT(I2C_SDA, 1); + delay_us(5); + IOWR_OUT(I2C_SCL, 1); + delay_us(5); + IOWR_OUT(I2C_SDA, 0); + delay_us(5); + IOWR_OUT(I2C_SCL, 0); + delay_us(5); +} + +// 结束位 +void CH455_I2c_Stop(void) +{ + IOWR_OUT(I2C_SCL, 0); + delay_us(5); + IOWR_OUT(I2C_SDA, 0); + delay_us(5); + IOWR_OUT(I2C_SCL, 1); + delay_us(5); + IOWR_OUT(I2C_SDA, 1); + delay_us(5); +} + +// 主控端写入一个字节到从机 +void CH455_I2C_WrByte(unsigned char IIC_Byte) +{ + unsigned char i; + for (i = 0; i < 8; i++) + { + // IOWR(I2C_SCL, 0); //钳住I2C总线,准备发送数据 + if (IIC_Byte & 0x80) + IOWR_OUT(I2C_SDA, 1); + else + IOWR_OUT(I2C_SDA, 0); + delay_us(5); + IOWR_OUT(I2C_SCL, 1); + delay_us(5); + IOWR_OUT(I2C_SCL, 0); + delay_us(5); + IIC_Byte <<= 1; + } + delay_us(5); + IOWR_OUT(I2C_SDA, 1); + delay_us(5); + IOWR_OUT(I2C_SCL, 1); + delay_us(5); + IOWR_OUT(I2C_SCL, 0); + delay_us(5); +} + +// 主控端对从机读取一个字节 +static unsigned char CH455_I2C_RdByte(void) // 读取一个字节数据 +{ + unsigned char i = 0; + unsigned char bytedata = 0; + delay_us(5); + // 将数据设置为输入模式 + IOWR_IN(I2C_SDA, 1); + delay_us(5); + IOWR_OUT(I2C_SCL, 0); + delay_us(5); + for (i = 0; i < 8; i++) + { + IOWR_OUT(I2C_SCL, 1); + delay_us(5); + bytedata <<= 1; + delay_us(5); + bytedata = bytedata | (IORD(I2C_SDA)); + delay_us(5); + IOWR_OUT(I2C_SCL, 0); + delay_us(5); + } + IOWR_OUT(I2C_SDA, 1); // 数据线设置回输出模式 + delay_us(5); + IOWR_OUT(I2C_SCL, 1); + delay_us(5); + IOWR_OUT(I2C_SCL, 0); + delay_us(5); + return (bytedata); // 返回数据 +} + +// 写命令 +static unsigned char CH455_Write(UINT16 cmd) +{ + printf("CH455_Write start...\n"); + CH455_I2c_Start(); // 启动总线 + printf("CH455_Write first byte= %02x\n", ((UINT8)(cmd >> 7) & CH455_I2C_MASK) | CH455_I2C_ADDR); + printf("CH455_Write second byte= %02x\n", (UINT8)cmd); + CH455_I2C_WrByte(((UINT8)(cmd >> 7) & CH455_I2C_MASK) | CH455_I2C_ADDR); + CH455_I2C_WrByte((UINT8)cmd); // 发送数据 + CH455_I2c_Stop(); // 结束总线 + printf("CH455_Write end...\n"); + printf("\n"); + return 1; +} + +static unsigned char CH455_Read(void) // 读取按键值 +{ + printf("CH455_Read start...\n"); + UINT8 keycode; + CH455_I2c_Start(); // 启动总线 + printf("write byte= %02x\n", (UINT8)(CH455_GET_KEY >> 7) & CH455_I2C_MASK | 0x01 | CH455_I2C_ADDR); + CH455_I2C_WrByte((UINT8)(CH455_GET_KEY >> 7) & CH455_I2C_MASK | 0x01 | CH455_I2C_ADDR); + keycode = CH455_I2C_RdByte(); // 读取数据 + printf("read byte= %02x\n", keycode); + CH455_I2c_Stop(); // 结束总线 + printf("CH455_Read end...\n"); + printf("\n"); + return keycode; +} + +void key_Inter(void) +{ + int ret; + int val = 0; + char buf[8]; + int num; + UINT16 key_value; + pollfd pfd; + pfd.fd = -1; + pfd.fd = open("/sys/class/gpio/gpio52/value", O_RDONLY); + if (pfd.fd > 0) + printf("huagao::open sucess,fd = %d\n", pfd.fd); + else + printf("huagao::open failed,fd = %d\n", pfd.fd); + pfd.events = POLLPRI; + num = read(pfd.fd, buf, 8); // This is to clear the avaible read + for (int i = 0; i < 8; i++) + printf("huagao::buf[%d] = %d\n", i, buf[i]); + + ret = CH455_Write(CH455_SYSON); + printf("CH455_SYSON = %02x\n", (CH455_SYSON)); + printf("CH455_Read() = %02x\n", CH455_Read()); + key_value = 0xff; + while (1) + { + ret = poll(&pfd, 1, 1000); + if (ret > 0) + { + printf("--------------------------------------------\n"); + printf("huagao::poll get date.\n"); + printf("huagao::poll ret = %d\n", ret); + /* + POLLIN: 有普通数据或者优先数据可读 + POLLRDNORM: 有普通数据可读 + POLLRDBAND: 有优先数据可读 + POLLPRI: 有紧急数据可读 + POLLOUT: 有普通数据可写 + POLLWRNORM: 有普通数据可写 + POLLWRBAND: 有紧急数据可写 + POLLERR: 有错误发生 + POLLHUP: 有描述符挂起事件发生 + POLLNVAL: 描述符非法 + */ + if (pfd.revents & POLLPRI) + { + lseek(pfd.fd, 0, SEEK_SET); + num = read(pfd.fd, buf, 8); + buf[num - 1] = '\0'; + ret = atoi(buf); + for (int i = 0; i < 8; i++) + printf("huagao::buf[%d] = %d\n", i, buf[i]); + printf("huagao::atoi(buf) ret = %d\n", ret); + } + key_value = CH455_Read(); + printf("CH455_Read() = %02x\n", key_value); + printf("--------------------------------------------\n"); + printf("\n"); + } + else if (ret == 0) + { + printf("--------------------------------------------\n"); + printf("huagao::ret = %d\n", ret); + printf("huagao::poll time out.\n"); + printf("--------------------------------------------\n"); + printf("\n"); + } + else + { + printf("--------------------------------------------\n"); + printf("huagao::ret = %d\n", ret); + printf("huagao::poll err.\n"); + printf("--------------------------------------------\n"); + printf("\n"); + } + } +} +int main(void) +{ + system("echo 52 > /sys/class/gpio/export"); + system("echo in > /sys/class/gpio/gpio52/direction"); + system("echo falling > /sys/class/gpio/gpio52/edge"); + key_Inter(); + return 0; +} diff --git a/imgproc/CMakeLists.txt b/imgproc/CMakeLists.txt new file mode 100644 index 0000000..48f0339 --- /dev/null +++ b/imgproc/CMakeLists.txt @@ -0,0 +1,32 @@ +project(imgproc) +add_compile_options(-std=c++14) +#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -O2") +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -O2") + +aux_source_directory(${PROJECT_SOURCE_DIR} DIR_SRCS) +aux_source_directory(${PROJECT_SOURCE_DIR}/imageprocess DIR_SUBSRC) +file(GLOB DIR_HEADS "${PROJECT_SOURCE_DIR}/*.h" "${PROJECT_SOURCE_DIR}/*.hpp") +set(DIR_SRCS ${DIR_SRCS} ${DIR_HEADS}) + +if(CMAKE_HOST_WIN32) +link_libraries( + libopencv_world.a + liblibjasper.a + libittnotify.a + libtegra_hal.a + libzlib.a + liblibjpeg-turbo.a + liblibpng.a + liblibtiff.a + liblibwebp.a +) +endif() +add_library(${PROJECT_NAME} STATIC ${DIR_SRCS} ${DIR_SUBSRC}) + +target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR}/imageprocess + ${PROJECT_SOURCE_DIR}/../packages/common.pkg/include + + ) + +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../bin) \ No newline at end of file diff --git a/imgproc/CSizedetect.cpp b/imgproc/CSizedetect.cpp new file mode 100644 index 0000000..14e6428 --- /dev/null +++ b/imgproc/CSizedetect.cpp @@ -0,0 +1,285 @@ +#include "CSizedetect.h" +#include +#include "ImageProcess_Public.h" +#include "commondef.h" + +void threshold_Mat(const cv::Mat &src, cv::Mat &dst, double thre) +{ + if (src.channels() == 3) + { +#ifdef USE_ONENCL + if (cl_res.context) + transforColor_threshold_opencl(src, dst, static_cast(thre)); + else +#endif + { + cv::Mat gray = hg::transforColor(src); + cv::threshold(gray, dst, thre, 255, cv::THRESH_BINARY); + gray.release(); + } + } + else + cv::threshold(src, dst, thre, 255, cv::THRESH_BINARY); +} + +void findContours(const cv::Mat &src, std::vector> &contours, std::vector &hierarchy, int retr, int method, cv::Point offset) +{ +#if CV_VERSION_REVISION == 6 + CvMat c_image = src; +#else + CvMat c_image; + c_image = cvMat(src.rows, src.cols, src.type(), src.data); + c_image.step = src.step[0]; + c_image.type = (c_image.type & ~cv::Mat::CONTINUOUS_FLAG) | (src.flags & cv::Mat::CONTINUOUS_FLAG); +#endif + cv::MemStorage storage(cvCreateMemStorage()); + CvSeq *_ccontours = nullptr; + +#if CV_VERSION_REVISION == 6 + cvFindContours(&c_image, storage, &_ccontours, sizeof(CvContour), retr, method, CvPoint(offset)); +#else + cvFindContours(&c_image, storage, &_ccontours, sizeof(CvContour), retr, method, CvPoint{offset.x, offset.y}); +#endif + if (!_ccontours) + { + contours.clear(); + return; + } + cv::Seq all_contours(cvTreeToNodeSeq(_ccontours, sizeof(CvSeq), storage)); + size_t total = all_contours.size(); + contours.resize(total); + + cv::SeqIterator it = all_contours.begin(); + for (size_t i = 0; i < total; i++, ++it) + { + CvSeq *c = *it; + reinterpret_cast(c)->color = static_cast(i); + int count = c->total; + int *data = new int[static_cast(count * 2)]; + cvCvtSeqToArray(c, data); + for (int j = 0; j < count; j++) + { + contours[i].push_back(cv::Point(data[j * 2], data[j * 2 + 1])); + } + delete[] data; + } + + hierarchy.resize(total); + it = all_contours.begin(); + for (size_t i = 0; i < total; i++, ++it) + { + CvSeq *c = *it; + int h_next = c->h_next ? reinterpret_cast(c->h_next)->color : -1; + int h_prev = c->h_prev ? reinterpret_cast(c->h_prev)->color : -1; + int v_next = c->v_next ? reinterpret_cast(c->v_next)->color : -1; + int v_prev = c->v_prev ? reinterpret_cast(c->v_prev)->color : -1; + hierarchy[i] = cv::Vec4i(h_next, h_prev, v_next, v_prev); + } + + storage.release(); +} + +std::vector getMaxContour(const std::vector> &contours, const std::vector &hierarchy) +{ + std::vector maxContour; + if (contours.size() < 1) + return {}; + + for (size_t i = 0, length = hierarchy.size(); i < length; i++) + if (hierarchy[i][3] == -1) + for (const auto &item : contours[i]) + maxContour.push_back(item); + + return maxContour; +} + +cv::RotatedRect getBoundingRect(const std::vector &contour) +{ + if (contour.empty()) + return {}; + + cv::RotatedRect rect = minAreaRect(contour); + if (rect.angle < -45) + { + rect.angle += 90; + float temp = rect.size.width; + rect.size.width = rect.size.height; + rect.size.height = temp; + } + if (rect.angle > 45) + { + rect.angle -= 90; + float temp = rect.size.width; + rect.size.width = rect.size.height; + rect.size.height = temp; + } + + return rect; +} + +CSizedetect::CSizedetect(int papaertype) : m_papertype(papaertype), + m_horThre(70), + m_verThre(100) +{ +} + +CSizedetect::~CSizedetect(void) {} + +void CSizedetect::SetPapertype(int papertype) +{ + m_papertype = papertype; +} +static int x = 0; +int CSizedetect::preprocess(cv::Mat &mat, void *unused) +{ + if (!mat.empty()) + { + float width, height; + cv::Mat thre; + hg::threshold_Mat(mat, thre, 40); + cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(8, 1)); + cv::morphologyEx(thre, thre, cv::MORPH_OPEN, element, cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar::all(0)); + std::vector> contours; + std::vector hierarchy; + hg::findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL); + std::vector maxContour = hg::getMaxContour(contours, hierarchy); + cv::RotatedRect rect = hg::getBoundingRect(maxContour); + width = rect.size.width; + height = rect.size.height; + printf("\n width =%f ,height = %f ", width, height); + // fastMeasureSize(mat.data,mat.cols,mat.rows,mat.channels(),width,height,40,20,5); + HGSize dstSize; + if (m_supportPaper.count((PaperSize)m_papertype) > 0) // 包含设置的幅面 + { + dstSize = m_supportPaper[(PaperSize)m_papertype]; + if ((width > (dstSize.width + m_horThre)) || (width < (dstSize.width - m_horThre)) || (height > (dstSize.height + m_verThre)) || (height < (dstSize.height - m_verThre))) + { + return 1; + } + } + } + return 0; +} + +void CSizedetect::rotate(float &x, float &y, float angle) +{ + float a = x * cos(angle) - y * sin(angle); + float b = x * sin(angle) + y * cos(angle); + x = a; + y = b; +} + +void CSizedetect::minAeaRect(const float *x, const float *y, int size, float &width, float &height) +{ + float area = width * height; + // rotate 0~90 degree + for (int i = 0; i < 91; ++i) + { + float tmpx = x[0], tmpy = y[0]; + rotate(tmpx, tmpy, i); + float xl = tmpx, xr = tmpx, yt = tmpy, yb = tmpy; + // traverse all points + for (int j = 1; j < size; ++j) + { + tmpx = x[j]; + tmpy = y[j]; + rotate(tmpx, tmpy, i); + if (tmpx < xl) + xl = tmpx; + if (tmpx > xr) + xr = tmpx; + if (tmpy < yb) + yb = tmpy; + if (tmpy > yt) + yt = tmpy; + } + float xx = xr - xl, yy = yt - yb; + if (area > xx * yy) + { + area = xx * yy; + height = xx; + width = yy; + } + } + + // + if (height < width) + { + float tmp = height; + height = width; + width = tmp; + } +} + +void CSizedetect::fastMeasureSize(const unsigned char *data, int src_width, int src_height, int channels, float &dst_width, float &dst_height, int threshold, int indent, int step) +{ + int bytesPerLine = src_width * channels; + int indent_x = indent * channels; + int indent_y = indent; + int step_x = step * channels; + int step_y = step; + + int total_count = (bytesPerLine + src_height) * 2 / indent; + if (total_count < 1) + return; + + float *points_x = new float[total_count]; + float *points_y = new float[total_count]; + + int points_count = 0; + // top + int rows = src_height / 2; + for (int x = 0; x < bytesPerLine; x += indent_x) + for (int y = 0; y < rows; y += step_y) + if (data[y * bytesPerLine + x] > threshold) + { + points_x[points_count] = x / channels; + points_y[points_count] = y; + points_count++; + break; + } + + // bottom + for (int x = 0; x < bytesPerLine; x += indent_x) + for (int y = src_height - 1; y >= rows; y -= step_y) + if (data[y * bytesPerLine + x] > threshold) + { + points_x[points_count] = x / channels; + points_y[points_count] = y; + points_count++; + break; + } + + // left + int cols = bytesPerLine / 2; + for (int y = 0; y < src_height; y += indent) + for (int x = 0; x < cols; x += step_x) + if (data[y * bytesPerLine + x] > threshold) + { + points_x[points_count] = x / channels; + points_y[points_count] = y; + points_count++; + break; + } + + // right + for (int y = 0; y < src_height; y += indent) + for (int x = bytesPerLine - 1; x >= cols; x -= step_x) + if (data[y * bytesPerLine + x] > threshold) + { + points_x[points_count] = x / channels; + points_y[points_count] = y; + points_count++; + break; + } + + if (points_count > 3) + { + dst_width = src_width; + dst_height = src_height; + minAeaRect(points_x, points_y, points_count, dst_width, dst_height); + } + + delete[] points_x; + delete[] points_y; +} diff --git a/imgproc/CSizedetect.h b/imgproc/CSizedetect.h new file mode 100644 index 0000000..fe9c4dd --- /dev/null +++ b/imgproc/CSizedetect.h @@ -0,0 +1,42 @@ +#pragma once +#include "IPreproc.h" +#include +#include "commondef.h" + +class CSizedetect : public IPreproc +{ +public: + explicit CSizedetect(int papaertype); + virtual ~CSizedetect(void); + virtual int preprocess(cv::Mat &mat, void *unused); + void SetPapertype(int papertype); + +private: + void rotate(float &x, float &y, float angle); + void minAeaRect(const float *x, const float *y, int size, float &width, float &height); + void fastMeasureSize(const unsigned char *data, int src_width, int src_height, int channels, float &dst_width, float &dst_height, int threshold = 40, int indent = 20, int step = 5); + +private: + int m_papertype; + int m_horThre; + int m_verThre; + std::map m_supportPaper = { + {PaperSize::G400_A3, HGSize{2338, 3307}}, + {PaperSize::G400_A4, HGSize{1653, 2338}}, + {PaperSize::G400_A4R, HGSize{2338, 1653}}, + {PaperSize::G400_A5, HGSize{1165, 1653}}, + {PaperSize::G400_A5R, HGSize{1653, 1165}}, + {PaperSize::G400_A6, HGSize{826, 1165}}, + {PaperSize::G400_A6R, HGSize{1165, 826}}, + {PaperSize::G400_B4, HGSize{1969, 2780}}, + {PaperSize::G400_B5, HGSize{1385, 1968}}, + {PaperSize::G400_B5R, HGSize{1968, 1385}}, + {PaperSize::G400_B6R, HGSize{1433, 1007}}, + {PaperSize::G400_B6, HGSize{1007, 1433}}, + {PaperSize::G400_DOUBLELETTER, HGSize{2200, 3400}}, + {PaperSize::G400_LEGAL, HGSize{1700, 2800}}, + {PaperSize::G400_LETTER, HGSize{1700, 2198}}, + {PaperSize::G400_LETTERR, HGSize{2198, 1700}}, + {PaperSize::G400_LONGLETTER, HGSize{2040, 2640}}, + {PaperSize::G400_MAXSIZE, HGSize{2338, 8189}}}; +}; \ No newline at end of file diff --git a/imgproc/ContaminationDetection.cpp b/imgproc/ContaminationDetection.cpp new file mode 100644 index 0000000..e0ac99a --- /dev/null +++ b/imgproc/ContaminationDetection.cpp @@ -0,0 +1,67 @@ +#include "ContaminationDetection.h" +#include +#include +#include + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +ContaminationDetection::ContaminationDetection() +{ +} + +int ContaminationDetection::detect1(const uchar *data1, const uchar *data2, int length, uchar threshold1, uchar threshold2, int width) +{ + int width_temp = 0; + for (size_t i = 0; i < length; i++) + { + if (MIN(data1[i], data2[i]) > threshold1) + return 1; + + if (MIN(data1[i], data2[i]) > threshold2) + { + width_temp++; + if (width_temp > width) + return 2; + } + else + width_temp = 0; + } + return 0; +} + +int ContaminationDetection::detect2(const uchar *data, int width, int height, int channels, uchar color, int length) +{ + uchar *ptr = const_cast(data); + std::vector sum_threshold; + sum_threshold.resize(height); + + uchar table[256]; + memset(table, 1, 256); + memset(table, 0, color); + + int sum, bit_sum; + for (size_t y = 0, bytePerLine = width * channels; y < height; y++) + { + sum = 0; + for (size_t x = 0; x < bytePerLine; x += channels) + { + bit_sum = 0; + for (size_t i = 0; i < channels; i++) + bit_sum |= table[ptr[x + i]]; + + sum += bit_sum; + } + sum_threshold[y] = sum; + ptr += bytePerLine; + } + + if (sum_threshold[0] > length || sum_threshold[height - 1] > length) + { + if (std::abs(sum_threshold[0] - sum_threshold[height - 1]) > 10) + return 1; + else + return 2; + } + + return 0; +} \ No newline at end of file diff --git a/imgproc/ContaminationDetection.h b/imgproc/ContaminationDetection.h new file mode 100644 index 0000000..9e98d7a --- /dev/null +++ b/imgproc/ContaminationDetection.h @@ -0,0 +1,51 @@ +/* + * ==================================================== + + * 功能:镜头脏污检测 + * 作者:刘丁维 + * 生成时间:2023/10/09 + * 最近修改时间:2023/10/09 v1.0 + 2023/11/08 v1.1 增加接口,对数据顶部和底部数据同时检测,避免受到纸张越界产生的误判。 + 2023/12/05 v1.2 增加接口,通过判定多行数据,来确认脏污性质。 + 2023/12/06 v1.2.1 微调接口2判定逻辑。 + * 版本号:v1.2.1 + + * ==================================================== + */ + +#ifndef CONTAMINATION_DETECTION_H +#define CONTAMINATION_DETECTION_H + +typedef unsigned char uchar; + +class ContaminationDetection +{ +public: + ContaminationDetection(); + + /// + /// 检测 + /// + /// top行待测数据 + /// bottom行待测数据 + /// 数据长度 + /// 第一阈值,超过该阈值视为存在脏污 + /// 第二阈值,配合width使用,超过该阈值且连续宽度达到width视为存在脏污 + /// 脏污宽度,配合threshold2使用 + /// 为0时表示无污染,反之有污染。 + static int detect1(const uchar *data1, const uchar *data2, int length, uchar threshold1, uchar threshold2, int width); + + /// + /// 检测 + /// + /// 图像数据 + /// 像素宽度 + /// 高度 + /// 通道数 + /// 超过该阈值视为存在脏污 + /// 脏污累计宽度 + /// 为0时表示无污染;为1时表示脏污无规则,可能由纸张遮挡造成;为2时表示脏污规则 + static int detect2(const uchar *data, int width, int height, int channels, uchar color, int length); +}; + +#endif \ No newline at end of file diff --git a/imgproc/IPreproc.cpp b/imgproc/IPreproc.cpp new file mode 100644 index 0000000..934cd01 --- /dev/null +++ b/imgproc/IPreproc.cpp @@ -0,0 +1,5 @@ +#include "IPreproc.h" + +IPreproc::IPreproc(void) {} + +IPreproc::~IPreproc(void) {} \ No newline at end of file diff --git a/imgproc/IPreproc.h b/imgproc/IPreproc.h new file mode 100644 index 0000000..d70b4ba --- /dev/null +++ b/imgproc/IPreproc.h @@ -0,0 +1,13 @@ +#pragma once +#include +#include + +class IPreproc +{ +public: + IPreproc(void); + + virtual ~IPreproc(void); + + virtual int preprocess(cv::Mat &mat, void *unused = nullptr) = 0; +}; \ No newline at end of file diff --git a/imgproc/cvimagex.cpp b/imgproc/cvimagex.cpp new file mode 100644 index 0000000..ee9d5d2 --- /dev/null +++ b/imgproc/cvimagex.cpp @@ -0,0 +1,32 @@ +#include "cvimagex.h" +#include "opencv2/opencv.hpp" + +CvImageX::CvImageX(MatPtr image) +{ + this->image = image; +} + +unsigned char *CvImageX::data() +{ + return image->data; +} + +int CvImageX::width() +{ + return image->cols; +} + +int CvImageX::height() +{ + return image->rows; +} + +int CvImageX::datasize() +{ + return height() * image->step; +} + +int CvImageX::type() +{ + return image->type(); +} \ No newline at end of file diff --git a/imgproc/cvimagex.h b/imgproc/cvimagex.h new file mode 100644 index 0000000..65b6b9d --- /dev/null +++ b/imgproc/cvimagex.h @@ -0,0 +1,22 @@ +#include "imgproc.h" + +namespace cv +{ + class Mat; +} + +typedef std::shared_ptr MatPtr; + +class CvImageX : public IImage +{ +public: + CvImageX(MatPtr image); + virtual unsigned char *data(); + virtual int width(); + virtual int height(); + virtual int type(); + virtual int datasize(); + +private: + MatPtr image; +}; \ No newline at end of file diff --git a/imgproc/iimage.h b/imgproc/iimage.h new file mode 100644 index 0000000..5a39883 --- /dev/null +++ b/imgproc/iimage.h @@ -0,0 +1,34 @@ +#pragma once +#include +#include +#include + +class IImage +{ +public: + virtual ~IImage() {} + + virtual unsigned char *data() = 0; + virtual int width() = 0; + virtual int height() = 0; + virtual int type() = 0; + virtual int stride() = 0; + virtual int datasize() = 0; +}; + +typedef std::shared_ptr IImagePtr; + +class IImagePair +{ +public: + IImagePair(IImagePtr imagef, IImagePtr imageb) + { + this->imagef = imagef; + this->imageb = imageb; + } + + IImagePtr imagef; + IImagePtr imageb; +}; + +typedef std::shared_ptr IImagePairPtr; \ No newline at end of file diff --git a/imgproc/iimageencode.h b/imgproc/iimageencode.h new file mode 100644 index 0000000..87551ee --- /dev/null +++ b/imgproc/iimageencode.h @@ -0,0 +1,18 @@ +#pragma once +#include "imemory.h" +#include "imgproc.h" + +namespace cv +{ + class Mat; +} + +class IImageEncode +{ +public: + virtual ~IImageEncode() {} + + virtual MemoryPtr encode(cv::Mat &image) = 0; +}; + +typedef std::shared_ptr ImageEncodePtr; \ No newline at end of file diff --git a/imgproc/imageencode.cpp b/imgproc/imageencode.cpp new file mode 100644 index 0000000..7767192 --- /dev/null +++ b/imgproc/imageencode.cpp @@ -0,0 +1,52 @@ +#include "imageencode.h" +#include "memoryex.h" +#include "opencv2/opencv.hpp" +#include "StopWatch.h" + +BmpImageEncode::~BmpImageEncode() +{ +} + +MemoryPtr BmpImageEncode::encode(cv::Mat &image) +{ + VectorMemroyPtr mem = VectorMemroyPtr(new VectorMemroy()); + // StopWatch sw; + cv::imencode(".bmp", image, mem->buf()); + // printf("encode time = %0.2f \n", sw.elapsed_ms()); + return mem; +} + +JpegImageEncode::JpegImageEncode(bool bwimg) +{ + if (!bwimg) + { + compression_params.push_back(cv::IMWRITE_JPEG_QUALITY); + compression_params.push_back(100); + } + else + { + compression_params.push_back(CV_IMWRITE_PNG_STRATEGY); + compression_params.push_back(cv::IMWRITE_PNG_STRATEGY_FIXED); + } + m_bwimg = bwimg; +} + +JpegImageEncode::~JpegImageEncode() +{ +} +MemoryPtr JpegImageEncode::encode(cv::Mat &image) +{ + VectorMemroyPtr mem = VectorMemroyPtr(new VectorMemroy()); + // StopWatch sw; + cv::imencode(m_bwimg ? ".png" : ".jpg", image, mem->buf(), compression_params); + // printf("encode time = %0.2f \n", sw.elapsed_ms()); + return mem; +} + +MemoryPtr buff2mem(void *data, int size) +{ + auto mem = std::shared_ptr(new VectorMemroy()); + mem->buf().resize(size); + // memcpy(mem->buf().data(), data, size); + return mem; +} \ No newline at end of file diff --git a/imgproc/imageencode.h b/imgproc/imageencode.h new file mode 100644 index 0000000..850f657 --- /dev/null +++ b/imgproc/imageencode.h @@ -0,0 +1,31 @@ +#pragma once +#include "iimageencode.h" +#include + +// typedef struct tagBITMAPFILEHEADER { +// WORD bfType; +// DWORD bfSize; +// WORD bfReserved1; +// WORD bfReserved2; +// DWORD bfOffBits; +// } BITMAPFILEHEADER, *PBITMAPFILEHEADER; + +class BmpImageEncode : public IImageEncode +{ +public: + virtual ~BmpImageEncode(); + + virtual MemoryPtr encode(cv::Mat &image); +}; + +class JpegImageEncode : public IImageEncode +{ +public: + JpegImageEncode(bool bwimg); + virtual ~JpegImageEncode(); + virtual MemoryPtr encode(cv::Mat &image); + +private: + std::vector compression_params; + bool m_bwimg; +}; diff --git a/imgproc/imageprocess b/imgproc/imageprocess new file mode 160000 index 0000000..8c7759d --- /dev/null +++ b/imgproc/imageprocess @@ -0,0 +1 @@ +Subproject commit 8c7759dba203f0a01d586d8c8174df54fcda7602 diff --git a/imgproc/imemory.h b/imgproc/imemory.h new file mode 100644 index 0000000..943339f --- /dev/null +++ b/imgproc/imemory.h @@ -0,0 +1,17 @@ +#pragma once +#include +#include +// #include + +class IMemory +{ +public: + virtual ~IMemory() {} + + virtual unsigned char *data() = 0; + virtual size_t size() = 0; +}; + +typedef std::shared_ptr MemoryPtr; + +MemoryPtr buff2mem(void *data, int size); \ No newline at end of file diff --git a/imgproc/imgproc.h b/imgproc/imgproc.h new file mode 100644 index 0000000..70c596a --- /dev/null +++ b/imgproc/imgproc.h @@ -0,0 +1,19 @@ +#pragma once +#include "iimage.h" + +class IImPorc +{ +public: + virtual ~IImPorc() {} + virtual IImagePairPtr proc(IImagePairPtr image) = 0; +}; + +class IImageWrite +{ +public: + virtual ~IImageWrite() {} + + virtual bool save(std::string path, std::vector params) = 0; +}; + +typedef std::shared_ptr ImageWritePtr; \ No newline at end of file diff --git a/imgproc/memoryex.h b/imgproc/memoryex.h new file mode 100644 index 0000000..8032a33 --- /dev/null +++ b/imgproc/memoryex.h @@ -0,0 +1,62 @@ +#pragma once +#include "imemory.h" + +class VectorMemroy : public IMemory +{ +public: + virtual unsigned char *data() + { + return m_data.empty() ? nullptr : &m_data[0]; + } + + virtual size_t size() + { + return m_data.size(); + } + + std::vector &buf() + { + return m_data; + } + + void resize(int size) + { + m_data.resize(size); + } + +private: + std::vector m_data; +}; + +typedef std::shared_ptr VectorMemroyPtr; + +// class FipMemory : public IMemory +// { +// public: +// FipMemory(){} +// virtual unsigned char *data() +// { +// unsigned char *p; +// DWORD size; +// mio.acquire(&p, &size); +// return p; +// } + +// virtual size_t size() +// { +// unsigned char *p; +// DWORD size; +// mio.acquire(&p, &size); +// return size; +// } + +// fipMemoryIO &io() +// { +// return mio; +// } + +// private: +// fipMemoryIO mio; +// }; + +// typedef std::shared_ptr FipMemoryPtr; \ No newline at end of file diff --git a/keymonitor/CMakeLists.txt b/keymonitor/CMakeLists.txt new file mode 100644 index 0000000..8b16bc6 --- /dev/null +++ b/keymonitor/CMakeLists.txt @@ -0,0 +1,18 @@ +project(keymonitor) +add_compile_options(-std=c++14) +#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -O2") +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -O2") + +aux_source_directory(${PROJECT_SOURCE_DIR} DIR_SRCS) +file(GLOB DIR_HEADS "${PROJECT_SOURCE_DIR}/*.h" "${PROJECT_SOURCE_DIR}/*.hpp") +set(DIR_SRCS ${DIR_SRCS} ${DIR_HEADS}) + + +add_library(${PROJECT_NAME} STATIC ${DIR_SRCS} ${DIR_SUBSRC}) + +target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR}/../packages/common.pkg/include + ${PROJECT_SOURCE_DIR}/../deviceio + ) + +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../bin) \ No newline at end of file diff --git a/keymonitor/keymonitor.cpp b/keymonitor/keymonitor.cpp new file mode 100644 index 0000000..14362a5 --- /dev/null +++ b/keymonitor/keymonitor.cpp @@ -0,0 +1,204 @@ +#include "keymonitor.h" +#include "Gpio.h" +#include "PinMonitor.h" +#include + +#define STATUS_SUCCESS 0 +#define STATUS_FAILURE -1 + +#define CH455_GET_KEY 0x0700 // 获取按键,返回按键代码 +#define CH455_SYSOFF 0x0400 // 关闭显示、关闭键盘 + +#define CH455_I2C_ADDR 0x40 // CH455的地址 +#define CH455_I2C_MASK 0x3E // CH455的高字节命令掩码 + +#define CH455_BIT_ENABLE 0x01 +//#define CH455_BIT_ENABLE 0x03 // 开启/关闭位 +#define CH455_BIT_SLEEP 0x04 // 睡眠控制位 + + +#define CH455_SYSON ( CH455_SYSOFF | CH455_BIT_ENABLE ) +#define CH455_SLEEPOFF CH455_SYSOFF // 关闭睡眠 +#define CH455_SLEEPON (CH455_SYSOFF|CH455_BIT_SLEEP) // 开启睡眠 + +KeyMonitor::KeyMonitor(std::function keycall) : m_keycall(keycall) +{ + m_gpioi2c_SCL = std::make_shared(44); //I2C_SCL + m_gpioi2c_SCL->setDirection(Gpio::out); + m_gpioi2c_SDA = std::make_shared(43); //I2C_SDA + m_gpioi2c_SDA->setDirection(Gpio::out); + write_cmd(CH455_SYSON); + printf("read_key = %02x\n", read_key()); + setled(HGLed::Led_All_close); + auto pincall=[&](int pin) + { + auto value= read_key(); + printf("Key = %02x pin value = %d \n",value,pin); + if(m_keycall) + m_keycall(value); + }; + m_keymonitor = std::make_shared(52,pincall); +} + +KeyMonitor::~KeyMonitor() +{ + if(m_gpioi2c_SCL.get()) + m_gpioi2c_SCL.reset(); + + if(m_gpioi2c_SDA.get()) + m_gpioi2c_SDA.reset(); + + if(m_keymonitor.get()) + m_keymonitor.reset(); +} + +void KeyMonitor::init() +{ +} + +void KeyMonitor::i2c_start() +{ + m_gpioi2c_SDA->setValue(Gpio::GpioLevel::High); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::High); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SDA->setValue(Gpio::GpioLevel::Low); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::Low); + std::this_thread::sleep_for(std::chrono::microseconds(5)); +} + +void KeyMonitor::i2c_write(unsigned char cmd) +{ + unsigned char i; + for(i=0; i<8; i++) + { + //IOWR(I2C_SCL, 0); //钳住I2C总线,准备发送数据 + if(cmd & 0x80) + m_gpioi2c_SDA->setValue(Gpio::GpioLevel::High); + else + m_gpioi2c_SDA->setValue(Gpio::GpioLevel::Low); + + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::High); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::Low); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + cmd<<=1; + } + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SDA->setValue(Gpio::GpioLevel::High); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::High); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::Low); + std::this_thread::sleep_for(std::chrono::microseconds(5)); +} + +unsigned char KeyMonitor::i2c_read() +{ + unsigned char bytedata = 0; + m_gpioi2c_SDA->setDirection(Gpio::in);//将数据设置为输入模式 + //m_gpioi2c_SDA->setValue(Gpio::GpioLevel::High); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::Low); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + for(int i=0; i<8; i++) + { + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::High); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + bytedata <<= 1; + bytedata = bytedata | (m_gpioi2c_SDA->getValue()); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::Low); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + } + m_gpioi2c_SDA->setDirection(Gpio::out); + m_gpioi2c_SDA->setValue(Gpio::GpioLevel::High);////数据线设置回输出模式 + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::High); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::Low); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + return bytedata; +} + +void KeyMonitor::i2c_stop() +{ + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::Low); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SDA->setValue(Gpio::GpioLevel::Low); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::High); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SDA->setValue(Gpio::GpioLevel::High); + std::this_thread::sleep_for(std::chrono::microseconds(5)); +} + +void KeyMonitor::write_cmd(unsigned short cmd) +{ + i2c_start(); + i2c_write(((unsigned char)(cmd>>7)&CH455_I2C_MASK)|CH455_I2C_ADDR); + i2c_write(cmd); + i2c_stop(); +} + +unsigned char KeyMonitor::read_key() +{ + unsigned char key=0; + i2c_start(); + i2c_write((unsigned char)(CH455_GET_KEY>>7)&CH455_I2C_MASK|0x01|CH455_I2C_ADDR); + key = i2c_read(); + i2c_stop(); + return key; +} + +std::uint8_t KeyMonitor::getledstate() +{ + return m_ledstate; +} + +void KeyMonitor::setled(HGLed value) +{ + switch (value) + { + case HGLed::Led_All_close: + m_ledstate = 0; + break; +#ifdef G200 + case HGLed::Led_All_open: + m_ledstate = 0xf8; + break; + case HGLed::Led_Count_close: + m_ledstate = m_ledstate & 0xef; + break; + case HGLed::Led_Count_open: + m_ledstate = m_ledstate | 0x10; + break; + case HGLed::Led_DoubleFeed_close: + m_ledstate = m_ledstate & 0xbf; + break; + case HGLed::Led_DoubleFeed_open: + m_ledstate = m_ledstate | 0x40; + break; + case HGLed::Led_Enter_close: + m_ledstate = m_ledstate & 0xf7; + break; + case HGLed::Led_Enter_open: + m_ledstate = m_ledstate | 0x8; + break; + case HGLed::Led_Handle_close: + m_ledstate = m_ledstate & 0xdf; + break; + case HGLed::Led_Handle_open: + m_ledstate = m_ledstate | 0x20; + break; +#endif + default: + break; + } + i2c_start(); + i2c_write(0x6e); + i2c_write(m_ledstate); + i2c_stop(); +} diff --git a/keymonitor/keymonitor.h b/keymonitor/keymonitor.h new file mode 100644 index 0000000..832d8b4 --- /dev/null +++ b/keymonitor/keymonitor.h @@ -0,0 +1,71 @@ +#pragma once + +#include +#include +#include "commondef.h" +class PinMonitor; +class Gpio; + +class KeyMonitor +{ +public: +#ifdef G200 + enum class HGKey + { + Key_Enter = 69, + Key_Cancle = 70, + Key_Count = 78, + Key_Handle = 77, + Key_DoubleFeed = 68, + Key_Left = 86, + Key_Menu = 85, + Key_Right = 76, + Key_Clear = 84 + }; +#else + enum class HGKey + { + Key_Enter = 70, + Key_Cancle = 69, + Key_Count = 78, + Key_Menu = 76, + Key_Right = 77, + Key_Clear = 68, + Key_Handle = 3331, + Key_DoubleFeed = 3332, + Key_Left = 3333 + }; +#endif + enum class HGLed + { + Led_Enter_open = 0, + Led_Enter_close, + Led_Count_open, + Led_Count_close, + Led_DoubleFeed_open, + Led_DoubleFeed_close, + Led_Handle_open, + Led_Handle_close, + Led_All_open, + Led_All_close + }; +public: + KeyMonitor(std::function keycall); + void setled(HGLed value); + std::uint8_t getledstate(); + ~KeyMonitor(); +private: + void init(); + void i2c_start(); + void i2c_write(unsigned char cmd); + unsigned char i2c_read(); + void i2c_stop(); + void write_cmd(unsigned short cmd); + unsigned char read_key(); +private: + std::shared_ptr m_keymonitor; + std::shared_ptr m_gpioi2c_SDA; + std::shared_ptr m_gpioi2c_SCL; + std::function m_keycall; + volatile std::uint8_t m_ledstate; +}; \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..6279872 --- /dev/null +++ b/main.cpp @@ -0,0 +1,48 @@ +#include +#include +#include +#include +#include +#include + +void test() +{ + auto _start = std::chrono::steady_clock::now(); + int arr[1000000]; + for (size_t i = 0; i < 1000000; i++) + { + for (size_t j = 0; j < 1000; j++) + { + arr[i] = i; + } + } + auto times = std::chrono::duration(std::chrono::steady_clock::now() - _start).count(); + printf("times = %.2f \n", times); +} + +int main(int argc, char *argv[]) +{ + struct sched_param param; + int maxpri; + maxpri = sched_get_priority_max(SCHED_FIFO); //»ñÈ¡×î´óÖµ + if (maxpri == -1) + { + printf("sched_get_priority_max() failed \n"); + exit(1); + } + printf("%d \n", maxpri); + param.sched_priority = maxpri; + std::thread threadaa(test); + // if (sched_setscheduler(getpid(), SCHED_FIFO, ¶m) == -1) //设置优先级 + // { + // printf("sched_setscheduler() failed \n"); + // exit(1); + // } + // if(pthread_setschedparam(threadaa.native_handle(),SCHED_FIFO,¶m)) + // { + // printf("sched_setscheduler() failed \n"); + // exit(1); + // } + threadaa.join(); + return 0; +} \ No newline at end of file diff --git a/motorboard/CMakeLists.txt b/motorboard/CMakeLists.txt new file mode 100644 index 0000000..de5d890 --- /dev/null +++ b/motorboard/CMakeLists.txt @@ -0,0 +1,39 @@ +project(motorboard) +add_compile_options(-std=c++14) + +aux_source_directory(${PROJECT_SOURCE_DIR} DIR_SRCS) +file(GLOB DIR_HEADS "${PROJECT_SOURCE_DIR}/*.h" "${PROJECT_SOURCE_DIR}/*.hpp") +set(DIR_SRCS ${DIR_SRCS} ${DIR_HEADS}) +if(CMAKE_HOST_WIN32) +link_libraries( + libopencv_world.a + liblibjasper.a + libittnotify.a + libtegra_hal.a + libzlib.a + liblibjpeg-turbo.a + liblibpng.a + liblibtiff.a + liblibwebp.a +) +else() +link_libraries( + opencv_core + opencv_imgproc + opencv_imgcodecs +) +endif() +add_library(${PROJECT_NAME} STATIC ${DIR_SRCS}) + +target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR}/../packages/common.pkg/include + ${PROJECT_SOURCE_DIR}/../deviceio + ${PROJECT_SOURCE_DIR}/../regs + ${PROJECT_SOURCE_DIR}/../applog + ${PROJECT_SOURCE_DIR}/../capimage + ${PROJECT_SOURCE_DIR}/../motorcontroller + ${PROJECT_SOURCE_DIR}/../scanner + ${PROJECT_SOURCE_DIR}/../display + ) + +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../bin) \ No newline at end of file diff --git a/motorboard/FeedControl.cpp b/motorboard/FeedControl.cpp new file mode 100644 index 0000000..a434180 --- /dev/null +++ b/motorboard/FeedControl.cpp @@ -0,0 +1,69 @@ +#include "FeedControl.h" +#include +#include + +FeedControl::FeedControl(/* args */) : m_thre(0.3) +{ +} + +FeedControl::~FeedControl() +{ +} + +FeedControl::FeedMode FeedControl::GetPredictFeedMode() +{ + return calcFeedMode(); +} + +FeedControl::FeedMode FeedControl::calcFeedMode() +{ + FeedMode mode = FeedMode::FMode_NOChange; + auto infos = m_sessioninfo.GetRecordInfo(); + if (infos.size() < 10) //样本数量大于10了 才做分纸模式分析切换 + return mode; + + unsigned int nDoubleFeedTimes, nJamTimes, nFeedErrorTimes, nTotalScanned; + nDoubleFeedTimes = nJamTimes = nFeedErrorTimes = nTotalScanned = 0; + for (auto &item : infos) + { + if (!item.NormalDone) + { + if (item.DoubleFeed) + nDoubleFeedTimes++; + if (item.Jammed) + nJamTimes++; + if (item.FeedError) + nFeedErrorTimes++; + + nTotalScanned += item.CurrentScaned; + } + } + + double percentHigh = nDoubleFeedTimes / 10.0; + double percentLow = nFeedErrorTimes / 10.0; + printf("\n percentHigh : %f percentLow : %f" , percentHigh,percentLow); + if (percentHigh >= m_thre || percentLow >= m_thre) + { + mode = percentHigh >= percentLow ? FeedMode::FMode_High : FeedMode::FMode_Low; + if(fabs(percentHigh - percentLow) < 0.2) + mode = FeedMode::FMode_Mid; + ResetMode(); + } + printf("\n Calc Feed Mode : %d" , (int)mode); + return mode; +} + +void FeedControl::AppendPattern(MotorSessionInfo::MBTaskRecordInfo info) +{ + m_sessioninfo.UpdateRecordInfo(info); +} + +void FeedControl::SetThre(double thre) +{ + m_thre = thre; +} + +void FeedControl::ResetMode() +{ + m_sessioninfo.RemoveInfos(); +} \ No newline at end of file diff --git a/motorboard/FeedControl.h b/motorboard/FeedControl.h new file mode 100644 index 0000000..771a05b --- /dev/null +++ b/motorboard/FeedControl.h @@ -0,0 +1,31 @@ +#pragma once +#include "MotorSessionInfo.h" + +class FeedControl +{ +public: + enum class FeedMode + { + FMode_Low, + FMode_Mid, + FMode_High, + FMode_NOChange, + }; +public: + FeedControl(/* args */); + ~FeedControl(); + //设置搓纸模式匹配阈值 + void SetThre(double thre); + //获取预测搓纸模式 + FeedMode GetPredictFeedMode(); + //搓纸模式变更时 清除配置记录信息 + void ResetMode(); + //更新走纸流程相关信息 + void AppendPattern(MotorSessionInfo::MBTaskRecordInfo info); +private: + FeedMode calcFeedMode(); +private: + MotorSessionInfo m_sessioninfo; + double m_thre; +}; + diff --git a/motorboard/Jtag.cpp b/motorboard/Jtag.cpp new file mode 100644 index 0000000..aeab5e2 --- /dev/null +++ b/motorboard/Jtag.cpp @@ -0,0 +1,95 @@ +#include "Jtag.h" + +Jtag::Jtag():jtag_tms(152),jtag_tck(156),jtag_tdi(155),jtag_tdo(72),COM_BOOT0(153) +{ + printf("Jtag()\n"); + char fname[128]; + + write_dev("/sys/class/gpio/export", 152); + write_dev("/sys/class/gpio/export", 156); + write_dev("/sys/class/gpio/export", 155); + write_dev("/sys/class/gpio/export", 72); + write_dev("/sys/class/gpio/export", 153); + + + jtag_tms.setDirection(Gpio::out); + jtag_tck.setDirection(Gpio::out); + jtag_tdi.setDirection(Gpio::out); + jtag_tdo.setDirection(Gpio::in); + COM_BOOT0.setDirection(Gpio::out); + + COM_BOOT0.setValue(Gpio::High); + jtag_tms.setValue(Gpio::Low); + jtag_tck.setValue(Gpio::Low); + jtag_tdi.setValue(Gpio::Low); + + +} + +void Jtag::TMS_Wr(u8 value) +{ + if(value == 1) + jtag_tms.setValue(Gpio::High); + else + jtag_tms.setValue(Gpio::Low); +} + +u8 Jtag::TMS_RD() +{ + return jtag_tms.getValue(); +} + +void Jtag::TCK_Wr(u8 value) +{ + if(value == 1) + jtag_tck.setValue(Gpio::High); + else + jtag_tck.setValue(Gpio::Low); +} + +u8 Jtag::TCK_RD() +{ + return jtag_tck.getValue(); +} + +void Jtag::TDI_Wr(u8 value) +{ + if(value == 1) + jtag_tdi.setValue(Gpio::High); + else + jtag_tdi.setValue(Gpio::Low); +} + +u8 Jtag::TDI_RD() +{ + return jtag_tdi.getValue(); +} + +u8 Jtag::TDO_RD() +{ + return jtag_tdo.getValue(); +} + +void Jtag::Anlogic_Calibration(void) +{ + /*Apply 2 pulses to TCK.*/ + TCK_Wr(1); + TCK_Wr(1); + TCK_Wr(0); + TCK_Wr(1); + TCK_Wr(0); + TCK_Wr(1); + TCK_Wr(1); + /*Delay for 1 millisecond. Pass on 1000 = 1ms delay.*/ + + Anlogic_ProcessRunTestTck(10000) ; + /*Apply 2 pulses to TCK*/ + TCK_Wr(1); + TCK_Wr(1); + TCK_Wr(0); + TCK_Wr(1); + TCK_Wr(0); + TCK_Wr(1); + TCK_Wr(1); + +} \ No newline at end of file diff --git a/motorboard/Jtag.h b/motorboard/Jtag.h new file mode 100644 index 0000000..05edc5d --- /dev/null +++ b/motorboard/Jtag.h @@ -0,0 +1,41 @@ +#ifndef HGSCANSERVICE_JTAG_H +#define HGSCANSERVICE_JTAG_H + +#include +#include +#include +#include +#include +#include "DevUtil.h" +#include "Gpio.h" +#include +#include +#include + +extern void Anlogic_ProcessRunTestTck(int num); + +typedef unsigned int u32; +typedef unsigned char u8; + +class Jtag +{ +private: + Gpio jtag_tms; + Gpio jtag_tck; + Gpio jtag_tdi; + Gpio jtag_tdo; + Gpio COM_BOOT0; + +public: + Jtag(); + void TMS_Wr(u8 value); + u8 TMS_RD(); + void TCK_Wr(u8 value); + u8 TCK_RD(); + void TDI_Wr(u8 value); + u8 TDI_RD(); + u8 TDO_RD(); + void Anlogic_Calibration(void); +}; + +#endif \ No newline at end of file diff --git a/motorboard/MotorConfig.cpp b/motorboard/MotorConfig.cpp new file mode 100644 index 0000000..b022ff2 --- /dev/null +++ b/motorboard/MotorConfig.cpp @@ -0,0 +1,195 @@ +#include "MotorConfig.h" +#include +#include +#include +#include + +using namespace std; +MotorConfig::MotorConfig() +{ + initconfigfile(); +} + +MotorConfig::~MotorConfig() +{ +} + +std::string MotorConfig::GetParams(bool bzouzhi, MTBDType mttype) +{ + std::string j_str; + json j; + if (mttype == MTBDType::MT_TMC) + { + std::ifstream i(bzouzhi ? MT_TMC216_ZOU_PATH : MT_TMC216_CUO_PATH); + i >> j; + j_str = j.dump(); + i.close(); + } + else + { + std::ifstream i(bzouzhi ? MT_DRV888_ZOU_PATH : MT_DRV888_CUO_PATH); + i >> j; + j_str = j.dump(); + i.close(); + } + return j_str; +} + +void MotorConfig::SetParams(bool bzouzhi, MTBDType mttype, MotorSpeedParamEx ¶m) +{ + std::string path; + auto params = GetMotorSpeedParams(bzouzhi, mttype); + for (int i = 0; i < params.size(); i++) + { + if (params[i].dpi == param.dpi && + params[i].colormode == param.colormode && + params[i].speed == param.speed) + { + params[i] = param; + } + } + + json j = json::array(); + + for (int i = 0; i < params.size(); i++) + { + json t_j; + to_json(params[i], t_j); + j.push_back(t_j); + } + + if (mttype == MTBDType::MT_TMC) + path = bzouzhi?MT_TMC216_ZOU_PATH:MT_TMC216_CUO_PATH; + else + path = bzouzhi?MT_DRV888_ZOU_PATH:MT_DRV888_CUO_PATH; + + ofstream ofs(path); + ofs << std::setw(4) << j << std::endl; + ofs.close(); +} + +std::vector MotorConfig::GetMotorSpeedParams(bool bzouzhi, MTBDType mttype) +{ + std::vector ret; + if (mttype == MTBDType::MT_TMC) + { + std::ifstream i(bzouzhi ? MT_TMC216_ZOU_PATH : MT_TMC216_CUO_PATH); + json j; + i >> j; + i.close(); + for (json::iterator it = j.begin(); it != j.end(); ++it) + { + auto tmv = it.value(); + MotorSpeedParamEx param; + from_json(tmv, param); + ret.push_back(param); + } + } + else + { + std::ifstream i(bzouzhi ? MT_DRV888_ZOU_PATH : MT_DRV888_CUO_PATH); + json j; + i >> j; + i.close(); + for (json::iterator it = j.begin(); it != j.end(); ++it) + { + auto tmv = it.value(); + MotorSpeedParamEx param; + from_json(tmv, param); + ret.push_back(param); + } + } + return ret; +} + +void MotorConfig::initconfigfile() +{ + struct stat buff; + for (int s = 0; s < m_jsonpaths.size(); s++) + { + if (stat(m_jsonpaths[s].c_str(), &buff) != 0) //不存在 + { + { + json j = json::array(); + for (int i = 1; i < 6; i++) + { + MotorSpeedParamEx param; + for (int k = 1; k < 4; k++) + { + float ratio = k == 1 ? 1 : (k == 2 ? 1.51 : 2.81); + param.mt_param.finalPeriod = s >= 2 ? 2000 / 4 *ratio: 2000*ratio; // s < 2 drv888 + param.mt_param.finalPeriod = s >= 2 ? 2000 / 4 : 2000; // s < 2 drv888 + param.mt_param.Fmin = s >= 2 ? 80000 / 4 : 80000; + param.mt_param.stepnum = 0.5; + param.mt_param.a = 0.35; + param.mt_param.offset = -5.7; + param.mt_param.finalDelay = 2500; + param.mt_param.acceleration_time = 2; + param.speed = i; // 0 gray 1 color + param.dpi = k; // 1 200dpi 2 300dpi 3 600dpi + param.sp = 1200; + for(int t = 0;t<2;t++) + { + param.colormode = t; + json t_j; + to_json(param, t_j); + j.push_back(t_j); + } + } + } + ofstream ofs(m_jsonpaths[s]); + ofs << std::setw(4) << j << std::endl; + ofs.close(); + } + } + } +} + +std::vector MotorConfig::GetMotorSpeedParams(const std::string& json_str) +{ + std::vector ret; + if(json_str.length()) + { + json j = json::parse(json_str); + for (json::iterator it = j.begin(); it != j.end(); ++it) + { + auto tmv = it.value(); + MotorSpeedParamEx param; + from_json(tmv, param); + ret.push_back(param); + } + + } + return ret; +} + +void MotorConfig::to_json(MotorSpeedParamEx ¶m, json &j) +{ + j = json{ + {"A", param.mt_param.a}, + {"FINALDELAY", param.mt_param.finalDelay}, + {"FINALPERIOD", param.mt_param.finalPeriod}, + {"FMIN", param.mt_param.Fmin}, + {"OFFSET", param.mt_param.offset}, + {"STEPNUM", param.mt_param.stepnum}, + {"DPI", param.dpi}, + {"COLORMODE", param.colormode}, + {"ACCELERATIONTIME",param.mt_param.acceleration_time}, + {"SPEED", param.speed}, + {"SP",param.sp}}; +} + +void MotorConfig::from_json(json &j, MotorSpeedParamEx ¶m) +{ + j.at("A").get_to(param.mt_param.a); + j.at("FINALDELAY").get_to(param.mt_param.finalDelay); + j.at("FINALPERIOD").get_to(param.mt_param.finalPeriod); + j.at("FMIN").get_to(param.mt_param.Fmin); + j.at("OFFSET").get_to(param.mt_param.offset); + j.at("STEPNUM").get_to(param.mt_param.stepnum); + j.at("DPI").get_to(param.dpi); + j.at("ACCELERATIONTIME").get_to(param.mt_param.acceleration_time); + j.at("COLORMODE").get_to(param.colormode); + j.at("SPEED").get_to(param.speed), + j.at("SP").get_to(param.sp); +} \ No newline at end of file diff --git a/motorboard/MotorConfig.h b/motorboard/MotorConfig.h new file mode 100644 index 0000000..7b87e55 --- /dev/null +++ b/motorboard/MotorConfig.h @@ -0,0 +1,68 @@ +#pragma once +#include +#include "json.hpp" + +using json= nlohmann::json; + +struct MotorSpeedParam +{ + int finalPeriod; + int Fmin; + float stepnum; + float a; + float offset; + float finalDelay; + float acceleration_time; +}; + +struct MotorSpeedParamEx +{ + MotorSpeedParam mt_param; + int speed; + int colormode; + int dpi; + int sp; +}; + +#ifndef WIN32 +#define MT_DRV888_CUO_PATH "/usr/local/huago/drv888_cuo.json" +#define MT_DRV888_ZOU_PATH "/usr/local/huago/drv888_zou.json" +#define MT_TMC216_CUO_PATH "/usr/local/huago/tmc216_cuo.json" +#define MT_TMC216_ZOU_PATH "/usr/local/huago/tmc216_zou.json" +#else +#define MT_DRV888_CUO_PATH "drv888_cuo.json" +#define MT_DRV888_ZOU_PATH "drv888_zou.json" +#define MT_TMC216_CUO_PATH "tmc216_cuo.json" +#define MT_TMC216_ZOU_PATH "tmc216_zou.json" +#endif + +class MotorConfig +{ +private: + std::vector m_cuoParams; + std::vector m_zouParams; + const std::vector m_jsonpaths={ + MT_DRV888_CUO_PATH, + MT_DRV888_ZOU_PATH, + MT_TMC216_CUO_PATH, + MT_TMC216_ZOU_PATH + }; + +public: + enum class MTBDType + { + MT_TMC, + MT_DRV + }; + MotorConfig(/* args */); + ~MotorConfig(); + std::string GetParams(bool bzouzhi,MTBDType mttype); + void SetParams(bool bzouzhi,MTBDType mttype,MotorSpeedParamEx& param); + std::vector GetMotorSpeedParams(bool bzouzhi,MTBDType mttype); + std::vector GetMotorSpeedParams(const std::string& json_str); +private: + void initconfigfile(); + void to_json(MotorSpeedParamEx& param,json& j); + void from_json(json& j,MotorSpeedParamEx& param); +}; + diff --git a/motorboard/MotorSessionInfo.cpp b/motorboard/MotorSessionInfo.cpp new file mode 100644 index 0000000..d53872e --- /dev/null +++ b/motorboard/MotorSessionInfo.cpp @@ -0,0 +1,118 @@ + +#include "MotorSessionInfo.h" +#include +#include +#include +#include +#include +#define MBTASKPATH "/usr/local/huago/mbtaskinfos.json" + +MotorSessionInfo::MotorSessionInfo(/* args */) : m_maxrecord(10) +{ +} + +MotorSessionInfo::~MotorSessionInfo() +{ +} + +//获取近十次的扫描情况汇总 +std::vector MotorSessionInfo::GetRecordInfo() +{ + + std::vector infos; + json j = getjsonobj(); + printf("\n -------------json = %s",j.dump().c_str()); + for (json::iterator it = j.begin(); it != j.end(); ++it) + { + auto tmv = it.value(); + MBTaskRecordInfo param; + js2struct(param, tmv); + infos.push_back(param); + } + //printf("\n -------------GetRecordInfo size"); + return infos; +} + +//仅记录最近十次的扫描情况,大于十次按照时间戳去除早前的记录 +void MotorSessionInfo::UpdateRecordInfo(MotorSessionInfo::MBTaskRecordInfo info) +{ + auto records = GetRecordInfo(); + //std::sort(records.begin(), records.end()); + printf("\n -------------GetRecordInfo size = %d",records.size()); + if (records.size() > 10) + { + //records.pop_back(); + records.erase(records.begin()); + } + records.push_back(info); + savejsonobj(records); +} + +void MotorSessionInfo::RemoveInfos() +{ + std::lock_guard mutex(m_mutex); + system("rm -f /usr/local/huago/mbtaskinfos.json"); +} + +void MotorSessionInfo::js2struct(MotorSessionInfo::MBTaskRecordInfo &info, const json &j) +{ + j["CurrentScaned"].get_to(info.CurrentScaned); + j["DoubleFeed"].get_to(info.DoubleFeed); + j["FeedError"].get_to(info.FeedError); + j["Jammed"].get_to(info.Jammed); + j["NormalDone"].get_to(info.NormalDone); + j["TimeStampStart"].get_to(info.TimeStampStart); + j["TimeStampEnd"].get_to(info.TimeStampEnd); +} + +void MotorSessionInfo::struct2js(const MotorSessionInfo::MBTaskRecordInfo info, json &j) +{ + j["CurrentScaned"] = (info.CurrentScaned); + j["DoubleFeed"] = (info.DoubleFeed); + j["FeedError"] = (info.FeedError); + j["Jammed"] = (info.Jammed); + j["NormalDone"] = (info.NormalDone); + j["TimeStampStart"] = (info.TimeStampStart); + j["TimeStampEnd"] = (info.TimeStampEnd); +} + +json MotorSessionInfo::getjsonobj() +{ + std::lock_guard mutex(m_mutex); + struct stat buff; + json j; + if (stat(MBTASKPATH, &buff) == 0) //存在 + { + std::ifstream i(MBTASKPATH); + // std::string buf; + // buf.resize(buff.st_size); + // i.read(&buf[0],buff.st_size); + // j = json::parse(buf); + i >> j; + i.close(); + //printf("\n ----json = %s ",j.dump().c_str()); + } + return j; +} + + +void MotorSessionInfo::savejsonobj(std::vector infos) +{ + std::lock_guard mutex(m_mutex); + json j= json::array(); + printf("\n -------------infos size = %d",infos.size()); + for (size_t i = 0; i < infos.size(); i++) + { + json jitem; + struct2js(infos[i],jitem); + j.push_back(jitem); + } + + if(!j.empty()) + { + std::ofstream ofs(MBTASKPATH); + ofs << std::setw(4) << j << std::endl; + ofs.close(); + + } +} \ No newline at end of file diff --git a/motorboard/MotorSessionInfo.h b/motorboard/MotorSessionInfo.h new file mode 100644 index 0000000..ed4df00 --- /dev/null +++ b/motorboard/MotorSessionInfo.h @@ -0,0 +1,54 @@ +#pragma once +#include +#include +#include + +using json = nlohmann::json; +class MotorSessionInfo +{ +public: + struct MBTaskRecordInfo + { + unsigned int CurrentScaned; + bool NormalDone; + bool Jammed; + bool DoubleFeed; + bool FeedError; + long TimeStampStart; + long TimeStampEnd; + bool operator < (const MBTaskRecordInfo& info) + { + return this->TimeStampEnd > info.TimeStampEnd; + } + + void Start() + { + std::chrono::time_point tpMicro = \ + std::chrono::time_point_cast(std::chrono::system_clock::now()); + this->TimeStampStart = tpMicro.time_since_epoch().count(); + } + + void Stop() + { + std::chrono::time_point tpMicro = \ + std::chrono::time_point_cast(std::chrono::system_clock::now()); + this->TimeStampEnd = tpMicro.time_since_epoch().count(); + } + }; + //nscanned / 300 nscanned∈[1,300] 即取值范围为[0,1.0] + +public: + MotorSessionInfo(/* args */); + ~MotorSessionInfo(); + std::vector GetRecordInfo();// m_mbtaskrecordInfos; + void UpdateRecordInfo(MBTaskRecordInfo info); + void RemoveInfos(); +private: + void js2struct(MBTaskRecordInfo& info,const json& j); + void struct2js(const MBTaskRecordInfo info,json& j); + json getjsonobj(); + void savejsonobj(std::vector infos); +private: + int m_maxrecord; + std::mutex m_mutex;//避免读写冲突 json文件丢失 +}; diff --git a/motorboard/SensorConfig.cpp b/motorboard/SensorConfig.cpp new file mode 100644 index 0000000..af8ed2f --- /dev/null +++ b/motorboard/SensorConfig.cpp @@ -0,0 +1,147 @@ +#include "SensorConfig.h" +#include +#include +#include +#include +#include + +SensorConfig m_static_sensorconfig; + +SensorConfig::SensorConfig(/* args */) +{ + { + std::lock_guard m_lc(m_lock); + initconfigfile(); + } + get_param(); +} + +SensorConfig::~SensorConfig() +{ +} + +SensorConfig::SensorConfig_Param SensorConfig::get_param() +{ + std::lock_guard m_lc(m_lock); + if(access(this->Path.c_str(),0) == -1) + { + initconfigfile(); + return m_param; + } + std::ifstream i(this->Path); + auto pos = i.tellg(); + i.seekg(0, std::ios::end); + if (i.tellg() <= 2) + { + initconfigfile(); + return m_param; + } + i.seekg(pos); + json m_json; + i >> m_json; + i.close(); + m_param = to_param(m_json); + return m_param; +} + +void SensorConfig::set_param(SensorConfig::SensorConfig_Param param) +{ + std::lock_guard m_lc(m_lock); + m_param = param; + auto js = to_json(param); + std::ofstream o(this->Path); + o << std::setw(4) << js < m_lc(m_lock); + if(access(this->Path.c_str(),F_OK) == 0) + return; + SensorConfig::SensorConfig_Param param{ + .Sensor_Scan_Pwm = 40, + .Sensor_ConverOpen_Pwm = 40, + .Sensor_Screw_1_Pwm = 40, + .Sensor_Screw_2_Pwm = 40, + .Sensor_PaperOut_Pwm = 40, + .Sensor_PaperDetection_Pwm = 40, + .Sensor_Double_double_check_cyc = 4, + .Sensor_Double_paper_check_cyc = 8, + .Sensor_Double_double_max = 0x1c, + .Sensor_Double_single_max = 0x70, + }; + m_param = param; + printf("\nfile: %s not found creat ...",this->Path.c_str()); + json js = to_json(param); + std::ofstream o(this->Path); + o << std::setw(4) << js < m_lc(m_lock); + remove(this->Path.c_str()); + initconfigfile(); +} + +json SensorConfig::to_json(SensorConfig::SensorConfig_Param param) +{ + json js; + js[Sensor_Scan_Pwm] = param.Sensor_Scan_Pwm; + js[Sensor_Screw_1_Pwm] = param.Sensor_Screw_1_Pwm; + js[Sensor_Screw_2_Pwm] = param.Sensor_Screw_2_Pwm; + js[Sensor_ConverOpen_Pwm] = param.Sensor_ConverOpen_Pwm; + js[Sensor_PaperOut_Pwm] = param.Sensor_PaperOut_Pwm; + js[Sensor_PaperDetection_Pwm] = param.Sensor_PaperDetection_Pwm; + js[Sensor_Double_double_check_cyc] = param.Sensor_Double_double_check_cyc; + js[Sensor_Double_paper_check_cyc] = param.Sensor_Double_paper_check_cyc; + js[Sensor_Double_double_max] = param.Sensor_Double_double_max; + js[Sensor_Double_single_max] = param.Sensor_Double_single_max; + return js; +} + +SensorConfig::SensorConfig_Param SensorConfig::to_param(json js) +{ + SensorConfig::SensorConfig_Param param{ + .Sensor_Scan_Pwm = 40, + .Sensor_ConverOpen_Pwm = 40, + .Sensor_Screw_1_Pwm = 40, + .Sensor_Screw_2_Pwm = 40, + .Sensor_PaperOut_Pwm = 40, + .Sensor_PaperDetection_Pwm = 40, + .Sensor_Double_double_check_cyc = 4, + .Sensor_Double_paper_check_cyc = 8, + .Sensor_Double_double_max = 0x1c, + .Sensor_Double_single_max = 0x70, + }; + if(js[Sensor_Scan_Pwm].is_object() && js[Sensor_Scan_Pwm].is_number_integer()) + param.Sensor_Scan_Pwm = js[Sensor_Scan_Pwm]; + if(js[Sensor_Screw_1_Pwm].is_object() && js[Sensor_Screw_1_Pwm].is_number_integer()) + param.Sensor_Screw_1_Pwm = js[Sensor_Screw_1_Pwm]; + if(js[Sensor_Screw_2_Pwm].is_object() && js[Sensor_Screw_2_Pwm].is_number_integer()) + param.Sensor_Screw_2_Pwm = js[Sensor_Screw_2_Pwm]; + if(js[Sensor_ConverOpen_Pwm].is_object() && js[Sensor_ConverOpen_Pwm].is_number_integer()) + param.Sensor_ConverOpen_Pwm = js[Sensor_ConverOpen_Pwm]; + if(js[Sensor_PaperOut_Pwm].is_object() && js[Sensor_PaperOut_Pwm].is_number_integer()) + param.Sensor_PaperOut_Pwm = js[Sensor_PaperOut_Pwm]; + if(js[Sensor_PaperDetection_Pwm].is_object() && js[Sensor_PaperDetection_Pwm].is_number_integer()) + param.Sensor_PaperDetection_Pwm = js[Sensor_PaperDetection_Pwm]; + if(js[Sensor_Double_double_check_cyc].is_object() && js[Sensor_Double_double_check_cyc].is_number_integer()) + param.Sensor_Double_double_check_cyc = js[Sensor_Double_double_check_cyc]; + if(js[Sensor_Double_paper_check_cyc].is_object() && js[Sensor_Double_paper_check_cyc].is_number_integer()) + param.Sensor_Double_paper_check_cyc = js[Sensor_Double_paper_check_cyc]; + if(js[Sensor_Double_double_max].is_object() && js[Sensor_Double_double_max].is_number_integer()) + param.Sensor_Double_double_max = js[Sensor_Double_double_max]; + if(js[Sensor_Double_single_max].is_object() && js[Sensor_Double_single_max].is_number_integer()) + param.Sensor_Double_single_max = js[Sensor_Double_single_max]; + return param; +} diff --git a/motorboard/SensorConfig.h b/motorboard/SensorConfig.h new file mode 100644 index 0000000..afa371b --- /dev/null +++ b/motorboard/SensorConfig.h @@ -0,0 +1,59 @@ +#pragma once +#include "commondef.h" +#include +#include "json.hpp" + +using json = nlohmann::json; + +class SensorConfig +{ +private: + const std::string Path = "/usr/local/huago/sensorconfig.json"; + const std::string Sensor_Scan_Pwm = "Sensor_Scan_Pwm"; + const std::string Sensor_Screw_1_Pwm = "Sensor_Screw_1_Pwm"; + const std::string Sensor_Screw_2_Pwm = "Sensor_Screw_2_Pwm"; + const std::string Sensor_ConverOpen_Pwm = "Sensor_ConverOpen_Pwm"; + const std::string Sensor_PaperOut_Pwm = "Sensor_PaperOut_Pwm"; + const std::string Sensor_PaperDetection_Pwm = "Sensor_PaperDetection_Pwm"; + + const std::string Sensor_Double_double_check_cyc = "Sensor_Double_double_check_cyc"; + const std::string Sensor_Double_paper_check_cyc = "Sensor_Double_paper_check_cyc"; + const std::string Sensor_Double_double_max = "Sensor_Double_double_max"; + const std::string Sensor_Double_single_max = "Sensor_Double_single_max"; + +public: + struct SensorConfig_Param + { + uint32_t Sensor_Scan_Pwm; //扫描传感器 + uint32_t Sensor_ConverOpen_Pwm; //开盖传感器 + uint32_t Sensor_Screw_1_Pwm; //歪斜_1传感器 + uint32_t Sensor_Screw_2_Pwm; //歪斜_2传感器 + uint32_t Sensor_PaperOut_Pwm; //出纸口传感器 + uint32_t Sensor_PaperDetection_Pwm; //有无纸传感器 + uint32_t Sensor_Double_double_check_cyc; //双张检测周期 + uint32_t Sensor_Double_paper_check_cyc; //双张有纸检测周期 + uint32_t Sensor_Double_double_max; //双张检测阈值 + uint32_t Sensor_Double_single_max; //双张有纸检测阈值 + }; + + + + SensorConfig(); + ~SensorConfig(); + SensorConfig::SensorConfig_Param get_param(); + void set_param(SensorConfig::SensorConfig_Param param); + SensorConfig::SensorConfig_Param get_mem_param(); +private: + void initconfigfile(); + void reset_json(); + json to_json(SensorConfig::SensorConfig_Param param); + SensorConfig::SensorConfig_Param to_param(json js); + std::mutex m_lock; + SensorConfig::SensorConfig_Param m_param; +}; + + +extern SensorConfig m_static_sensorconfig; +static SensorConfig& Get_Static_SC(){ + return m_static_sensorconfig; +}; \ No newline at end of file diff --git a/motorboard/aje2vec.cpp b/motorboard/aje2vec.cpp new file mode 100644 index 0000000..a8c20ae --- /dev/null +++ b/motorboard/aje2vec.cpp @@ -0,0 +1,918 @@ +/******************************************************************* + * Copyright (c) 2011 -2021 Anlogic Inc. + * The Software is distributed in source code form and is open to + * re-distribution and modification where applicable +*******************************************************************/ + +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include +#include +#include +#include +#include + +#include "opcode.h" + +#define AJE_DEBUG + +/* jtag instruction macro list */ +#define INS_REFRESH 0x01 +#define INS_SAMPLE 0x05 +#define INS_READ_STATUS 0x20 +#define INS_BYPASS 0xFF + +#define INS_PROG_SPI 0x39 + +extern unsigned int g_hdr_size; +extern unsigned int g_hir_size; +extern unsigned int g_tdr_size; +extern unsigned int g_tir_size; + +extern unsigned char* g_hdr_data; +extern unsigned char* g_hir_data; +extern unsigned char* g_tdr_data; +extern unsigned char* g_tir_data; + +/* some static & global variables */ +static char s_compress = FULL_MODE; /* compress mode */ +static long int s_cfg_start_pos = 0; /* the start cfg position in aje file */ +static int s_done_status = 1; /* done pin status */ +static int s_find_refresh_ins = 0; /* the flag that refresh instrcution has been found or not */ +static int s_cur_level = 0; /* for daisy chain, current level */ +static int s_total_level = 0; /* for daisy chain, total level */ + +FILE* g_aje_file; +char g_aje_crc[3]; +long int g_freq = 0; +unsigned char s_idcode_pub = IDCODE_PUB; +static unsigned int s_cascade = 0; /* cascade flag */ + +/* function declared in decode.c */ +extern unsigned char* Anlogic_BytesDecode(long bytes); +extern unsigned char* Anlogic_NibbleDecode(long bytes); +extern unsigned char* Anlogic_HuffmanDecode(long bytes); +extern unsigned char* Anlogic_LzwDecode(long bytes); + +/* function declared in ajeutil.c */ +extern int Anlogic_GetBit(unsigned char* data, int id); +extern void Anlogic_SetBit(unsigned char* data, int id, int val); +extern char* Anlogic_HexStrToBinStr(char* src_str, int bin_len); + +/* function declared in vec.c */ +extern enum TAP_STATE Anlogic_TapState(unsigned char opcode); +extern const char* Anlogic_TapState2Str(enum TAP_STATE tap_state); +extern void Anlogic_SetEndDRState(enum TAP_STATE end_st); +extern void Anlogic_SetEndIRState(enum TAP_STATE end_st); +extern int Anlogic_TapTransist(enum TAP_STATE state); +extern int Anlogic_ExeSirCommand(unsigned char command, int cur_lvl, int total_lvl); +extern int Anlogic_ExeSdrCommand(unsigned int data_size, int cur_lvl, int total_lvl, + unsigned char* tdi_data, unsigned char* tdo_data); +extern void Anlogic_Init(void); +extern void Anlogic_ProcessRunTestTck(int num); +extern int Anlogic_SendData(unsigned char* tdi_data, unsigned int data_size, int cascade); +extern int Anlogic_SaveData(unsigned char* tdi_data, unsigned int data_size, unsigned char** tdo_data); +extern int Anlogic_ProcessShiftCmd(unsigned int op_code, unsigned int cascade, unsigned int read, unsigned int data_size, + unsigned char* tdi_data, unsigned char* tdo_data, unsigned char* mask); + +/* function forward declaration */ +int Anlogic_ExeSirCommands(unsigned int data_size, unsigned char* tdi_data, unsigned char* tdo_data, unsigned char* mask); +int Anlogic_ExeSDRCommands(unsigned int cascade, unsigned int data_size, + unsigned char* tdi_data, unsigned char* tdo_data, unsigned char* mask); + +long Anlogic_ReadNumber() +{ + long number = 0; + char byte = 0, cnt = 0; + do { + byte = fgetc(g_aje_file); + if (byte == EOF) { break; } + number += (byte & 0x007F) << (7 * cnt); + cnt ++; + } while (byte & 0x0080); + return number; +} + +unsigned long Anlogic_ProcessRuntestCmd() +{ + unsigned long ulTime = 0; + unsigned long num = 0; + char opcode = 0; + // char pre_opcode = 0; + char done = 0; + + if (g_freq == 0) { + g_freq = 80000; + } + + do { + //pre_opcode = opcode; + opcode = fgetc(g_aje_file); + switch (opcode) { + case TCK: + num = Anlogic_ReadNumber(); + if (num > 0x8000) { num -= 0x8000; } + ulTime += num; + ulTime -= 10; + break; + case WAIT: + num = Anlogic_ReadNumber(); + num -= 10; + if (num > 0x8000) { + num -= 0x8000; + num = g_freq * num / 1000; + } else { + num = g_freq * num / 1000000; + } + //if(TCK == pre_opcode){ + // ulTime = 0; + //} + ulTime += num; + break; + case RUNTEST: + break; + default: + done = 1; + break; + } + } while (!done); + + if (opcode == BEGINLINE) { + fseek(g_aje_file, -1, SEEK_CUR); + } + + //ulTime = 1200; + return ulTime; +} + +unsigned char* Anlogic_ProcessData(unsigned int byte_num) { + unsigned int index = 0; + unsigned char* data = NULL; + char mode = '\0'; + + if (s_compress == (char)FULL_MODE) { + data = (unsigned char*)calloc((byte_num+1), sizeof(unsigned char)); + for(index = 0; index < byte_num; ++index) { + data[index] = fgetc(g_aje_file); + } + } else { // compress mode + mode = fgetc(g_aje_file); + if (mode == 0) { // no compress + data = (unsigned char*)calloc((byte_num+1), sizeof(unsigned char)); + for(index = 0; index < byte_num; ++index) { + data[index] = fgetc(g_aje_file); + } + } else if (mode == 1) { // byte compress + data = Anlogic_BytesDecode(byte_num); + } else if (mode == 2) { // nibble compress + data = Anlogic_NibbleDecode(byte_num); + } else if (mode == 3) { // huffman compress + data = Anlogic_HuffmanDecode(byte_num); + } else if (mode == 4) { // LZW compress + data = Anlogic_LzwDecode(byte_num); + } else { + assert(0 && "Error: Unkown compress mode."); + } + } + return data; +} + +void Anlogic_PrintData(unsigned int byte_size, unsigned char* data) { + int byte_id = 0; + unsigned int bit_id = 0; + unsigned char byte = '\0'; + unsigned char flip_byte = '\0'; + + printf( " (" ); + for(byte_id = byte_size-1; byte_id >=0; --byte_id) { + byte = data[byte_id]; + flip_byte = 0x00; + for (bit_id = 0; bit_id < 8; bit_id++) { + flip_byte <<= 1; + if (byte & 0x1) { + flip_byte |= 0x1; + } + byte >>= 1; + } + printf("%02X", flip_byte); + } + printf(") "); +} + +/* Get the SIR Instruction */ +unsigned char Anlogic_ParseSirIns(unsigned int len, unsigned char* tdi_data) { + /* default value : bypass instruction */ + unsigned char sir_ins = INS_BYPASS; + + unsigned int byte_id = 0; + unsigned int bit_id = 0; + unsigned char byte = '\0'; + unsigned char flip_byte = '\0'; + + if (len % 8 != 0) { + return sir_ins; + } + + for(byte_id = 0; byte_id < len/8; ++byte_id) { + byte = tdi_data[byte_id]; + flip_byte = 0x00; + for (bit_id = 0; bit_id < 8; bit_id++) { + flip_byte <<= 1; + if (byte & 0x1) { + flip_byte |= 0x1; + } + byte >>= 1; + } + + if (flip_byte != INS_BYPASS) { + sir_ins = flip_byte; + break; + } + } + + return sir_ins; +} + +/* read the head and trailer bit number in sir instruction */ +int Anlogic_ReadSirInfo(int* header_num, int* trailer_num) { + unsigned int bin_num = 0; + unsigned int flip_byte = 0; + unsigned int bit_id = 0; + + int byte_id = 0; + int byte_num = 0; + + int* tmp_val = trailer_num; + + unsigned char* tdi = NULL; + char byte = '\0'; + + *header_num = 0; + *trailer_num = 0; + + bin_num = Anlogic_ReadNumber(); + byte_num = bin_num / 8; + if (bin_num % 8 != 0) { + byte_num++; + } + + if (fgetc(g_aje_file) != TDI) { + printf("Error Invalid format when executing read sir information!\n"); + fseek(g_aje_file, bin_num-1, SEEK_CUR); + return 0; + } + + tdi = Anlogic_ProcessData(byte_num); + for(byte_id = byte_num-1; byte_id >= 0; --byte_id) { + byte = tdi[byte_id]; + flip_byte = 0x00; + for (bit_id = 0; bit_id < 8; bit_id++) { + flip_byte <<= 1; + if (byte & 0x1) { + flip_byte |= 0x1; + } + byte >>= 1; + } + + if (flip_byte == BYPASS) { + *tmp_val += 1; + } else if (flip_byte != BYPASS) { + tmp_val = header_num; + if(flip_byte == IDCODE_PUB_2) { + s_idcode_pub = IDCODE_PUB_2; + } + } + } + + if (CONTINUE != fgetc(g_aje_file)) { + printf("Error Invalid format when executing read sir information!\n"); + return 0; + } + + return (tmp_val == trailer_num) ? 0 : 1; +} + +int Anlogic_ProcessShiftCommand(char op_code) +{ + int rtn_val = AJE_OK; + int id = 0; + unsigned int bin_num = 0; + unsigned int byte_num = 0; + unsigned char* tdi = NULL; + unsigned char* tdo = NULL; + unsigned char* msk = NULL; + unsigned char ins = 0xFF; + char byte = '\0'; + + bin_num = Anlogic_ReadNumber(); + byte_num = bin_num / 8; + if (bin_num % 8 != 0) { + byte_num++; + } + + while((byte = fgetc(g_aje_file)) != CONTINUE) { + switch (byte) { + case TDI: + tdi = Anlogic_ProcessData(byte_num); + break; + case TDO: + tdo = Anlogic_ProcessData(byte_num); + break; + case MASK: + msk = Anlogic_ProcessData(byte_num); + break; + default: + printf("Error: Invalid format when executing process sir or sdr instruction!\n"); + return AJE_INVALID_COMMAND; + break; + } + } + + /* exe sir or sdr instruction */ + if (op_code == SIR) { + + /* if done=0, 'refresh' must be executed before 'program_spi' */ + if (s_done_status == 0 && s_find_refresh_ins == 0) { + ins = Anlogic_ParseSirIns(bin_num, tdi); + if (ins == INS_REFRESH) { + s_find_refresh_ins = 1; + } else if (ins == INS_PROG_SPI) { +#ifdef AJE_DEBUG + printf("SIR %d TDI (", s_total_level*8); + for (id = 1; id <= s_total_level; ++id) { + if (id == s_cur_level) { + printf("%02X", INS_REFRESH); + } else { + printf("FF"); + } + } + printf(") ;\n"); + printf("SIR %d TDI (", s_total_level*8); + + for (id = 1; id <= s_total_level; ++id) { + printf("FF"); + } + printf(") ;\n"); +#endif + Anlogic_ExeSirCommand(INS_REFRESH, s_cur_level, s_total_level); + Anlogic_ExeSirCommand(INS_BYPASS, s_cur_level, s_total_level); + s_done_status = 1; + } + } + +#ifdef AJE_DEBUG + printf("SIR %d TDI", bin_num); + Anlogic_PrintData(byte_num, tdi); + if (tdo != NULL) { + printf("TDO"); + Anlogic_PrintData(byte_num, tdo); + } + if (msk != NULL) { + printf("MASK"); + Anlogic_PrintData(byte_num, msk); + } + printf(";\n"); +#endif + + rtn_val = Anlogic_ExeSirCommands(bin_num, tdi, tdo, msk); + } else { + +#ifdef AJE_DEBUG + printf("SDR %d TDI", bin_num); + Anlogic_PrintData(byte_num, tdi); + if (tdo != NULL) { + printf("TDO"); + Anlogic_PrintData(byte_num, tdo); + } + if (msk != NULL) { + printf("MASK"); + Anlogic_PrintData(byte_num, msk); + } + printf(";\n"); +#endif + + rtn_val = Anlogic_ExeSDRCommands(s_cascade, bin_num, tdi, tdo, msk); + } + + //free tdi tdo msk + if (tdi != NULL) { free(tdi); tdi = NULL; } + if (tdo != NULL) { free(tdo); tdo = NULL; } + if (msk != NULL) { free(msk); msk = NULL; } + + return rtn_val; +} + +int Anlogic_ProcessBypassCommand(char op_code) { + unsigned int bin_num = 0; + unsigned int byte_num = 0; + unsigned int index = 0; + + unsigned char* tdi = NULL; + char byte = '\0'; + + char* op_code_str = NULL; + + bin_num = Anlogic_ReadNumber(); + if (bin_num > 0) { + byte_num = bin_num / 8; + if (bin_num % 8 != 0) { + byte_num++; + } + byte = fgetc(g_aje_file); + if (byte == TDI) { + tdi = (unsigned char*)calloc((byte_num+1), sizeof(unsigned char)); + for(index = 0; index < byte_num; ++index) { + tdi[index] = fgetc(g_aje_file); + } + } + } + + switch (op_code) + { + case TIR: op_code_str = "TIR"; g_tir_size = bin_num; g_tir_data = tdi; break; + case TDR: op_code_str = "TDR"; g_tdr_size = bin_num; g_tdr_data = tdi; break; + case HIR: op_code_str = "HIR"; g_hir_size = bin_num; g_hir_data = tdi; break; + case HDR: op_code_str = "HDR"; g_hdr_size = bin_num; g_hdr_data = tdi; break; + default: + printf("Error: invalid Head/Trailer format, unkown opcode.\n\n"); + return AJE_INVALID_COMMAND; + } + +#ifdef AJE_DEBUG + printf("%s %d", op_code_str, bin_num); + if ( bin_num > 0) { + printf(" TDI "); + Anlogic_PrintData(byte_num, tdi); + } + printf(" ;\n"); +#endif + + if (bin_num > 0) { // Skip CONTINUE command + fgetc(g_aje_file); + } + return AJE_OK; +} + +int Anlogic_ExeSirCommands(unsigned int data_size, unsigned char* tdi_data, unsigned char* tdo_data, + unsigned char* mask) { + unsigned int rtn_val = AJE_OK; + unsigned int op_code = SIR; + unsigned int cascade = 0; // no casecade + unsigned int read = 0; // send data only + rtn_val = Anlogic_ProcessShiftCmd(op_code, cascade, read, data_size, tdi_data, tdo_data, mask); + return rtn_val; +} + +int Anlogic_ExeSDRCommands(unsigned int cascade, unsigned int data_size, + unsigned char* tdi_data, unsigned char* tdo_data, unsigned char* mask) { + unsigned int rtn_val = AJE_OK; + unsigned int op_code = SDR; + unsigned int read = 0; // send data only + rtn_val = Anlogic_ProcessShiftCmd(op_code, cascade, read, data_size, tdi_data, tdo_data, mask); + return rtn_val; +} + +/* + * read the aje header information, + * include crc, version, compress mode, maximum memory size and vendor +*/ +int Anlogic_ReadAjeHeader() +{ + char byte; + char buffer[100]; + int i; + printf("Anlogic_ReadAjeHeader start.\n"); + // crc bytes + if (fgetc(g_aje_file) != FILECRC) { + return AJE_FILE_INVALID; + } + + if (fgets(g_aje_crc, 3, g_aje_file) == NULL) { + return AJE_FILE_INVALID; + } + else { + printf("g_aje_crc[0] = 0x%02x, g_aje_crc[1] = 0x%02x, g_aje_crc[2] = 0x%02x,\n", + g_aje_crc[0],g_aje_crc[1],g_aje_crc[2]); + } + + // version + if (fgets(buffer, 9, g_aje_file) == NULL) { + return AJE_FILE_INVALID; + } + else + { + for(int i=0;i<9;i++) + printf("buffer[%d] = 0x%02x ",i,buffer[i]); + printf("\n"); + } + + // compress or full + byte = fgetc(g_aje_file); + if (byte != (char)COMP_MODE && byte != (char)FULL_MODE) { + return AJE_FILE_INVALID; + } + else + printf("byte = 0x%02x ",byte); + s_compress = byte; + + // maximum memory size + if (MEM != fgetc(g_aje_file)) { + return AJE_FILE_INVALID; + } + Anlogic_ReadNumber(); + + // Vender + if (VENDOR != fgetc(g_aje_file )) { + return AJE_FILE_INVALID; + } + if (ANLOGIC != fgetc(g_aje_file)) {; + return AJE_FILE_INVALID; + } + + s_cfg_start_pos = ftell(g_aje_file); + + printf("Anlogic_ReadAjeHeader end.\n"); + + return AJE_OK; +} + +/* read the chip id before processing data, need to get the chain information */ +int Anlogic_ReadChipIdcode(void) +{ + int rtn_val = AJE_OK; + int finish = 0; + + /* get from HDR/TDR Command */ + int hdr_num = 0; + int tdr_num = 0; + + /* get from SIR Command */ + int trailer_num = 0; + int header_num = 0; + + long line_length = 0; + char op_code = 0x00; + + printf("Anlogic_ReadChipIdcode start.\n"); + while((finish == 0) && (fgetc(g_aje_file)) == BEGINLINE) { + line_length = Anlogic_ReadNumber()/8; + printf("Anlogic_ReadNumber()/8 = %d.\n",line_length); + op_code = fgetc(g_aje_file); + printf("op_code = 0x%02x.\n",op_code); + switch (op_code) { + case HDR: + printf("Acase HDR.\n"); + hdr_num = Anlogic_ReadNumber(); + if (hdr_num != 0) { + while (CONTINUE != fgetc(g_aje_file)); + } + break; + case TDR: + printf("Acase TDR.\n"); + tdr_num = Anlogic_ReadNumber(); + if (tdr_num != 0) { + while (CONTINUE != fgetc(g_aje_file)); + } + break; + case SIR: + printf("Acase SIR.\n"); + finish = Anlogic_ReadSirInfo(&header_num, &trailer_num); + break; + default: + printf("Acase default.\n"); + fseek(g_aje_file, line_length-1, SEEK_CUR); + break; + } + } + + if (finish == 0) { + return AJE_WARNING; + } + + s_cur_level = tdr_num+trailer_num+1; + s_total_level = tdr_num+trailer_num+1+header_num+hdr_num; + + rtn_val = Anlogic_ExeSirCommand(s_idcode_pub, s_cur_level, s_total_level); + if (rtn_val != AJE_OK) { + return rtn_val; + } + + unsigned char* tdo_data = (unsigned char*)malloc(5*sizeof(unsigned char)); + tdo_data[4] = '\0'; + rtn_val = Anlogic_ExeSdrCommand(32, s_cur_level, s_total_level, NULL, tdo_data); + if (rtn_val == AJE_OK) { /* print 32 bit chip id in terminal */ + if (tdo_data[0] == 0 && tdo_data[1] == 0 && + tdo_data[2] == 0 && tdo_data[3] == 0) { + printf("Error: Chip validation failed, please check the connection.\n"); + rtn_val = AJE_ERROR; + } else { + printf("\n Chip Id : "); + Anlogic_PrintData(4, tdo_data); + printf("\n"); + } + } + free(tdo_data); + tdo_data = NULL; + printf("Anlogic_ReadChipIdcode end.\n"); + return rtn_val; +} + +/* Loading Read chip io status instrcution and compare ref_io_status */ +int Anlogic_LoadingReadChipIOStatusInstruction(unsigned int bit_size, unsigned char* ref_io_status) { + int rtn_val = AJE_OK; + int bit = 0; + unsigned int io_index = 0; + unsigned int byte = (bit_size+7)/8; + + rtn_val = Anlogic_ExeSirCommand(SAMPLE, s_cur_level, s_total_level); + if (rtn_val != AJE_OK) { + return rtn_val; + } + + unsigned char* tdo_data = (unsigned char*)malloc((byte+1)*sizeof(unsigned char)); + tdo_data[byte] = '\0'; + rtn_val = Anlogic_ExeSdrCommand(bit_size, s_cur_level, s_total_level, NULL, tdo_data); + if (rtn_val == AJE_OK) { + printf("\nIO Status: \n"); + printf("Bs order\t\tRef\t\tRead\t\tVerify\n"); + + for (io_index = 0; io_index < bit_size; ++io_index) { + bit = Anlogic_GetBit(tdo_data, io_index); + printf("%8d\t\t%c\t\t%d\t\t", io_index, ref_io_status[io_index], bit); + if (ref_io_status[io_index] - '0' == bit) { + printf("true\n"); + } else { + printf("false\n"); + } + } + } + + free(tdo_data); + tdo_data = NULL; + return rtn_val; +} + +int Anlogic_ReadChipIOStatus(char* io_state_file) { + int rtn_val = AJE_OK; + FILE* io_stat_stream = NULL; + char line[LINE_MAX_SIZE]; + char buf[10]; + int sscanf_num = 0; + char sdr_tdi_str[DATA_MAX_SIZE]; + char sdr_tdo_str[DATA_MAX_SIZE]; + char sdr_mask_str[DATA_MAX_SIZE]; + + char* sdr_tdo_bin_str = NULL; + char* sdr_mask_bin_str = NULL; + unsigned char* ref_io_status = NULL; + + int sir_num = 0; + int sir_val = 0; + int sdr_num = 0; + int str_idx = 0; + + int find_sample_ins = 0; /* sample instruction flag */ + + char* p = strstr(io_state_file, ".svf"); + if (p == NULL || strcmp(p, ".svf") != 0) { + printf("Error: %s is not a svf file\n", io_state_file); + return AJE_FILE_INVALID; + } + + if ((io_stat_stream = fopen(io_state_file, "r")) == NULL) { + printf("Error: cannot read the svf file %s\n", io_state_file); + return AJE_FILE_OPEN_FAIL; + } + + // Parse svf file + while (!feof(io_stat_stream)) { + fgets(line, LINE_MAX_SIZE, io_stat_stream); + + // Find "Sample" instruction, E.G. SIR 8 TDI (05) + if (find_sample_ins == 0) { + sscanf_num = sscanf(line, "SIR %d TDI (%d)", &sir_num, &sir_val); + if (sscanf_num != 2) { continue; } + if (sir_num != 8 || sir_val != INS_SAMPLE) { + continue; + } + find_sample_ins = 1; + } else { + if (strncasecmp(line, "SDR", 3) != 0) { + continue; + } + // sample instruction + // E.G. SDR 426 TDI (3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) + // TDO (3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBAFBFEAAFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) + // MASK (0000000000000000000000000000000000000000000000AAAAAAAA00000000000000000000000000000000000000000000000000000); + sscanf_num = sscanf(line, "SDR %d TDI (%[^)]) TDO (%[^)]) MASK (%[^)])", &sdr_num, sdr_tdi_str, sdr_tdo_str, sdr_mask_str); + if (sscanf_num == 2) { // for line feeds + fgets(line, LINE_MAX_SIZE, io_stat_stream); + sscanf_num = sscanf(line, "%s (%[^)])", buf, sdr_tdo_str); + assert(strcasecmp(buf, "TDO") == 0); + if (sscanf_num == 2) { + fgets(line, LINE_MAX_SIZE, io_stat_stream); + sscanf_num = sscanf(line, "%s (%[^ )])", buf, sdr_mask_str); + assert(strcasecmp(buf, "MASK") == 0); + } + } + + if (sdr_num == 0 || sdr_tdi_str == NULL || sdr_tdo_str == NULL || sdr_mask_str == NULL) { + printf("Error: Invalid SDR string %s", line); + return AJE_FILE_INVALID; + } + + ref_io_status = (unsigned char*)malloc((sdr_num+1)*sizeof(unsigned char)); + memset(ref_io_status, 'x', sdr_num); + ref_io_status[sdr_num] = 0x00; + + sdr_tdo_bin_str = Anlogic_HexStrToBinStr(sdr_tdo_str, sdr_num); + sdr_mask_bin_str = Anlogic_HexStrToBinStr(sdr_mask_str, sdr_num); + + for(str_idx = 0; str_idx < sdr_num; ++str_idx) { + if (sdr_mask_bin_str[str_idx] == '1') { // the bit need verify + ref_io_status[sdr_num-1-str_idx] = sdr_tdo_bin_str[str_idx]; + } + } + } // end read sdr instruction + } // end of read file + + if (ref_io_status == NULL) { + printf("Error: Invalid svf file %s, cannot find the sample data", io_state_file); + return AJE_FILE_INVALID; + } + + if (sdr_tdo_bin_str != NULL) { free(sdr_tdo_bin_str); sdr_tdo_bin_str = NULL; } + if (sdr_mask_bin_str != NULL) { free(sdr_mask_bin_str); sdr_mask_bin_str = NULL; } + + rtn_val = Anlogic_LoadingReadChipIOStatusInstruction(sdr_num, ref_io_status); + + return rtn_val; +} + +int Anlogic_CheckDonePinStatus() { + int rtn_val = AJE_OK; + unsigned char* tdo_data = NULL; + + s_done_status = 1; + rtn_val = Anlogic_ExeSirCommand(INS_READ_STATUS, s_cur_level, s_total_level); + + tdo_data = (unsigned char*)malloc(5*sizeof(unsigned char)); + tdo_data[4] = '\0'; + rtn_val = Anlogic_ExeSdrCommand(32, s_cur_level, s_total_level, NULL, tdo_data); + if (rtn_val == AJE_OK) { + s_done_status = Anlogic_GetBit(tdo_data, 26); + } + + free(tdo_data); + tdo_data = NULL; + return rtn_val; +} + +/* core function, parse aje file and process data */ +int Anlogic_ProcessCmd() { + int rtn_val = AJE_OK; + int tck_num = 0; /* for runtest num tck command */ + int loop_num = 0; /* for loop command */ + long cmd_length = 0; + long cur_pos = 0; + long freq = 0; + char op_code = '\0'; + + enum TAP_STATE tap_state = TAP_RESET; + + fseek(g_aje_file, s_cfg_start_pos, SEEK_SET); /* restore to the start position of configuration */ + + while((fgetc(g_aje_file)) == BEGINLINE) { + cmd_length = Anlogic_ReadNumber()/8; + + op_code = fgetc(g_aje_file); + switch (op_code) { + case STATE: + tap_state = Anlogic_TapState(fgetc(g_aje_file)); + Anlogic_TapTransist(tap_state); + if (cmd_length == 2) { + printf("STATE %s;\n", Anlogic_TapState2Str(tap_state)); + } + if (cmd_length >= 2 && tap_state == TAP_IDLE) { + tck_num = Anlogic_ProcessRuntestCmd(); + if (tck_num > 0) { + Anlogic_ProcessRunTestTck(tck_num); + } + } + break; + case FREQUENCY: + freq = Anlogic_ReadNumber(); + if (g_freq == 0 || g_freq > freq) { + g_freq = freq; +#ifdef AJE_DEBUG + printf("FREQUENCY %.2E HZ;\n", (float)g_freq); +#endif + } + break; + case SIR: + case SDR: + rtn_val = Anlogic_ProcessShiftCommand(op_code); + break; + case LOOP: + loop_num = Anlogic_ReadNumber(); + cur_pos = ftell(g_aje_file); + break; + case ENDLOOP: + if (loop_num > 1) { + fseek(g_aje_file, cur_pos, SEEK_SET); + loop_num--; + } + break; + case TDR: + case TIR: + case HDR: + case HIR: + rtn_val = Anlogic_ProcessBypassCommand(op_code); + break; + case ENDIR: + tap_state = Anlogic_TapState(fgetc(g_aje_file)); + Anlogic_SetEndIRState(tap_state); + break; + case ENDDR: + tap_state = Anlogic_TapState(fgetc(g_aje_file)); + Anlogic_SetEndDRState(tap_state); + break; + case SETFLOW: + if (fgetc(g_aje_file) == CASCADE) { + s_cascade = 1; + } + break; + case RESETFLOW: + if (fgetc(g_aje_file) == CASCADE) { + s_cascade = 0; + } + break; + case TRST: + if (fgetc(g_aje_file) == ON) { + printf("TRST ON;\n"); + } else { + printf("TRST OFF;\n"); + } + break; + case RUNTEST: + { + fseek(g_aje_file, cmd_length-1, SEEK_CUR); + } + break; + default: + printf("Error: invalid file format, unkown opcode.\n\n"); + return AJE_INVALID_COMMAND; + } + + if (rtn_val != AJE_OK) { + return rtn_val; + } + } + return rtn_val; +} + + +int Anlogic_AjeToVec(const char* aje_file) { + int rtn_code = AJE_OK; + char* io_state_file = NULL; /* input svf file, use to read io status */ + + if ((g_aje_file = fopen(aje_file, "rb")) == NULL) { + return AJE_FILE_OPEN_FAIL; + } + else + printf("fopen %s sucess,file * = %p.\n",aje_file,g_aje_file); + + /* read header content */ + rtn_code = Anlogic_ReadAjeHeader(); + if (rtn_code != AJE_OK) { + return rtn_code; + } + + /* execute "state reset" first, 2019/12/20 */ + Anlogic_Init(); + + /* read chip id code */ + rtn_code = Anlogic_ReadChipIdcode(); + if (rtn_code != AJE_OK) { + return rtn_code; + } + + /* read io status */ + if (io_state_file != NULL) { + rtn_code = Anlogic_ReadChipIOStatus(io_state_file); + if (rtn_code != AJE_OK) { + return rtn_code; + } + } + + /* check done pin status */ + Anlogic_CheckDonePinStatus(); + + /* core process function */ + rtn_code = Anlogic_ProcessCmd(); + + fclose(g_aje_file); + return rtn_code; +} diff --git a/motorboard/ajeutil.cpp b/motorboard/ajeutil.cpp new file mode 100644 index 0000000..0cb7cc3 --- /dev/null +++ b/motorboard/ajeutil.cpp @@ -0,0 +1,101 @@ +/******************************************************************* +* Copyright (c) 2011 -2021 Anlogic Inc. + * The Software is distributed in source code form and is open to + * re-distribution and modification where applicable +*******************************************************************/ + +/******************************************************************* + Filename : ajeutil.c + Description: utility source file + Log: initial version, December 2019 +*******************************************************************/ + +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include +#include + +int Anlogic_GetBit(unsigned char* data, int id) { + return (data[id/8] & (1 << (7-id%8))) ? 1 : 0; +} + +void Anlogic_SetBit(unsigned char* data, int id, int val) { + unsigned char mask = 1 << (7-id%8); + if (val) { + data[id/8] |= mask; + } else { + data[id/8] &= ~mask; + } +} + +/* reverse char data e.g. 8'b10001101 -> 8'b10110001 */ +unsigned char Anlogic_ReverseChar(unsigned char byte) { + unsigned int bit_id = 0; + unsigned char flip_byte = 0x00; + for (bit_id = 0; bit_id < 8; ++bit_id) { + flip_byte <<= 1; + if (byte & 0x1) { + flip_byte |= 0x1; + } + byte >>= 1; + } + return flip_byte; +} + +/* tranfer hex to bin data, e.g. char('A') -> char[4] = {'1', '0', '1', '0' } */ +void Anlogic_HexTobin(char hex, char* char_s) { + switch(hex) { + case '0': strcpy(char_s ,"0000"); break; + case '1': strcpy(char_s ,"0001"); break; + case '2': strcpy(char_s ,"0010"); break; + case '3': strcpy(char_s ,"0011"); break; + case '4': strcpy(char_s ,"0100"); break; + case '5': strcpy(char_s ,"0101"); break; + case '6': strcpy(char_s ,"0110"); break; + case '7': strcpy(char_s ,"0111"); break; + case '8': strcpy(char_s ,"1000"); break; + case '9': strcpy(char_s ,"1001"); break; + case 'a': + case 'A': strcpy(char_s ,"1010"); break; + case 'b': + case 'B': strcpy(char_s ,"1011"); break; + case 'c': + case 'C': strcpy(char_s ,"1100"); break; + case 'd': + case 'D': strcpy(char_s ,"1101"); break; + case 'e': + case 'E': strcpy(char_s ,"1110"); break; + case 'f': + case 'F': strcpy(char_s ,"1111"); break; + default: + printf("Error: HexToChar Invalid Hex value %c", hex); + } +} + +char* Anlogic_HexStrToBinStr(char* src_str, int bin_len) { + char* bin_value = NULL; + int hex_idx = 0; + int char_idx = 0; + char char_s[5] = { 0 }; + int hex_size = strlen(src_str); + if (hex_size*4 < bin_len) { + return NULL; + } + bin_value = (char*)malloc((bin_len+1)*sizeof(char)); + bin_value[bin_len] = 0x00; + + for(hex_idx=hex_size-1; hex_idx>=0; --hex_idx) { + char c = src_str[hex_idx]; + Anlogic_HexTobin(c, char_s); + for (char_idx = 0; char_idx<4; ++char_idx) { + bin_value[--bin_len] = char_s[3-char_idx]; + if (bin_len == 0) { + return bin_value; + } + } // end char_idx + } // end hex_idx + return bin_value; +} + diff --git a/motorboard/decodel.cpp b/motorboard/decodel.cpp new file mode 100644 index 0000000..c93a6d0 --- /dev/null +++ b/motorboard/decodel.cpp @@ -0,0 +1,155 @@ +/******************************************************************* +* Copyright (c) 2011 -2021 Anlogic Inc. + * The Software is distributed in source code form and is open to + * re-distribution and modification where applicable +*******************************************************************/ + +/*********************************************************************** +Filename: decode.c +Description: decode the data from aje file +Log: initial version, July 2019 + ***********************************************************************/ + +#include +#include +#include + +extern FILE* g_aje_file; + +/* Function delcared in lzw_lib.c */ +extern int lzw_decompress (void (*dst)(int), int (*src)(void)); + +unsigned char* g_pWriteBuffer = NULL; +long int g_iWriteCount = 0; + +void Anlogic_WriteBufferByte(int byte) +{ + g_pWriteBuffer[g_iWriteCount++] = (unsigned char)byte; +} + +int Anlogic_ReadAjeByte(void) +{ + return fgetc(g_aje_file); +} + +long Anlogic_NumberDecode(void) { + long number = 0; + char byte = '\0'; + unsigned int count = 0; + do { + byte = fgetc(g_aje_file); + number += (byte & 0x7F) << (7 * count++); + } while (byte & 0x80); + return number; +} + +unsigned char* Anlogic_BytesDecode(long bytes) { + long int i = 0; + long int key_count = 0; + unsigned char byte = 0, key = 0; + unsigned char* rtn_val = NULL; + rtn_val = (unsigned char*)malloc((bytes+1)*sizeof(unsigned char)); + + key = fgetc(g_aje_file); + + for (i = 0; i < bytes; i++) { + if (key_count <= 0) { + byte = fgetc(g_aje_file); + rtn_val[i] = byte; + if (byte == key) { + key_count = Anlogic_NumberDecode(); // The number of key bytes + } + } else { + key_count--; // Use up the key chain first + rtn_val[i] = key; + } + } + return rtn_val; +} + +unsigned char* Anlogic_NibbleDecode(long bytes) { + int i = 0, j = 0, byte_time = 0; + long int num_keys = 0, key_bytes, key_times; + unsigned char *buffer = 0; + unsigned char* rtn_val; + rtn_val = (unsigned char*)malloc((bytes+1)*sizeof(unsigned char)); + + num_keys = Anlogic_NumberDecode(); + key_bytes = (num_keys + 1) / 2; + key_times = (bytes * 2) / num_keys; + buffer = (unsigned char*)calloc(key_bytes + 1 , sizeof(unsigned char)); + if (!buffer) { + assert(0 && "nibble decode: calloc fail"); + } + + for (i = 0; i < key_bytes; i++ ) + buffer[i] = fgetc(g_aje_file); + + if (num_keys % 2 == 0) { + for ( i = 0; i < key_times; i++ ) { + for ( j = 0; j < key_bytes; j++ ) { + rtn_val[j+i*key_bytes] = buffer[j]; + } + } + } else { + assert(key_times % 2 == 0); + buffer = (unsigned char*)realloc(buffer, key_bytes*2*sizeof(unsigned char)); + if (!buffer) { + assert(0 && "nibble decode: realloc fail"); + } + //buffer[key_bytes-2 : 0] keep no change + for(i = key_bytes-1; i < key_bytes*2-1; ++i) { + if (i == key_bytes-1) + buffer[i] = (buffer[i] & 0xF0) + (buffer[0] >> 4); + else + buffer[i] = ((buffer[i-key_bytes] << 4) & 0xF0) + + (buffer[i-key_bytes+1] >> 4); + } + byte_time = key_times / 2; + for(i = 0; i < byte_time; ++i) { + for(j = 0; j < (key_bytes*2-1); ++j) { + rtn_val[j+i*(key_bytes*2-1)] = buffer[j]; + } + } + } + return rtn_val; +} + +unsigned char* Anlogic_HuffmanDecode(long bytes) { + int i = 0, j = 0, m = 0, bits = 8; + unsigned char cur_char = 0, key = 0, byte = 0; + unsigned char* rtn_val; + rtn_val = (unsigned char*)malloc((bytes+1)*sizeof(unsigned char)); + + key = fgetc(g_aje_file); + + for ( i = 0; i < bytes; i++ ) { + byte = 0x00; + if ( bits > 7 ) { + cur_char = fgetc(g_aje_file); + bits = 0; + } + if ( ( cur_char << bits++ ) & 0x80 ) { + m = 8; + for (j = 0; j < m; j++) { + if (bits > 7) { + cur_char = fgetc(g_aje_file); + bits = 0; + } + byte |= ( ( cur_char << bits++ ) & 0x80 ) >> j; + } + } else { + byte = key; + m = 0; + } + rtn_val[i] = byte; + } + return rtn_val; +} + +unsigned char* Anlogic_LzwDecode(long bytes) { + g_pWriteBuffer = (unsigned char*)malloc((bytes+1)*sizeof(unsigned char)); + g_iWriteCount = 0; + lzw_decompress(Anlogic_WriteBufferByte, Anlogic_ReadAjeByte); + return g_pWriteBuffer; +} diff --git a/motorboard/jtagupdata.cpp b/motorboard/jtagupdata.cpp new file mode 100644 index 0000000..a65a07d --- /dev/null +++ b/motorboard/jtagupdata.cpp @@ -0,0 +1,26 @@ +#include "jtagupdata.h" +#include "aje2vec.cpp" +JtagUp::JtagUp(std::string file):filepath(file){ + m_state = 0; +} +JtagUp::~JtagUp(){ + if(is_uping()) + m_fu.get(); +} +void JtagUp::startup(){ + if(is_uping()) + return; + m_state = 0; + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + m_fu = std::async(std::launch::async,&JtagUp::upfc,this); +} +bool JtagUp::is_uping() +{ + return m_fu.wait_for(std::chrono::milliseconds(0)) == std::future_status::timeout; +} +int JtagUp::getresult(){ + return m_state; +} +void JtagUp::upfc(){ + m_state = Anlogic_AjeToVec(filepath.c_str()); +} \ No newline at end of file diff --git a/motorboard/jtagupdata.h b/motorboard/jtagupdata.h new file mode 100644 index 0000000..aec9287 --- /dev/null +++ b/motorboard/jtagupdata.h @@ -0,0 +1,22 @@ +#pragma once +#include +#include +#include +#include "Jtag.h" +#include "opcode.h" +#include +#include + +class JtagUp{ +public: + JtagUp(std::string file); + ~JtagUp(); + void startup(); + bool is_uping(); + int getresult(); +private: + void upfc(); + volatile int m_state; + std::future m_fu; + std::string filepath; +}; \ No newline at end of file diff --git a/motorboard/lzw_lib.cpp b/motorboard/lzw_lib.cpp new file mode 100644 index 0000000..cf3701a --- /dev/null +++ b/motorboard/lzw_lib.cpp @@ -0,0 +1,353 @@ +//////////////////////////////////////////////////////////////////////////// +// **** LZW-AB **** // +// Adjusted Binary LZW Compressor/Decompressor // +// Copyright (c) 2016 David Bryant // +// All Rights Reserved // +// Distributed under the BSD Software License (see license.txt) // +//////////////////////////////////////////////////////////////////////////// + +//#define KERNEL_MODE +#ifdef KERNEL_MODE +#include +#include +#include +#include +#else +#include +#include +#include +#endif + + +/* This library implements the LZW general-purpose data compression algorithm. + * The algorithm was originally described as a hardware implementation by + * Terry Welsh here: + * + * Welch, T.A. “A Technique for High-Performance Data Compression.” + * IEEE Computer 17,6 (June 1984), pp. 8-19. + * + * Since then there have been enumerable refinements and variations on the + * basic technique, and this implementation is no different. The target of + * the present implementation is embedded systems, and so emphasis was placed + * on simplicity, fast execution, and minimal RAM usage. + * + * The symbols are stored in adjusted binary, which provides considerably + * better compression performance with virtually no speed penalty compared to + * the fixed sizes normally used. To ensure good performance on data with + * varying characteristics (like executable images) the encoder resets as + * soon as the dictionary is full. Also, worst-case performance is limited + * to about 8% inflation by catching poor performance and forcing an early + * reset before longer symbols are sent. + * + * The maximum symbol size is configurable on the encode side (from 9 bits + * to 12 bits) and determines the RAM footprint required by both sides and, + * to a large extent, the compression performance. This information is + * communicated to the decoder in the first stream byte so that it can + * allocate accordingly. The RAM requirements are as follows: + * + * maximum encoder RAM decoder RAM + * symbol size requirement requirement + * ----------------------------------------- + * 9-bit 1792 bytes 1024 bytes + * 10-bit 4352 bytes 3072 bytes + * 11-bit 9472 bytes 7168 bytes + * 12-bit 19712 bytes 15360 bytes + * + * This implementation uses malloc(), but obviously an embedded version could + * use static arrays instead if desired (assuming that the maxbits was + * controlled outside). + */ + +#define NULL_CODE -1 // indicates a NULL prefix +#define CLEAR_CODE 256 // code to flush dictionary and restart decoder +#define FIRST_STRING 257 // code of first dictionary string + +/* This macro writes the adjusted-binary symbol "code" given the maximum + * symbol "maxcode". A macro is used here just to avoid the duplication in + * the lzw_compress() function. The idea is that if "maxcode" is not one + * less than a power of two (which it rarely will be) then this code can + * often send fewer bits that would be required with a fixed-sized code. + * + * For example, the first code we send will have a "maxcode" of 257, so + * every "code" would normally consume 9 bits. But with adjusted binary we + * can actually represent any code from 0 to 253 with just 8 bits -- only + * the 4 codes from 254 to 257 take 9 bits. + */ + +#define WRITE_CODE(code,maxcode) do { \ + int code_bits = (maxcode) < 1024 ? \ + ((maxcode) < 512 ? 8 : 9) : \ + ((maxcode) < 2048 ? 10 : 11); \ + int extras = (1 << (code_bits + 1)) - (maxcode) - 1; \ + if ((code) < extras) { \ + shifter |= ((long)(code) << bits); \ + bits += code_bits; \ + } \ + else { \ + shifter |= ((long)(((code) + extras) >> 1) << bits); \ + bits += code_bits; \ + shifter |= ((long)(((code) + extras) & 1) << bits++); \ + } \ + do { (*dst)(shifter); shifter >>= 8; output_bytes++; \ + } while ((bits -= 8) >= 8); \ +} while (0) + +/* LZW compression function. Bytes (8-bit) are read and written through callbacks and the + * "maxbits" parameter specifies the maximum symbol size (9-12), which in turn determines + * the RAM requirement and, to a large extent, the level of compression achievable. A return + * value of EOF from the "src" callback terminates the compression process. A non-zero return + * value indicates one of the two possible errors -- bad "maxbits" param or failed malloc(). + */ + +int lzw_compress (void (*dst)(int), int (*src)(void), int maxbits) +{ + int next = FIRST_STRING, prefix = NULL_CODE, bits = 0, total_codes, c; + unsigned long input_bytes = 0, output_bytes = 0; + short *first_references, *next_references; + unsigned char *terminators; + unsigned long shifter = 0; + + if (maxbits < 9 || maxbits > 12) // check for valid "maxbits" setting + return 1; + + // based on the "maxbits" parameter, compute total codes and allocate dictionary storage + + total_codes = 1 << maxbits; +#ifdef KERNEL_MODE + first_references = ( short int * ) kmalloc (total_codes * sizeof (first_references [0])); + next_references = ( short int * ) kmalloc ((total_codes - 256) * sizeof (next_references [0])); + terminators = ( unsigned char * ) kmalloc ((total_codes - 256) * sizeof (terminators [0])); +#else + first_references = ( short int * ) malloc (total_codes * sizeof (first_references [0])); + next_references = ( short int * ) malloc ((total_codes - 256) * sizeof (next_references [0])); + terminators = ( unsigned char * ) malloc ((total_codes - 256) * sizeof (terminators [0])); +#endif + + if (!first_references || !next_references || !terminators) + return 1; // failed malloc() + + // clear the dictionary + + memset (first_references, 0, total_codes * sizeof (first_references [0])); + memset (next_references, 0, (total_codes - 256) * sizeof (next_references [0])); + memset (terminators, 0, (total_codes - 256) * sizeof (terminators [0])); + + (*dst)(maxbits - 9); // first byte in output stream indicates the maximum symbol bits + + // This is the main loop where we read input bytes and compress them. We always keep track of the + // "prefix", which represents a pending byte (if < 256) or string entry (if >= FIRST_STRING) that + // has not been sent to the decoder yet. The output symbols are kept in the "shifter" and "bits" + // variables and are sent to the output every time 8 bits are available (done in the macro). + + while ((c = (*src)()) != EOF) { + int cti; // coding table index + + input_bytes++; + + if (prefix == NULL_CODE) { // this only happens the very first byte when we don't yet have a prefix + prefix = c; + continue; + } + + if ((cti = first_references [prefix])) { // if any longer strings are built on the current prefix... + while (1) + if (terminators [cti - 256] == c) { // we found a matching string, so we just update the prefix + prefix = cti; // to that string and continue without sending anything + break; + } + else if (!next_references [cti - 256]) { // this string did not match the new character and + next_references [cti - 256] = next; // there aren't any more, so we'll add a new string + cti = 0; // and point to it with "next_reference" + break; + } + else + cti = next_references [cti - 256]; // there are more possible matches to check, so loop back + } + else // no longer strings are based on the current prefix, so now + first_references [prefix] = next; // the current prefix plus the new byte will be the next string + + // If "cti" is zero, we could not simply extend our "prefix" to a longer string because we did not find a + // dictionary match, so we send the symbol representing the current "prefix" and add the new string to the + // dictionary. Since the current byte "c" was not included in the prefix, that now becomes our new prefix. + + if (!cti) { + WRITE_CODE (prefix, next); // send symbol for current prefix (0 to next-1) + terminators [next - 256] = c; // newly created string has current byte as the terminator + prefix = c; // current byte also becomes new prefix for next string + + // This is where we bump the next string index and decide whether to clear the dictionary and start over. + // The triggers for that are either the dictionary is full or we've been outputting too many bytes and + // decide to cut our losses before the symbols get any larger. Note that for the dictionary full case we + // do NOT send the CLEAR_CODE because the decoder knows about this and we don't want to be redundant. + + if (++next == total_codes || output_bytes > 8 + input_bytes + (input_bytes >> 4)) { + if (next < total_codes) + WRITE_CODE (CLEAR_CODE, next); + + // clear the dictionary and reset the byte counters -- basically everything starts over + // except that we keep the last pending "prefix" (which, of course, was never sent) + + memset (first_references, 0, total_codes * sizeof (first_references [0])); + memset (next_references, 0, (total_codes - 256) * sizeof (next_references [0])); + memset (terminators, 0, (total_codes - 256) * sizeof (terminators [0])); + input_bytes = output_bytes = 0; + next = FIRST_STRING; + } + } + } + + // we're done with input, so if we've received anything we still need to send that pesky pending prefix... + + if (prefix != NULL_CODE) { + WRITE_CODE (prefix, next); + + if (++next == total_codes) // watch for clearing to the first string to stay in step with the decoder! + next = FIRST_STRING; // (this was actually a corner-case bug that did not trigger often) + } + + WRITE_CODE (next, next); // the maximum possible code is always reserved for our END_CODE + + if (bits) // finally, flush any pending bits from the shifter + (*dst)(shifter); + +#ifdef KERNEL_MODE + kfree (terminators); kfree (next_references); kfree (first_references); +#else + free (terminators); free (next_references); free (first_references); +#endif + return 0; +} + +/* LZW decompression function. Bytes (8-bit) are read and written through callbacks. The + * "maxbits" parameter is read as the first byte in the stream and controls how much memory + * is allocated for decoding. A return value of EOF from the "src" callback terminates the + * compression process (although this should not normally occur). A non-zero return value + * indicates an error, which in this case can be a bad "maxbits" read from the stream, a + * failed malloc(), or if an EOF is read from the input stream before the compression + * terminates naturally with END_CODE. + */ + +int lzw_decompress (void (*dst)(int), int (*src)(void)) +{ + int read_byte, next = FIRST_STRING, prefix = CLEAR_CODE, bits = 0, total_codes; + unsigned char *terminators, *reverse_buffer; + unsigned long shifter = 0; + short *prefixes; + + if ((read_byte = ((*src)())) == EOF || (read_byte & 0xfc)) //sanitize first byte + return 1; + + // based on the "maxbits" parameter, compute total codes and allocate dictionary storage + + total_codes = 512 << (read_byte & 0x3); +#ifdef KERNEL_MODE + reverse_buffer = ( unsigned char *) kmalloc ((total_codes - 256) * sizeof (reverse_buffer [0])); + prefixes = ( short * ) kmalloc ((total_codes - 256) * sizeof (prefixes [0])); + terminators = ( unsigned char * ) kmalloc ((total_codes - 256) * sizeof (terminators [0])); +#else + reverse_buffer = ( unsigned char *) malloc ((total_codes - 256) * sizeof (reverse_buffer [0])); + prefixes = ( short * ) malloc ((total_codes - 256) * sizeof (prefixes [0])); + terminators = ( unsigned char * ) malloc ((total_codes - 256) * sizeof (terminators [0])); +#endif + + if (!reverse_buffer || !prefixes || !terminators) // check for mallco() failure + return 1; + + // This is the main loop where we read input symbols. The values range from 0 to the code value + // of the "next" string in the dictionary (although the actual "next" code cannot be used yet, + // and so we reserve that code for the END_CODE). Note that receiving an EOF from the input + // stream is actually an error because we should have gotten the END_CODE first. + + while (1) { + int code_bits = next < 1024 ? (next < 512 ? 8 : 9) : (next < 2048 ? 10 : 11), code; + int extras = (1 << (code_bits + 1)) - next - 1; + + do { + if ((read_byte = ((*src)())) == EOF) { +#ifdef KERNEL_MODE + kfree (terminators); kfree (prefixes); kfree (reverse_buffer); +#else + free (terminators); free (prefixes); free (reverse_buffer); +#endif + return 1; + } + + shifter |= (long) read_byte << bits; + } while ((bits += 8) < code_bits); + + // first we assume the code will fit in the minimum number of required bits + + code = (int) shifter & ((1 << code_bits) - 1); + shifter >>= code_bits; + bits -= code_bits; + + // but if code >= extras, then we need to read another bit to calculate the real code + // (this is the "adjusted binary" part) + + if (code >= extras) { + if (!bits) { + if ((read_byte = ((*src)())) == EOF) { +#ifdef KERNEL_MODE + kfree (terminators); kfree (prefixes); kfree (reverse_buffer); +#else + free (terminators); free (prefixes); free (reverse_buffer); +#endif + return 1; + } + + shifter = (long) read_byte; + bits = 8; + } + + code = (code << 1) - extras + (shifter & 1); + shifter >>= 1; + bits--; + } + + if (code == next) // sending the maximum code is reserved for the end of the file + break; + else if (code == CLEAR_CODE) // otherwise check for a CLEAR_CODE to start over early + next = FIRST_STRING; + else if (prefix == CLEAR_CODE) { // this only happens at the first symbol which is always sent + (*dst)(code); // literally and becomes our initial prefix + next++; + } + // Otherwise we have a valid prefix so we step through the string from end to beginning storing the + // bytes in the "reverse_buffer", and then we send them out in the proper order. One corner-case + // we have to handle here is that the string might be the same one that is actually being defined + // now (code == next-1). Also, the first 256 entries of "terminators" and "prefixes" are fixed and + // not allocated, so that messes things up a bit. + else { + int cti = (code == next-1) ? prefix : code; + unsigned char *rbp = reverse_buffer, c; + + do *rbp++ = cti < 256 ? cti : terminators [cti - 256]; // step backward through string... + while ((cti = (cti < 256) ? NULL_CODE : prefixes [cti - 256]) != NULL_CODE); + + c = *--rbp; // the first byte in this string is the terminator for the last string, which is + // the one that we'll create a new dictionary entry for this time + + do (*dst)(*rbp); // send string in corrected order (except for the terminator + while (rbp-- != reverse_buffer); // which we don't know yet) + + if (code == next-1) + (*dst)(c); + + prefixes [next - 1 - 256] = prefix; // now update the next dictionary entry with the new string + terminators [next - 1 - 256] = c; // (but we're always one behind, so it's not the string just sent) + + if (++next == total_codes) // check for full dictionary, which forces a reset (and, BTW, + next = FIRST_STRING; // means we'll never use the dictionary entry we just wrote) + } + + prefix = code; // the code we just received becomes the prefix for the next dictionary string entry + // (which we'll create once we find out the terminator) + } + +#ifdef KERNEL_MODE + kfree (terminators); kfree (prefixes); kfree (reverse_buffer); +#else + free (terminators); free (prefixes); free (reverse_buffer); +#endif + return 0; +} diff --git a/motorboard/motorboard.cpp b/motorboard/motorboard.cpp new file mode 100644 index 0000000..69bd2b7 --- /dev/null +++ b/motorboard/motorboard.cpp @@ -0,0 +1,892 @@ +#include "motorboard.h" +#include +#include "PinMonitor.h" +#include "uartregsaccess.h" +#include +#include "stringex.hpp" +#include "config.h" +#include "StopWatch.h" +#include "applog.h" +#include "StateControl.h" +#include "Displaydef.h" +#include "MotorConfig.h" +#include "DisplayCenter.h" +#include +#include "SensorConfig.h" + +static const std::string loggername = "MotorBoard"; + + +MotorBoard::MotorBoard(std::shared_ptr wake) + : devPort(MOTOR_UART), + m_glue({nullptr, nullptr, nullptr,nullptr,nullptr,nullptr,nullptr}), + autopaperkeystop(nullptr), + m_config({0}) +{ + LOG_INIT(); + //m_uartEnable.reset(new GpioOut(149)); + //m_uartEnable->setValue(Gpio::Low); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + m_regsAccess.reset(new UartRegsAccess(devPort, bauds, 0x07, 0x87)); + m_intPinMonitor.reset(new PinMonitor(intport, std::bind(&MotorBoard::pin_call, this, std::placeholders::_1))); + //m_uartEnable->setValue(Gpio::High); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + m_os_mode = os_mode(); + m_statecontrol.reset(new StateControl(m_regsAccess,wake)); + m_wake = wake; + init_sensor_duty(); +} + +static int paperinnum = 0; +void MotorBoard::start(HGScanConfig cfg) +{ + m_config = cfg; + keep_last_paper=false; + paperinnum = 0; + m_paperout_count = 0; + clear_error(); + set_motor_stop(false); + set_time_error(120); + set_double_inpect(m_config.g200params.double_feed_enbale); + set_staple_inpect(m_config.g200params.stable_enbale); + set_paper_inspect(0); + set_auto_paper(m_config.g200params.is_autopaper,m_config.g200params.en_anlogic_key); + set_screw_inpect(m_config.g200params.screw_detect_enable); + set_screw_level(m_config.g200params.screw_detect_level); + set_long_paper(true); + set_double_out_en(m_config.g200params.double_out_en); + unsigned int val; + SMBCONFIG *smbc = (SMBCONFIG *)(&val); + read(0, val); + smbc->enable = 0; + write(0, val); + smbc->enable = 1; + write(0, val); + + en_lifter(); +} + +void MotorBoard::stop() +{ + printf("MotorBoard Stop \n"); + unsigned int val; + SMBCONFIG *smbc = (SMBCONFIG *)(&val); + read(0, val); + smbc->enable = 0; + write(0, val); +} +bool MotorBoard::en_lifter() +{ + unsigned int val; + SMBCONFIG *smbc = (SMBCONFIG *)(&val); + read(0x00, val); + smbc->lifter_en = 1; + write(0x00, val); + smbc->lifter_en = 0; + return write(0x00, val); +} + +void MotorBoard::pick_paper(void) +{ + unsigned int val,pick_en; + SMBCONFIG *smbc = (SMBCONFIG *)(&val); + read(0x00, val); + smbc->pick_paper = 0; + write(0x00, val); + std::this_thread::sleep_for(std::chrono::microseconds(400)); + smbc->pick_paper = 1; + write(0x00, val); + std::string v_str = std::to_string(m_version); + if(v_str.size()<8) + return; + uint32_t date = atoi(v_str.substr(2,6).c_str()); +#ifdef G100 + if(date < 231115) + return; +#else + if(date < 231122) + return; +#endif + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + read(0x09,pick_en); + if(!(pick_en&0xffff)) + { + smbc->pick_paper = 0; + write(0x00, val); + std::this_thread::sleep_for(std::chrono::microseconds(400)); + smbc->pick_paper = 1; + write(0x00, val); + } + // smbc->pick_paper = 0; + // write(0x00, val); +} + +void MotorBoard::clean_paper_road(){ + unsigned int val; + SMB_FUNC *smbc = (SMB_FUNC *)(&val); + read(6, val); + if(smbc->param.work_mode == 0) + { + smbc->param.func_clean_passthro = 1; + write(6, val); + smbc->param.func_clean_passthro = 0; + write(6, val); + } + else{ + printf("\n 非空闲模式不允许清理纸道!!!!"); + } + +} + +void MotorBoard::clear_error() +{ + unsigned int val; + SMBCONFIG *smbc = (SMBCONFIG *)(&val); + read(0, val); + smbc->error_clean = 1; + write(0, val); + smbc->error_clean = 0; + write(0, val); +} + +bool MotorBoard::wait_arrival_top(int timeout_ms) +{ + return cv_arrival_top.wait(timeout_ms); +} + +bool MotorBoard::wait_paper_in(int timeout_ms) +{ + return cv_paper_in.wait(timeout_ms); +} + +bool MotorBoard::wait_error(int timeout_ms) +{ + return cv_error.wait(timeout_ms); +} + +bool MotorBoard::wait_paper_out(int timeout_ms) +{ + // StopWatch sw; + // LOG_TRACE("wait_paper_out "); + // while(sw.elapsed_ms() 0) + // { + // m_paperout_count--; + // return true; + // } + // std::this_thread::sleep_for(std::chrono::milliseconds(1)); + // } + // return false; + return cv_paper_out.wait(timeout_ms); +} + +bool MotorBoard::wait_done(int timeout_ms) +{ + return cv_scan_done.wait(timeout_ms); +} + +int MotorBoard::os_mode() +{ + // unsigned int val; + // read(0x02, val); + // SMB_MODE *smb_mode = (SMB_MODE *)&val; + // return smb_mode->scan_mode; + unsigned int val; + read(0x06,val); + SMB_FUNC smb_func = *(SMB_FUNC*)&val; + return smb_func.param.work_mode == 1; +} + +bool MotorBoard::paper_ready() +{ + unsigned int val; + read(0x02, val); + SMB_MODE *smb_mode = (SMB_MODE *)&val; + return smb_mode->feeding_paper_ready; +} + +bool MotorBoard::is_scanning() +{ + unsigned int val; + read(0x02, val); + SMB_MODE *smb_mode = (SMB_MODE *)&val; + return smb_mode->work_status; +} + +int MotorBoard::paper_counter() +{ + unsigned int val; + read(0x02, val); + SMBMODE *smb_mode = (SMBMODE *)&val; + return smb_mode->scan_num; +} + +bool MotorBoard::set_paper_inspect_param(unsigned int value /* = 1000 */) +{ + unsigned int val; + if (!read(0x04, val)) + return false; + SMBCONFIGEXT *smb_config_ext = (SMBCONFIGEXT *)&val; + smb_config_ext->error_range_set = value; + return write(0x04, val); +} + +bool MotorBoard::get_keeplastpaper(){ + return keep_last_paper; +} + +bool MotorBoard::set_paper_inpect_info(unsigned int value) +{ + unsigned int val; + if (!read(0x04, val)) + return false; + SMBCONFIGEXT *smb_config_ext = (SMBCONFIGEXT *)&val; + smb_config_ext->paper_infor = value; + return write(0x04, val); +} + +bool MotorBoard::set_paper_inspect(bool enable /* = true */) +{ + unsigned int val; + if (!read(0x04, val)) + return false; + SMBCONFIGEXT *smb_config_ext = (SMBCONFIGEXT *)&val; + smb_config_ext->paper_size_check_en = enable; + return write(0x04, val); +} + +bool MotorBoard::set_double_inpect(bool enable) +{ + unsigned int val; + if (!read(0x00, val)) + return false; + enable?m_statecontrol->lcdcontrol(4):m_statecontrol->lcdcontrol(5); + SMBCONFIG *smb_config = (SMBCONFIG *)&val; + smb_config->double_paper = enable; + return write(0x00, val); +} +bool MotorBoard::get_doublle_inpect() +{ + return 0; +} +bool MotorBoard::set_double_out_en(bool enable) +{ + unsigned int val; + if (!read(0x00, val)) + return false; + SMBCONFIG *smb_config = (SMBCONFIG *)&val; + smb_config->double_out_en = enable; + return write(0x00, val); +} +bool MotorBoard::get_double_out_en() +{ + unsigned int val; + if (!read(0x00, val)) + return false; + SMBCONFIG *smb_config = (SMBCONFIG *)&val; + return smb_config->double_out_en; +} +bool MotorBoard::set_staple_inpect(bool enable) +{ + unsigned int val; + if (!read(0x00, val)) + return false; + SMBCONFIG *smb_config = (SMBCONFIG *)&val; + smb_config->staple_enable = enable; + return write(0x00, val); +} +bool MotorBoard::get_staple_inpect() +{ + return 0; +} + +bool MotorBoard::set_cuospeed(int value) +{ + unsigned int val; + if (!read(0x4, val)) + return false; + SMBCONFIGEXT *smb_config = (SMBCONFIGEXT *)&val; + smb_config->cuo_speed = value; + return write(0x04, val); +} + +// bool MotorBoard::set_en600DPI(bool en) +// { +// unsigned int val; +// if (!read(0x00, val)) +// return false; +// SMBCONFIG *smb_config = (SMBCONFIG *)&val; +// smb_config->dpi600 = en?1:0; +// return write(0x00, val); +// } +bool MotorBoard::set_color_mode(int mode) +{ + unsigned int val; + if (!read(0x00, val)) + return false; + SMBCONFIG *smb_config = (SMBCONFIG *)&val; + smb_config->color_mode = mode; + return write(0x00, val); +} + +bool MotorBoard::set_slowmoire(bool en){ + unsigned int val; + if (!read(0x00, val)) + return false; + SMBCONFIG *smb_config = (SMBCONFIG *)&val; + smb_config->slow_moire = en; + return write(0x00, val); +} + + +int MotorBoard::get_color_mode() +{ + return 0; +} + +bool MotorBoard::set_speed_mode(int mode) +{ + unsigned int val; + if (!read(0x00, val)) + return false; + + SMBCONFIG *smb_config = (SMBCONFIG *)&val; + smb_config->speed_set_enable = 1; + smb_config->v_setting = mode; + write(0x00, val); + smb_config->speed_set_enable = 0; + return write(0x00, val); +} + +bool MotorBoard::set_speed_mode_v_temp(int mode) +{ + unsigned int val; + if (!read(0x00, val)) + return false; + printf(" set v_tmp = %d \n",mode); + SMBCONFIG *smb_config = (SMBCONFIG *)&val; + smb_config->speed_set_enable = 1; + smb_config->v_temp = mode; + write(0x00, val); + smb_config->speed_set_enable = 0; + return write(0x00, val); +} + +int MotorBoard::get_speed_mode() +{ + unsigned int val; + if (!read(0x00, val)) + return -1; + SMBCONFIG *smb_config = (SMBCONFIG *)&val; + return smb_config->v_setting; +} + +std::shared_ptr MotorBoard::regs() +{ + return m_regsAccess; +} +static int countindex =0; +void MotorBoard::pin_call(unsigned int pinNum) +{ + static int index = 0; + // int os_m = os_mode(); //安路屏蔽计数 扫描过程中无法操作按键 + // if (m_os_mode != os_m) + // { + // m_os_mode = os_m; + // cv_os_mode.notify_all(); + // if (m_glue.m_os_mode_call) + // m_glue.m_os_mode_call(m_os_mode); + // } + + // if (m_os_mode) //安路屏蔽计数返回 以刷新计数状态 + // { + // LOG_TRACE("not scan mode"); + // return; + // } + + unsigned int val; + SMBSTATUS *smb_status = (SMBSTATUS *)&val; + if (!read(0x01, val)) + LOG_TRACE("read error"); + LOG_TRACE(string_format("status %08x", val)); + if(val & 0x800){ + //printf("\n keep_last_paper "); + keep_last_paper=true; + } + if(val & 0x1000) + { + if(m_glue.m_set_sleepmode_call) + m_glue.m_set_sleepmode_call(val & 0xf000); + } + if(val & 0x80000) + { + if(m_glue.m_mltop_call) + m_glue.m_mltop_call(val); + } + if(smb_status->auto_feed) + { + if(m_glue.m_auto_paper) + m_glue.m_auto_paper(1); + } + if (val & 0x7c003FE) + { + SetKeyState(false); + cv_error.notify_all(); + if (m_glue.m_error_call) + m_glue.m_error_call(val & 0x30efe); //0xefe index of 16:aquireimage error index of bit 17 :size check error + if(val & 0x30efe){ + cv_paper_out.notify_all(); + cv_paper_in.notify_all(); + m_paperout_count++; + } + errormsg(val & 0x1c003fa); + if((val & 0x4) ||(val & 0x02000000)) + { + if(m_glue.m_coveropen_call) + m_glue.m_coveropen_call((val & 0x4));//cover open & 0x04 + if(val & 0x4){ + PutMsg(DisType::Dis_Err_CoverOpen,0,ClearScreen::All); + set_auto_paper(false,false); + autopaperkeystop?autopaperkeystop():void(0); + if(m_statecontrol){ + m_statecontrol->setcoverstate(true); + m_statecontrol->setmenuindex(0); + } + } + else{ + PutMsg(DisType::Dis_Idel,0,ClearScreen::All); + m_statecontrol?m_statecontrol->setcoverstate(false):void(); + } + return; + } + if(smb_status->double_clean_f) + PutMsg(DisType::Dis_Idel,0,ClearScreen::All); + LOG_TRACE("error"); + return; + } + else + { + if (!smb_status->scan_pulse) + { + cv_paper_in.notify_all(); + unsigned int papercount = 0; + read(0x02,papercount); + SMBMODE smbmode = *(SMBMODE*)&papercount; + printf("paper in arm count = %d ,motorcount = %d\n",++countindex,smbmode.scan_num); + startcapimage(true); + PutMsg(DisType::Dis_Scan_Page, smbmode.scan_num,ClearScreen::BOT); + } + if(smb_status->paper_left) + { + cv_paper_out.notify_all(); + m_paperout_count++; + //printf("paper out time = %s \n",GetCurrentTimeStamp(2).c_str()); + startcapimage(true); + LOG_TRACE(string_format("m_paperout_count %s",to_string(m_paperout_count))); + } + } + + if (val & 0x400) + { + LOG_TRACE("done"); + cv_scan_done.notify_all(); + if (m_glue.m_scan_done_call) + m_glue.m_scan_done_call(); + cv_paper_out.notify_all(); + cv_paper_in.notify_all(); + clear_error(); + SetKeyState(false); + if(m_wake.get()) + m_wake->setsleepfalg(false); + } +} + +bool MotorBoard::write(unsigned int addr, unsigned int val) +{ + return m_regsAccess.get()?m_regsAccess->write(addr, val):false; +} + +bool MotorBoard::read(unsigned int addr, unsigned int &val) +{ + return m_regsAccess.get()?m_regsAccess->read(addr, val):false; +} + + bool MotorBoard::set_time_error(int value){ + unsigned int val; + if (!read(0x05, val)) + return false; + SMBCONFIGTIME *smb_config = (SMBCONFIGTIME *)&val; + smb_config->error_time_set = value; + return write(0x05, val); + } + +void MotorBoard::set_callbacks(MotorBoardGlue glue) +{ + m_glue = glue; +} + +bool MotorBoard::set_screw_inpect(bool enable) +{ + unsigned int val; + if (!read(0x00, val)) + return false; + SMBCONFIG *smb_config = (SMBCONFIG *)&val; + smb_config->skew_enable = enable; + return write(0x00, val); +} +bool MotorBoard::get_screw_inpect() +{ + unsigned int val; + read(0x00, val); + SMBCONFIG *smb_mode = (SMBCONFIG *)&val; + return smb_mode->skew_enable; +} + +bool MotorBoard::set_screw_level(int level) +{ + unsigned int val; + if (!read(0x00, val)) + return false; + SMBCONFIG *smb_config = (SMBCONFIG *)&val; + smb_config->skew_parameter = level; + return write(0x00, val); +} + +bool MotorBoard::set_auto_paper(bool enable,bool enkey){ + unsigned int val; + if (!read(0x00, val)) + return false; + m_statecontrol?m_statecontrol->setautopaperflag(enable,enkey):void(0); + SMBCONFIG *smb_config = (SMBCONFIG *)&val; + smb_config->autofeed_mode = enable; + return write(0x00, val); +} + +bool MotorBoard::set_long_paper(bool enable) +{ + unsigned int val; + if (!read(0x00, val)) + return false; + SMBCONFIG *smb_config = (SMBCONFIG *)&val; + smb_config->paper = enable; + return write(0x00, val); +} + +int MotorBoard::get_screw_level() +{ + unsigned int val; + auto ret= read(0x00, val); + if(!ret) + return -1; + SMBCONFIG *smb_mode = (SMBCONFIG *)&val; + return smb_mode->skew_parameter; +} + +void MotorBoard::start_countmode() +{ + unsigned int regval=0; + + read(0x06,regval); + LOG_TRACE(string_format("func6 regval = %08x",regval)); + SMBFUNC func = *(SMBFUNC*)®val; + func.param.work_mode =1; + func.param.func_feed_mid = 1; + func.param.func_clear_count = 1; + LOG_TRACE(string_format("func6 value = %08x",func.value)); + write(0x06,func.value); + func.param.func_encount = 1; + func.param.key_sound = 1; + func.param.func_clear_count = 0; + LOG_TRACE(string_format("func6 value = %08x",func.value)); + write(0x06,func.value); + func.param.func_encount = 0; + func.param.key_sound = 0; + LOG_TRACE(string_format("func6 value = %08x",func.value)); + write(0x06,func.value); +} + + +void MotorBoard::PutMsg(DisType type,int value,ClearScreen clearscreen) +{ + if(m_statecontrol.get()) + m_statecontrol->PutMsg(type,value,clearscreen); +} + +void MotorBoard::errormsg(uint value) +{ + if(value & 0x4) + PutMsg(DisType::Dis_Err_CoverOpen,0,ClearScreen::All); + else if (value & 0x2) + PutMsg(DisType::Dis_Err_NoPaper,0,ClearScreen::All); + else if (value & 0x8) + PutMsg(DisType::Dis_Err_FeedError,0,ClearScreen::All); + // else if (value & 0x10) + // PutMsg(DisType::Dis_Err_JamIn,0,ClearScreen::All); + else if (value & 0x20) + PutMsg(DisType::Dis_Err_DoubleFeed,0,ClearScreen::All); + else if (value & 0x40) + PutMsg(DisType::Dis_Err_Stable,0,ClearScreen::All); + else if (value & 0x80) + PutMsg(DisType::Dis_Err_PaperScrew,0,ClearScreen::All); + else if (value & 0x00010000) + PutMsg(DisType::Dis_Err_AqrImgTimeout,0,ClearScreen::All); + else if((value & 0x1000010) == 0x1000010) + PutMsg(DisType::Dis_Err_JamIn,3,ClearScreen::All); + else if((value & 0x800010) == 0x800010) + PutMsg(DisType::Dis_Err_JamIn,2,ClearScreen::All); + else if((value & 0x400010) == 0x400010) + PutMsg(DisType::Dis_Err_JamIn,1,ClearScreen::All); +} + +void MotorBoard::SetKeyState(bool value) +{ + if(m_statecontrol) + m_statecontrol->setrunstate(value); +} + + +void MotorBoard::set_keystopenable(bool value){ + unsigned int regval=0; + read(0x06,regval); + LOG_TRACE(string_format("func6 regval = %08x",regval)); + SMBFUNC func = *(SMBFUNC*)®val; + func.param.key_stop_enable = value; + write(0x06,regval); +} + + +void MotorBoard::set_freq(int motor_choose,int speedmode,int colormode,int dpi) +{ + MotorConfig cf; + auto params = cf.GetMotorSpeedParams(motor_choose == 1?0:1,MotorConfig::MTBDType::MT_DRV); + MotorSpeedParam param; + //printf("\n---node.dpi ==%d && node.colormode == %d && node.speed == %d----- ",dpi,colormode,speedmode); + for(auto &node : params) + { + if(node.dpi == dpi && node.colormode == colormode && node.speed == speedmode) + { + param = node.mt_param; + //printf("\n-------------------------------------------------"); + break; + } + } + std::vector table; + if(motor_choose == 0) + { + int x = (dpi == 1?(Get_static_jsonconfig().getscannerinfo().chu_motor_speed_200):(dpi == 2?Get_static_jsonconfig().getscannerinfo().chu_motor_speed_300 : Get_static_jsonconfig().getscannerinfo().chu_motor_speed_600)); + unsigned int regval=0; + read(0x06,regval); + SMBFUNC func = *(SMBFUNC*)®val; + func.param.motor_choose = motor_choose; + func.param.wr_en = 1; + write(0x06,func.value); + write(0x04,x); + //func.param.wr_en = 0; + //write(0x06,func.value); + return ; + } + if(motor_choose == 1) + table = frep_cfg(param.finalPeriod,param.Fmin,param.stepnum,param.a,param.offset,param.finalDelay,param.acceleration_time); + if(motor_choose == 2) + table = frep_cfg(param.finalPeriod,param.Fmin,param.stepnum,param.a,param.offset,param.finalDelay,param.acceleration_time); + if(motor_choose == 3) + table = frep_cfg(param.finalPeriod,param.Fmin,param.stepnum,param.a,param.offset,param.finalDelay,param.acceleration_time); + unsigned int regval=0; + read(0x06,regval); + SMBFUNC func = *(SMBFUNC*)®val; + int start_addr_cuo = 0; +#ifdef G200 + if(motor_choose ==1 && speedmode > 1 && dpi <3) + start_addr_cuo = 63; + if(motor_choose ==1 && dpi ==3) + start_addr_cuo = 127; +#endif + printf("\nstart_addr_cuo =%d ",start_addr_cuo); + for(int i =0;i<256;i++) + { + func.param.motor_choose = motor_choose; + func.param.wr_en = 1; + func.param.motor_addr =i; + write(0x06,func.value); + write(0x04,isetautopaperstopcallback([&]{ + autopaperkeystop?autopaperkeystop():void(0); + if(m_config.g200params.is_autopaper) + set_auto_paper(false,false); + }); + init_sensor_duty(); + PutMsg(DisType::Dis_Idel,0,ClearScreen::All); +} + +void MotorBoard::release_statecontrol() +{ + + if(autopaperkeystop.operator bool()) + autopaperkeystop(); + set_auto_paper(false,false); + m_statecontrol.reset(); + m_regsAccess.reset(); + m_intPinMonitor.reset(); + +} + +void MotorBoard::setautopaperkeystopcallback(std::function func){ + if(func) + autopaperkeystop = func; + m_statecontrol?m_statecontrol->setautopaperstopcallback([&]{ + autopaperkeystop?autopaperkeystop():void(0); + set_auto_paper(false,false); + }):void(0); +} +void MotorBoard::startcapimage(bool value) +{ + // if(m_config.g200params.is_fixedpaper) + // return; + // FILE *fp = fopen("/sys/class/tty/ttyUSB0/device/huagao_scanner", "w"); + // if (fp == NULL) + // perror("startcapimage open filed"); + // else{ + // fprintf(fp, "%d", value ? 1 : 0); + // fclose(fp); + // } +} + +bool MotorBoard::set_sensor_pwm_duty(int sensorid,int duty) +{ + //1:扫描;2:开盖;3:歪斜—1;4:歪斜-2;5:出纸口;6:有无纸 + printf("set_sensor_pwm_duty type = %d duty = %d \n",sensorid,duty); + unsigned int val; + if (!read(0x05, val)) + return false; + if(sensorid< 1 || sensorid >6) + return false; + if(duty< 2 || duty > 90) + return false; + SMBCONFIGTIME *smb_config_time = (SMBCONFIGTIME *)&val; + smb_config_time->sen_duty_set_sel = sensorid; + smb_config_time->duty_set = duty*8+50; + write(0x05, val); + smb_config_time->sen_duty_set_sel = 0; + return write(0x05, val); +} + +bool MotorBoard::enable_sensor_pwm(int sensorid,bool en) +{ + std::uint32_t val; + if (!read(0x05, val)) + return false; + if(sensorid< 1 || sensorid >6) + return false; + std::bitset<32> bit(val); + bit.set(sensorid+6,en); + val = bit.to_ulong(); + printf("enable_sensor_pwm = %d \n",val); + return write(0x05, val); +} + +bool MotorBoard::set_ultrasonic_param(int type,int value){ + //1:双张检测周期;2:有无纸检测周期;3:双张阈值;4:单张阈值; + unsigned int val; + if (!read(0x07, val)) + return false; + if(type< 1 || type >4) + return false; + printf("set_ultrasonic_param type = %d value = %d \n",type,value); + SMB_Ultrasonic_Config *tmp = (SMB_Ultrasonic_Config *)&val; + switch (type) + { + case 1: + tmp->param.double_check_cyc = value; + break; + case 2: + tmp->param.paper_check_cyc = value; + break; + case 3: + tmp->param.double_max = value; + break; + case 4: + tmp->param.single_max = value; + break; + default: + break; + } + printf("val = %d \n",val); + tmp->param.send_cyc_en = 1; + write(0x07,val); + tmp->param.send_cyc_en = 0; + return write(0x07,val); +} + +void MotorBoard::init_sensor_duty() +{ + auto p = Get_Static_SC().get_mem_param(); + std::vector params(sizeof(SensorConfig::SensorConfig_Param)/sizeof(uint32_t)); + memcpy(¶ms[0],&p,sizeof(SensorConfig::SensorConfig_Param)); + for(int i = 0;i= 0) || (i < 6)) && (params[i] < 100)) + { + set_sensor_pwm_duty(i+1,params[i]); + } + if((i >= 6) || (i < 10)) + { + set_ultrasonic_param(i-5,params[i]); + } + } +} + +std::uint32_t MotorBoard::get_ultrasonic_version(){ + unsigned int val; + if (!read(0x07, val)) + return 0; + SMB_Ultrasonic_Config *tmp = (SMB_Ultrasonic_Config *)&val; + tmp->param.rd_ver_en = 1; + write(0x07,val); + tmp->param.rd_ver_en = 0; + write(0x07,val); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + read(0x08,val); + return val; +} + +std::string MotorBoard::getmbversion(){ + u32 value = 0; + read(0x03, value); + m_version = value; + printf("mb version: = %s \n", std::to_string(value).c_str()); + return std::to_string(value); +} + +bool MotorBoard::set_motor_stop(bool value) +{ + SMB_FUNC reg6; + if(!read(6,reg6.value)) + return false; + reg6.param.motor_disable = value; + return write(6,reg6.value); +} + +SMB_JAM_Time MotorBoard::get_jam_param() +{ + SMB_JAM_Time jam_time{0}; + read(0xa,jam_time.value); + return jam_time; +} + +void MotorBoard::set_jam_param(SMB_JAM_Time jam_time) +{ + write(0xa,jam_time.value); +} \ No newline at end of file diff --git a/motorboard/motorboard.h b/motorboard/motorboard.h new file mode 100644 index 0000000..f664791 --- /dev/null +++ b/motorboard/motorboard.h @@ -0,0 +1,273 @@ +#pragma once +#include +#include +#include +#include +#include "autoevent.hpp" +#include "commondef.h" +#include +#include +#include "wakeup.hpp" + +//static std::vector frep_cfg(int a,int b,float k,int s) +static std::vector frep_cfg(int finalPeriod, int Fmin, float stepnum, float a, float offset, float finalDelay,float acceleration_time) +{ + std::vector freq; + int freq_word = 0; + int pulse_word = 0; + for(int i =1;i<=256;i++) + { + freq_word = 8000000/((Fmin+(finalPeriod-Fmin)/(1+exp((-1)*(offset+a*(double)(i)*stepnum))))*2); + pulse_word = ((8000000/acceleration_time)/63)/freq_word; + //printf("\nfreq_word = %d pulse_word = %d",freq_word,pulse_word); + freq.push_back((pulse_word&0xffff)+((freq_word&0xffff)<<16)); + } + return freq; +} +class IRegsAccess; +class PinMonitor; +class Gpio; +class StateControl; +enum class DisType; +enum class ClearScreen; +/* +注: + 安路电机板已去除幅面检测以及休眠配置相关寄存器操作, + 休眠将由Arm 进行控制 +*/ + +typedef struct SMB_CONFIG +{ + unsigned int enable : 1; + unsigned int color_mode : 1; + unsigned int paper : 1; + unsigned int double_paper : 1; + unsigned int staple_enable : 1;//5 + unsigned int error_clean : 1; + unsigned int status_init : 1; + unsigned int pick_paper : 1; + unsigned int skew_enable : 1; + unsigned int skew_parameter : 3; + unsigned int key_staple_enable : 1;//8 + unsigned int iic_config_addr : 7; + unsigned int slow_moire : 1; + unsigned int v_setting : 2;//10 + unsigned int speed_set_enable : 1; + unsigned int double_out_en : 1; + unsigned int dpi_mode : 2; + // unsigned int sleep_parameter : 2;//6 + // unsigned int dpi600:1; + unsigned int v_temp : 3; + unsigned int autofeed_mode:1; + unsigned int lifter_en:1; +} SMBCONFIG; + +typedef struct SMB_STATUS +{ + unsigned int scan_pulse : 1; + unsigned int m1_paper_sin : 1; + unsigned int open_machine : 1; + unsigned int pick_failed : 1; + unsigned int stop_jam : 1;//5 + unsigned int double_paper : 1; + unsigned int staple : 1; + unsigned int papertilted : 1; + unsigned int count_pulse : 1; + unsigned int scan_mode_change : 1;//5 + unsigned int motor_status : 1; + unsigned int keep_last_paper : 1; + unsigned int sleep_set : 1; + unsigned int sleep_conf : 3;//6 + unsigned int dsp_get_paper_error : 1; + unsigned int paper_check_result : 1; + unsigned int arrival_top:1;//顶部无纸 + unsigned int arrival_top_int:1;//到达顶部中断 + unsigned int auto_feed:1;//4 + unsigned int paper_left:1; + unsigned int jam_1 : 1; //进纸口 + unsigned int jam_2 : 1; //纸道 + unsigned int jam_3 : 1; //出纸口 + unsigned int cover_closed : 1; //已关盖 + unsigned int double_clean_f : 1; //液晶双张错误清除 +} SMBSTATUS; + +typedef struct SMB_MODE +{ + unsigned int scan_num : 14; + unsigned int scan_mode : 2; + unsigned int feeding_paper_ready : 1; + unsigned int work_status : 1; +} SMBMODE; +//Reg 4 +typedef struct SMB_CONFIG_EXT +{ + unsigned int paper_infor : 5; + unsigned int paper_size_check_en : 1; + unsigned int error_range_set : 15; + unsigned int cuo_speed : 7; +} SMBCONFIGEXT; +//Reg 5 +typedef struct SMB_CONFIG_TIME +{ + unsigned int error_time_set : 7; + unsigned int scan_ctr_en : 1; + unsigned int skew_ctr_en_1 : 1; + unsigned int skew_ctr_en_2 : 1; + unsigned int open_machine_ctr_en : 1; + unsigned int paper_out_ctr_en : 1; + unsigned int paper_check_ctr_en : 1; + unsigned int sen_duty_set_sel : 3; + unsigned int duty_set : 10; +} SMBCONFIGTIME; + + +//Reg 6 +typedef union SMB_FUNC +{ + struct{ + unsigned int work_mode : 3; + unsigned int func_clean_passthro : 1; + unsigned int func_feed_low : 1; + unsigned int func_feed_mid : 1; + unsigned int func_feed_high : 1; + unsigned int key_sound : 1; + unsigned int key_endouble_feed : 1; + unsigned int func_encount : 1; + unsigned int func_clear_count : 1; + unsigned int motor_choose : 2; + unsigned int wr_en : 1; + unsigned int motor_addr : 8; + unsigned int key_stop_enable : 1; + unsigned int lift_init_set: 2; + unsigned int unused: 3; + unsigned int motor_disable : 1; + }param; + unsigned int value; +} SMBFUNC; + +//Reg 7 +typedef union SMB_Ultrasonic_Config +{ + struct + { + unsigned int double_check_cyc : 4; + unsigned int paper_check_cyc : 4; + unsigned int double_max : 8; + unsigned int single_max : 8; + unsigned int rd_ver_en : 1; + unsigned int send_cyc_en : 1; + unsigned int reserved : 6; + }param; + unsigned int value; +}SMBUltrasonicConfig; + + +//Reg 10 +typedef union SMB_JAM_Time +{ + struct + { + unsigned int jam_time_1 : 8; + unsigned int jam_time_2 : 8; + unsigned int jam_time_3 : 8; + unsigned int jam_time_4 : 8; + }param; + unsigned int value; +}SMBJAMTime; + + +class MotorBoard +{ +public: + MotorBoard(std::shared_ptr wake); + + void start(HGScanConfig cfg); + void stop(); + void clear_error(); + void pick_paper(); + int os_mode(); + bool paper_ready(); + bool is_scanning(); + int paper_counter(); + bool en_lifter(); + bool set_long_paper(bool enable); + bool set_double_inpect(bool enable); + bool get_doublle_inpect(); + bool set_double_out_en(bool enable); + bool get_double_out_en(); + bool set_staple_inpect(bool enable); + bool get_staple_inpect(); + bool set_color_mode(int mode); + int get_color_mode(); + int get_speed_mode(); + bool set_auto_paper(bool enable,bool enkey); + bool set_speed_mode(int mode); + bool set_speed_mode_v_temp(int mode); + bool set_screw_inpect(bool enable); + bool get_screw_inpect(); + bool set_screw_level(int level); + int get_screw_level(); + bool wait_arrival_top(int timeout_ms); + bool wait_paper_in(int timeout_ms); + bool wait_paper_out(int timeout_ms); + bool wait_error(int timeout_ms); + bool wait_done(int timeout_ms); + bool read(unsigned int addr, unsigned int &val); + bool write(unsigned int addr, unsigned int val); + bool set_paper_inspect_param(unsigned int value = 1000); + bool set_paper_inpect_info(unsigned int value); + bool set_paper_inspect(bool enable = true); + void set_callbacks(MotorBoardGlue glue); + bool set_cuospeed(int value); + bool get_keeplastpaper(); + //bool set_en600DPI(bool en); + bool set_time_error(int value); + void start_countmode(); + std::shared_ptr regs(); + void PutMsg(DisType type,int value,ClearScreen clearscreen); + void SetKeyState(bool value); + void set_freq(int motor_choose,int speedmode,int colormode,int dpi); + void set_keystopenable(bool value); + void init_statecontrol(); + void release_statecontrol() __attribute__((optimize("O0"))); + void setautopaperkeystopcallback(std::function func); + void errormsg(uint value); + void startcapimage(bool value); + void clean_paper_road(); + bool set_slowmoire(bool en); + bool set_sensor_pwm_duty(int sensorid,int duty); + bool enable_sensor_pwm(int sensorid,bool en); + bool set_ultrasonic_param(int type,int value); + void init_sensor_duty(); + bool set_motor_stop(bool value); + SMB_JAM_Time get_jam_param(); + void set_jam_param(SMB_JAM_Time jam_time); + std::uint32_t get_ultrasonic_version(); + std::string getmbversion(); +private: + void pin_call(unsigned int pinNum); + + + const std::string devPort; + const unsigned int bauds = 921600; + const int readflag = 0x07; + const int writeflag = 0x87; + const unsigned int intport = 151; + uint32_t m_version; + std::shared_ptr m_regsAccess; + std::shared_ptr m_intPinMonitor; + std::shared_ptr m_statecontrol; + std::shared_ptr m_wake; + std::atomic_uint m_paperout_count; + AutoSemaphore cv_paper_in; + AutoSemaphore cv_arrival_top; + AutoSemaphore cv_paper_out; + AutoSemaphore cv_error; + AutoSemaphore cv_scan_done; + AutoSemaphore cv_os_mode; + HGScanConfig m_config; + unsigned int m_os_mode; + volatile bool keep_last_paper; + MotorBoardGlue m_glue; + std::function autopaperkeystop; +}; \ No newline at end of file diff --git a/motorboard/opcode.h b/motorboard/opcode.h new file mode 100644 index 0000000..cf0ad91 --- /dev/null +++ b/motorboard/opcode.h @@ -0,0 +1,142 @@ +/******************************************************************* +* Copyright (c) 2011 -2021 Anlogic Inc. + * The Software is distributed in source code form and is open to + * re-distribution and modification where applicable +*******************************************************************/ + + +#ifndef OPCODE_H +#define OPCODE_H + + +#define AJE_DEBUG + + + +// SVF OpCode +#define UNKNOWN 0x00 +#define TRST 0x01 +#define ON 0x02 +#define OFF 0x03 +#define STATE 0x04 +#define ENDIR 0x05 +#define ENDDR 0x06 +#define FREQUENCY 0x07 +#define HZ 0x08 +#define TDR 0x09 +#define TIR 0x0A +#define HDR 0x0B +#define HIR 0x0C +#define SDR 0x0D +#define SIR 0x0E +#define TDI 0x0F +#define TDO 0x10 +#define MASK 0x11 +#define SMASK 0x12 +#define RUNTEST 0x13 +#define TCK 0x14 +#define ENDCMD 0x15 +#define LEFTPAREN 0x16 +#define CONTINUE 0x17 +#define WAIT 0x18 +#define XSDR 0x19 +#define XTDI 0x1A +#define XTDO 0x1B +#define RSDR 0x1C /* It means two SDRs and TDI data of second SDR is the same as TDO of first SDR */ +#define HEADER 0x20 /* Add the specified header to AJE file */ +#define COMMENT 0x21 /* Write comments in SVF file into AJE file */ +#define SETFLOW 0x22 /* Change the flow control register. */ +#define RESETFLOW 0x23 /* Clear the flow control register. */ + +#define LOOP 0x24 +#define ENDLOOP 0x25 + +// Header +#define FILECRC 0x61 +#define MEM 0x62 // The maximum memory needed to allocate in order hold one row of data. +#define ENDFILE 0x7F // End of the file +#define BEGINLINE 0x5E // Begining of line +#define ENDLINE 0x24 // End of line + +// JTAG OpCode +#define RESET 0x00 +#define IDLE 0x01 +#define IRSHIFT 0x02 +#define DRSHIFT 0x03 +#define DRPAUSE 0x04 +#define IRPAUSE 0x05 +#define DRSELECT 0x06 +#define IRSELECT 0x07 +#define DRCAPTURE 0x08 +#define IRCAPTURE 0x09 +#define DREXIT1 0x10 +#define IREXIT1 0x11 +#define DREXIT2 0x12 +#define IREXIT2 0x13 +#define DRUPDATE 0x14 +#define IRUPDATE 0x15 + +// Flow control register bit definitions. +// A set bit indicates that the register currently exhibits the corresponding mode. +#define INTEL_PRGM 0x0001 /* Intelligent programming is in effect. */ +#define CASCADE 0x0002 /* Currently splitting large SDR. */ +#define REPEATLOOP 0x0008 /* Currently executing a repeat loop. */ +#define SHIFTRIGHT 0x0080 /* The next data stream needs a right shift. */ +#define SHIFTLEFT 0x0100 /* The next data stream needs a left shift. */ +#define VERIFYUES 0x0200 /* Continue if fail is in effect. */ + + +// Vendor Code +#define VENDOR 0x56 +#define ANLOGIC 0x01 +#define XILINX 0x02 +#define ALTERA 0x03 +#define LATTICE 0x04 + +// Mode Code +#define COMP_MODE 0xF1 // compress mode +#define FULL_MODE 0xF2 // full mode + +// SIR Command +#define BYPASS 0xFF +#define SAMPLE 0x05 +#define IDCODE_PUB 0x06 +#define IDCODE_PUB_2 0xE0 + +// Reading IO Status +#define LINE_MAX_SIZE 1000 /* max size of a line when reading svf file */ +#define DATA_MAX_SIZE 300 /* max size of tdi/tdo/mask hex str in svf file */ + +// return type +#define AJE_OK 0 +#define AJE_WARNING -1 +#define AJE_ERROR -2 +#define AJE_FILE_OPEN_FAIL -6 +#define AJE_FILE_INVALID -7 +#define AJE_INVALID_COMMAND -10 +#define AJE_INVALID_VALUE -11 +#define AJE_INVALID_TAP_STATE -12 +#define AJE_TRANSFER_FAIL -16 +#define AJE_VERIFY_FAIL -17 + +/* TAP STATE Enumerate */ +enum TAP_STATE { + TAP_RESET = 0, /* Initialization state */ + TAP_IDLE = 1, + TAP_DRSELECT = 2, /* DR STATE: 2~8 */ + TAP_DRCAPTURE = 3, + TAP_DRSHIFT = 4, + TAP_DREXIT1 = 5, + TAP_DRPAUSE = 6, + TAP_DREXIT2 = 7, + TAP_DRUPDATE = 8, + TAP_IRSELECT = 9, /* IR STATE: 9~15 */ + TAP_IRCAPTURE = 10, + TAP_IRSHIFT = 11, + TAP_IREXIT1 = 12, + TAP_IRPAUSE = 13, + TAP_IREXIT2 = 14, + TAP_IRUPDATE = 15, +}; + +#endif // OPCODE_H diff --git a/motorboard/vec.cpp b/motorboard/vec.cpp new file mode 100644 index 0000000..9562a47 --- /dev/null +++ b/motorboard/vec.cpp @@ -0,0 +1,521 @@ +/******************************************************************* + * Copyright (c) 2011 -2021 Anlogic Inc. + * This file is strictly confidential. All rights reserved. +*******************************************************************/ + +/*********************************************************************** +Filename: vec.c +Description: generate vec +Log: initial version, July 2019 + ***********************************************************************/ + +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include +#include +#include +#include "Jtag.h" + +#include "opcode.h" + + +/* global variables about hdr/hir/tdr/tir */ +unsigned int g_hdr_size = 0; +unsigned int g_hir_size = 0; +unsigned int g_tdr_size = 0; +unsigned int g_tir_size = 0; + +unsigned char* g_hdr_data = NULL; +unsigned char* g_hir_data = NULL; +unsigned char* g_tdr_data = NULL; +unsigned char* g_tir_data = NULL; + +static Jtag jtag_burning; + +/* function declared in ajeutil.c */ +extern int Anlogic_GetBit(unsigned char* data, int id); +extern void Anlogic_SetBit(unsigned char* data, int id, int val); +extern unsigned char Anlogic_ReverseChar(unsigned char byte); + + +/* Function forward declaration */ +void Anlogic_WritePulseTck(void); + +/* Tap Opcode To TAP_STATE */ +enum TAP_STATE Anlogic_TapState(unsigned char opcode) { + enum TAP_STATE state = TAP_RESET; + switch (opcode) { + case RESET: state = TAP_RESET; break; + case IDLE: state = TAP_IDLE; break; + case DRSELECT: state = TAP_DRSELECT; break; + case DRCAPTURE: state = TAP_DRCAPTURE; break; + case DRSHIFT: state = TAP_DRSHIFT; break; + case DREXIT1: state = TAP_DREXIT1; break; + case DRPAUSE: state = TAP_DRPAUSE; break; + case DREXIT2: state = TAP_DREXIT2; break; + case DRUPDATE: state = TAP_DRUPDATE; break; + case IRSELECT: state = TAP_IRSELECT; break; + case IRCAPTURE: state = TAP_IRCAPTURE; break; + case IRSHIFT: state = TAP_IRSHIFT; break; + case IREXIT1: state = TAP_IREXIT1; break; + case IRPAUSE: state = TAP_IRPAUSE; break; + case IREXIT2: state = TAP_IREXIT2; break; + case IRUPDATE: state = TAP_IRUPDATE; break; + default: + printf("Error: Illegal tap state opcode %u\n", (unsigned int)opcode); + } + return state; +} + +/* TAP_STATE to TapState String */ +const char* Anlogic_TapState2Str(enum TAP_STATE tap_state) { +#define X(_w) if (tap_state == TAP_ ## _w) return #_w + X(RESET); + X(IDLE); + X(DRSELECT); + X(DRCAPTURE); + X(DRSHIFT); + X(DREXIT1); + X(DRPAUSE); + X(DREXIT2); + X(DRUPDATE); + X(IRSELECT); + X(IRCAPTURE); + X(IRSHIFT); + X(IREXIT1); + X(IRPAUSE); + X(IREXIT2); + X(IRUPDATE); +#undef X + return "TapState2Str: unkown state"; +} + +static enum TAP_STATE cur_tap_state = TAP_RESET; /* current tap state */ +static enum TAP_STATE end_dr_state = TAP_IDLE; /* the tap state that device goes after sdr */ +static enum TAP_STATE end_ir_state = TAP_IDLE; /* the tap state that device goes after sir */ + + +/* Tap State Transistions */ +int Anlogic_TapTransist(enum TAP_STATE state) { + int id = 0; + int count = 0; + +// printf("Anlogic_TapTransist start...\n"); + if (cur_tap_state == state && state == TAP_RESET) { + for (id = 0; id < 6; ++id) { + jtag_burning.TMS_Wr(1); + + Anlogic_WritePulseTck(); + } +// printf("Anlogic_TapTransist 107 end...\n"); + return 0; + } + + while (cur_tap_state != state) { + switch (cur_tap_state) { + case TAP_RESET: + jtag_burning.TMS_Wr(0); + cur_tap_state = TAP_IDLE; + break; + case TAP_IDLE: + jtag_burning.TMS_Wr(1); + cur_tap_state = TAP_DRSELECT; + break; + /* DR STATE Transistion */ + case TAP_DRSELECT: + if (state >= TAP_IRSELECT || state == TAP_RESET) { + jtag_burning.TMS_Wr(1); + cur_tap_state = TAP_IRSELECT; + } else { + jtag_burning.TMS_Wr(0); + cur_tap_state = TAP_DRCAPTURE; + } + break; + case TAP_DRCAPTURE: + if (state == TAP_DRSHIFT) { + jtag_burning.TMS_Wr(0); + cur_tap_state = TAP_DRSHIFT; + } else { + jtag_burning.TMS_Wr(1); + cur_tap_state = TAP_DREXIT1; + } + break; + case TAP_DRSHIFT: + jtag_burning.TMS_Wr(1); + cur_tap_state = TAP_DREXIT1; + break; + case TAP_DREXIT1: + if (state == TAP_DRPAUSE) { + jtag_burning.TMS_Wr(0); + cur_tap_state = TAP_DRPAUSE; + } else { + jtag_burning.TMS_Wr(1); + cur_tap_state = TAP_DRUPDATE; + } + break; + case TAP_DRPAUSE: + jtag_burning.TMS_Wr(1); + cur_tap_state = TAP_DREXIT2; + break; + case TAP_DREXIT2: + if (state == TAP_DRSHIFT) { + jtag_burning.TMS_Wr(0); + cur_tap_state = TAP_DRSHIFT; + } else { + jtag_burning.TMS_Wr(1); + cur_tap_state = TAP_DRUPDATE; + } + break; + case TAP_DRUPDATE: + if (state == TAP_IDLE) { + jtag_burning.TMS_Wr(0); + cur_tap_state = TAP_IDLE; + } else { + jtag_burning.TMS_Wr(1); + cur_tap_state = TAP_DRSELECT; + } + break; + /* IR STATE Transistion */ + case TAP_IRSELECT: + if (state == TAP_RESET) { + jtag_burning.TMS_Wr(1); + cur_tap_state = TAP_RESET; + } else { + jtag_burning.TMS_Wr(0); + cur_tap_state = TAP_IRCAPTURE; + } + break; + case TAP_IRCAPTURE: + if (state == TAP_IRSHIFT) { + jtag_burning.TMS_Wr(0); + cur_tap_state = TAP_IRSHIFT; + } else { + jtag_burning.TMS_Wr(1); + cur_tap_state = TAP_IREXIT1; + } + break; + case TAP_IRSHIFT: + jtag_burning.TMS_Wr(1); + cur_tap_state = TAP_IREXIT1; + break; + case TAP_IREXIT1: + if (state == TAP_IRPAUSE) { + jtag_burning.TMS_Wr(0); + cur_tap_state = TAP_IRPAUSE; + } else { + jtag_burning.TMS_Wr(1); + cur_tap_state = TAP_IRUPDATE; + } + break; + case TAP_IRPAUSE: + jtag_burning.TMS_Wr(1); + cur_tap_state = TAP_IREXIT2; + break; + case TAP_IREXIT2: + if (state == TAP_IRSHIFT) { + jtag_burning.TMS_Wr(0); + cur_tap_state = TAP_IRSHIFT; + } else { + jtag_burning.TMS_Wr(1); + cur_tap_state = TAP_IRUPDATE; + } + break; + case TAP_IRUPDATE: + if (state == TAP_IDLE) { + jtag_burning.TMS_Wr(0); + cur_tap_state = TAP_IDLE; + } else { + jtag_burning.TMS_Wr(1); + cur_tap_state = TAP_IRSELECT; + } + break; + default: + printf("Error: invalid tap sate.\n"); + return -1; + } + Anlogic_WritePulseTck(); + + if (++count > 10) { + printf("Error: Loop in Tap Transistion."); + return -1; + } + } + jtag_burning.TDI_Wr(0); +// printf("Anlogic_TapTransist 240 end...\n"); + return 0; +} + +/* Init function, set current tap state to reset */ +void Anlogic_Init(void) { + cur_tap_state = TAP_RESET; + Anlogic_TapTransist(TAP_RESET); +} + +/* set the tap state that deevice goes after sdr */ +void Anlogic_SetEndDRState(enum TAP_STATE end_st) { + end_dr_state = end_st; +#ifdef AJE_DEBUG + printf("ENDDR %s;\n", Anlogic_TapState2Str(end_st)); +#endif +} + +/* set the tap state that deevice goes after sir */ +void Anlogic_SetEndIRState(enum TAP_STATE end_st) { + end_ir_state = end_st; +#ifdef AJE_DEBUG + printf("ENDIR %s;\n", Anlogic_TapState2Str(end_st)); +#endif +} + +/* Send HIR/HDR/TIR/TDR data to device */ +void Anlogic_SendBypassData(unsigned int op_code) { + unsigned char* data = NULL; + unsigned int size = 0; + unsigned int index = 0; + unsigned int bit = 0; + + switch (op_code) { + case HIR: size = g_hir_size; data = g_hir_data; break; + case HDR: size = g_hdr_size; data = g_hdr_data; break; + case TIR: size = g_tir_size; data = g_tir_data; break; + case TDR: size = g_tdr_size; data = g_tdr_data; break; + default: break; + } + + /* no value set, use default */ + if (data == NULL) { + bit = (op_code == HIR || op_code == TIR) ? 1 : 0; + } + + for (index = 0; index < size-1; ++index) { + if (data != NULL) { + bit = Anlogic_GetBit(data, index); + } + jtag_burning.TDI_Wr(bit); + Anlogic_WritePulseTck(); + } + + bit = Anlogic_GetBit(data, index); + jtag_burning.TDI_Wr(bit); +} + +/* Send TDI data to device */ +int Anlogic_SendData(unsigned char* tdi_data, unsigned int bin_size, int cascade) { + unsigned int index = 0; + unsigned int bit = 0; + + for (index = 0; index < bin_size-1; ++index) { + bit = Anlogic_GetBit(tdi_data, index); + jtag_burning.TDI_Wr(bit); + Anlogic_WritePulseTck(); + } + + bit = Anlogic_GetBit(tdi_data, index); + jtag_burning.TDI_Wr(bit); + + if (cascade == 1) { + Anlogic_WritePulseTck(); + } + return 0; +} + +/* Send TDI data and read TDO, Verify */ +int Anlogic_ReadData(unsigned char* tdi_data, unsigned char* tdo_data, unsigned char* mask, unsigned int data_size, int cascade) { + unsigned int index = 0; + int tdi_bit = 0; + int tdo_bit = 0; + int mask_bit = 0; + + for (index = 0; index < data_size-1; ++index) { + tdi_bit = Anlogic_GetBit(tdi_data, index); + tdo_bit = Anlogic_GetBit(tdo_data, index); + mask_bit = Anlogic_GetBit(mask, index); + + if (mask_bit == 1 && tdo_bit != jtag_burning.TDO_RD()) { + return AJE_VERIFY_FAIL; + } + + jtag_burning.TDI_Wr(tdi_bit); + Anlogic_WritePulseTck(); + } + + tdi_bit = Anlogic_GetBit(tdi_data, index); + tdo_bit = Anlogic_GetBit(tdo_data, index); + mask_bit = Anlogic_GetBit(mask, index); + + if (mask_bit == 1 && tdo_bit != jtag_burning.TDO_RD()) { + return AJE_VERIFY_FAIL; + } + jtag_burning.TDI_Wr(tdi_bit); + + if (cascade == 1) { + Anlogic_WritePulseTck(); + } + + return AJE_OK; +} + +/* Send TDI Data and Save TDO */ +int Anlogic_SaveData(unsigned char* tdi_data, unsigned int data_size, unsigned char** tdo_data) { + unsigned int index = 0; + unsigned int tdi_bit = 0; + unsigned int tdo_bit = 0; + + for (index = 0; index < data_size-1; ++index) { + tdo_bit = jtag_burning.TDO_RD(); + Anlogic_SetBit(*tdo_data, index, tdo_bit); + tdi_bit = Anlogic_GetBit(tdi_data, index); + jtag_burning.TDI_Wr(tdi_bit); + Anlogic_WritePulseTck(); + } + tdo_bit = jtag_burning.TDO_RD(); + Anlogic_SetBit(*tdo_data, index, tdo_bit); + tdi_bit = Anlogic_GetBit(tdi_data, index); + jtag_burning.TDI_Wr(tdi_bit); + + return AJE_OK; +} + +/* Process SIR/SDR */ +int Anlogic_ProcessShiftCmd(unsigned int op_code, unsigned int cascade, unsigned int read, unsigned int data_size, + unsigned char* tdi_data, unsigned char* tdo_data, unsigned char* mask) { + int rtn_val = AJE_OK; + // process header data + switch (op_code) { + case SIR: + if (cascade != 1) { + Anlogic_TapTransist(TAP_IRSHIFT); + if (g_hir_size > 0) { + Anlogic_SendBypassData(HIR); + Anlogic_WritePulseTck(); + } + } + break; + case SDR: + if (cascade != 1) { + Anlogic_TapTransist(TAP_DRSHIFT); + if (g_hdr_size > 0) { + Anlogic_SendBypassData(HDR); + Anlogic_WritePulseTck(); + } + } + break; + default: + break; + } + + if (read == 1) { + rtn_val =Anlogic_SaveData(tdi_data, data_size, &tdo_data); + } else if (mask == NULL) { + rtn_val =Anlogic_SendData(tdi_data, data_size, cascade); + } else { + rtn_val =Anlogic_ReadData(tdi_data, tdo_data, mask, data_size, cascade); + } + + // process tailer data + switch (op_code) { + case SIR: + if (cascade != 1) { + if (g_tir_size > 0) { + Anlogic_WritePulseTck(); + Anlogic_SendBypassData(TIR); + } + Anlogic_TapTransist(end_ir_state); + } + break; + case SDR: + if (cascade != 1) { + if (g_tdr_size > 0) { + Anlogic_WritePulseTck(); + Anlogic_SendBypassData(TDR); + } + Anlogic_TapTransist(end_dr_state); + } + break; + default: + break; + } + + return rtn_val; +} + +/* process single sir command, do not use bypass data (hir/tir) */ +int Anlogic_ExeSirCommand(unsigned char command, int cur_lvl, int total_lvl) { + int rtn_val = AJE_OK; + unsigned char* tdi_data = NULL; + int id = 0; + Anlogic_TapTransist(TAP_IRSHIFT); + + tdi_data = (unsigned char*)calloc((total_lvl*8+1), sizeof(unsigned char)); + for(id = 0; id < total_lvl; ++id) { + if (id == (total_lvl - cur_lvl)) { + tdi_data[id] = Anlogic_ReverseChar(command); + } else { + tdi_data[id] = 0xFF; + } + } + rtn_val = Anlogic_SendData(tdi_data, total_lvl*8, 0 /*cascade*/); + Anlogic_TapTransist(end_ir_state); + + return rtn_val; +} + +/* process sdr command, do not use bypass data (hdr/tdr) */ +int Anlogic_ExeSdrCommand(unsigned int bit_size, int cur_lvl, int total_lvl, + unsigned char* tdi_data, unsigned char* tdo_data) { + int rtn_val = AJE_OK; + int head_num = total_lvl - cur_lvl; + int tailer_num = cur_lvl-1; + int id = 0; + unsigned int byte_size = (bit_size + 7)/8; + + Anlogic_TapTransist(TAP_DRSHIFT); + if (head_num > 0) { + for (id = 0; id < head_num; ++id) { + jtag_burning.TDI_Wr(0); + Anlogic_WritePulseTck(); + } + } + + if (tdi_data == NULL) { + tdi_data = (unsigned char*)calloc((byte_size+1), sizeof(unsigned char)); + } + + if (tdo_data == NULL) { + rtn_val = Anlogic_SendData(tdi_data, bit_size, 0 /*cascade*/); + } else { /* read and save tdo readback data */ + rtn_val = Anlogic_SaveData(tdi_data, bit_size, &tdo_data /*cascade*/); + } + + if (tailer_num > 0) { + for (id = 0; id < tailer_num; ++id) { + Anlogic_WritePulseTck(); + jtag_burning.TDI_Wr(0); + } + } + + Anlogic_TapTransist(end_dr_state); + return rtn_val; +} + +/* process runtest num tck */ +void Anlogic_ProcessRunTestTck(int num) { + volatile int i = 0; + jtag_burning.TDI_Wr(0); + jtag_burning.TMS_Wr(0); + for(i = 0; i < num; ++i) { + jtag_burning.TCK_Wr(1); + jtag_burning.TCK_Wr(0); + } +#ifdef AJE_DEBUG + printf("RUNTEST %d TCK;\n", num); +#endif +} + +void Anlogic_WritePulseTck(void) { + static unsigned int i = 0; + jtag_burning.TCK_Wr(1); + jtag_burning.TCK_Wr(0); +} diff --git a/motorcontroller/CMakeLists.txt b/motorcontroller/CMakeLists.txt new file mode 100644 index 0000000..00c6d03 --- /dev/null +++ b/motorcontroller/CMakeLists.txt @@ -0,0 +1,22 @@ +project(motorcontroller) +add_compile_options(-std=c++14) +#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -O2") +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -O2") + +aux_source_directory(${PROJECT_SOURCE_DIR} DIR_SRCS) +file(GLOB DIR_HEADS "${PROJECT_SOURCE_DIR}/*.h" "${PROJECT_SOURCE_DIR}/*.hpp") +set(DIR_SRCS ${DIR_SRCS} ${DIR_HEADS}) + +add_library(${PROJECT_NAME} STATIC ${DIR_SRCS}) + +target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR} + ${PROJECT_SOURCE_DIR}/../packages/common.pkg/include + ${PROJECT_SOURCE_DIR}/../display + ${PROJECT_SOURCE_DIR}/../keymonitor + ${PROJECT_SOURCE_DIR}/../applog + ${PROJECT_SOURCE_DIR}/../regs + ${PROJECT_SOURCE_DIR}/../scanner + ${PROJECT_SOURCE_DIR}/../capimage + ) + +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../bin) \ No newline at end of file diff --git a/motorcontroller/IState.h b/motorcontroller/IState.h new file mode 100644 index 0000000..93ec134 --- /dev/null +++ b/motorcontroller/IState.h @@ -0,0 +1,32 @@ +#pragma once +#include +#include +#include +#include +#include +#include "Statedef.h" +#include "BlockingQueue.h" +#include "LCDDisplay.h" +#include +class IState +{ +public: + IState(/* args */){ + display = std::make_unique(LCDDisplay::Language::Chinese); + } + virtual ~IState(){} + virtual void InitState(int state=0) =0; + virtual IState* OnState(StateInfo state) = 0; + virtual void SetBtnCall(std::function call) = 0; + std::string typeName = "FsmState"; + static void SetConfirmCall(std::function confirmcall) + { + m_confirmcall = confirmcall; + } +private: + static std::function m_confirmcall; +protected: + std::unique_ptr display; +}; + + diff --git a/motorcontroller/Menu.cpp b/motorcontroller/Menu.cpp new file mode 100644 index 0000000..92ad7a0 --- /dev/null +++ b/motorcontroller/Menu.cpp @@ -0,0 +1,51 @@ +#include "Menu.h" + +Menu::Menu(const char *const name,DisType dt) : name_(name) +{ + +} + +Menu::~Menu() +{ + std::cout << "Menu " << name_ << " destroyed" << std::endl; + for (auto &item : menu_items) + { + item.reset(); + } +} + +string Menu::get_name() +{ + return name_; +} + +int Menu::select() +{ + int ret = -1; + int choice; + int count = 0; + + for (auto &item : menu_items) + { + std::cout << item->get_name() << " : " << count++ << std::endl; + } + + if (choice >= 0 && choice <= menu_items.size()) + { + ret = menu_items[choice]->select(); + // if(!ret) + // g_call(); + } + + + count = 0; + choice = 0; + + return ret; +} + +void Menu::add_menu_item(unique_ptr menu_item) +{ + menu_items.push_back(std::move(menu_item)); +} + diff --git a/motorcontroller/Menu.h b/motorcontroller/Menu.h new file mode 100644 index 0000000..4e05781 --- /dev/null +++ b/motorcontroller/Menu.h @@ -0,0 +1,16 @@ +#pragma once +#include "Selectable.h" + +class Menu : public Selectable +{ +private: + std::string name_; + vector> menu_items; + +public: + Menu(const char *const name,DisType dt); + virtual ~Menu(); + virtual string get_name() override; + virtual int select() override; + void add_menu_item(unique_ptr menu_item); +}; \ No newline at end of file diff --git a/motorcontroller/MenuComponent.cpp b/motorcontroller/MenuComponent.cpp new file mode 100644 index 0000000..063cc7f --- /dev/null +++ b/motorcontroller/MenuComponent.cpp @@ -0,0 +1,157 @@ +#include "MenuComponent.h" +#include "Menu.h" +#include "Menu_Item.h" +#include "commondef.h" + +MenuComponent::MenuComponent() +{ + if (!m_menu.get()) + m_menu.reset(new Menu("Menu",DisType::Dis_Idel)); + current_distype = DisType::Dis_Idel; + cur_index = 0; +} + +MenuComponent::~MenuComponent() +{ + + if (m_menu.get()) + m_menu.reset(); +} + +void MenuComponent::initmenu() +{ + m_keytable.push_back({0,0,1,DisType::Dis_Idel}); //0 + m_keytable.push_back({8,2,0,DisType::Dis_Set_ClearPaperPass}); //1 + m_keytable.push_back({1,3,9,DisType::Dis_Set_PollPaperIntensity}); //2 +#ifdef G200 + m_keytable.push_back({2,4,13,DisType::Dis_Set_SleepMode}); //3 + m_keytable.push_back({3,6,22,DisType::Dis_Set_TrayPosition}); //4 + m_keytable.push_back({7,8,0,DisType::Dis_Set_Poweroff}); //5 + m_keytable.push_back({4,7,26,DisType::Dis_Set_ScanNum_Option}); //6 + m_keytable.push_back({6,5,33,DisType::Dis_Language}); //7 +#else + m_keytable.push_back({2,6,13,DisType::Dis_Set_SleepMode}); //3 + m_keytable.push_back({3,5,22,DisType::Dis_Set_TrayPosition}); //4 + m_keytable.push_back({7,8,0,DisType::Dis_Set_Poweroff}); //5 + m_keytable.push_back({3,7,26,DisType::Dis_Set_ScanNum_Option}); //6 + m_keytable.push_back({6,5,33,DisType::Dis_Language}); //7 +#endif + m_keytable.push_back({5,1,0,DisType::Dis_Set_Return}); //8 + + m_keytable.push_back({12,10,2,DisType::Dis_Set_PollPI_High}); //9 + m_keytable.push_back({9,11,2,DisType::Dis_Set_PollPI_Mid}); //10 + m_keytable.push_back({10,12,2,DisType::Dis_Set_PollPI_Low}); //11 + m_keytable.push_back({11,9,2,DisType::Dis_Set_Item_Return}); //12 + + m_keytable.push_back({21,14,3,DisType::Dis_Set_SleepMode_5M}); //13 + m_keytable.push_back({13,15,3,DisType::Dis_Set_SleepMode_10M}); //14 + m_keytable.push_back({14,16,3,DisType::Dis_Set_SleepMode_20M}); //15 + m_keytable.push_back({15,17,3,DisType::Dis_Set_SleepMode_30M}); //16 + m_keytable.push_back({16,18,3,DisType::Dis_Set_SleepMode_1H}); //17 + m_keytable.push_back({17,19,3,DisType::Dis_Set_SleepMode_2H}); //18 + m_keytable.push_back({18,20,3,DisType::Dis_Set_SleepMode_4H}); //19 + m_keytable.push_back({19,21,3,DisType::Dis_Set_SleepMode_NEVER}); //20 + m_keytable.push_back({20,13,3,DisType::Dis_Set_Item_Return}); //21 + + m_keytable.push_back({25,23,4,DisType::Dis_Set_TrayPosition_High}); //22 + m_keytable.push_back({22,24,4,DisType::Dis_Set_TrayPosition_Mid}); //23 + m_keytable.push_back({23,25,4,DisType::Dis_Set_TrayPosition_Low}); //24 + m_keytable.push_back({24,22,4,DisType::Dis_Set_Item_Return}); //25 + + m_keytable.push_back({29,27,6,DisType::Dis_Set_Get_Roller_ScanNum}); //26 + m_keytable.push_back({26,28,6,DisType::Dis_Set_Get_History_ScanNum}); //27 + m_keytable.push_back({27,29,30,DisType::Dis_Set_Clear_Roller_ScanNum}); //28 + m_keytable.push_back({28,26,6,DisType::Dis_Set_Item_Return}); //29 + //m_keytable.push_back({32,30,4,DisType::Dis_Set_Is_Sure});//29 + m_keytable.push_back({32,31,28,DisType::Dis_Set_YES}); //30 + m_keytable.push_back({30,32,28,DisType::Dis_Set_No}); //31 + m_keytable.push_back({31,30,28,DisType::Dis_Set_Item_Return}); //32 + + m_keytable.push_back({36,34,0,DisType::Dis_Language_Chinese}); //33 + m_keytable.push_back({33,35,0,DisType::Dis_Language_Chinese_Traditional}); //34 + m_keytable.push_back({34,36,0,DisType::Dis_Language_English}); //35 + m_keytable.push_back({35,33,0,DisType::Dis_Set_Item_Return}); //36 + + // if (m_menu.get()) + // { + + // unique_ptr menu_clearpass = std::make_unique("clearpass",DisType::Dis_Set_ClearPaperPass); + // m_menu->add_menu_item(std::move(menu_clearpass)); + + // unique_ptr submenu_feedstrength = std::make_unique("feedstrenth",DisType::Dis_Set_PollPaperIntensity); + // std::unique_ptr feeditemH = std::make_unique("feedhigh",DisType::Dis_Set_PollPI_High); + // std::unique_ptr feeditemM = std::make_unique("feedmid",DisType::Dis_Set_PollPI_Mid); + // std::unique_ptr feeditemL = std::make_unique("feedlow",DisType::Dis_Set_PollPI_Low); + // submenu_feedstrength->add_menu_item(std::move(feeditemH)); + // submenu_feedstrength->add_menu_item(std::move(feeditemM)); + // submenu_feedstrength->add_menu_item(std::move(feeditemL)); + // m_menu->add_menu_item(std::move(submenu_feedstrength)); + + // unique_ptr submenu_sleep = std::make_unique("sleepset",DisType::Dis_Set_SleepMode); + // std::unique_ptr sleep30 = std::make_unique("30min",DisType::Dis_Set_SleepMode_30M); + // std::unique_ptr sleep60 = std::make_unique("60min",DisType::Dis_Set_SleepMode_1H); + // std::unique_ptr sleep120 = std::make_unique("120min",DisType::Dis_Set_SleepMode_2H); + // std::unique_ptr sleepnever = std::make_unique("never",DisType::Dis_Set_SleepMode_NEVER); + // submenu_sleep->add_menu_item(std::move(sleep30)); + // submenu_sleep->add_menu_item(std::move(sleep60)); + // submenu_sleep->add_menu_item(std::move(sleep120)); + // submenu_sleep->add_menu_item(std::move(sleepnever)); + // m_menu->add_menu_item(std::move(submenu_sleep)); + + // unique_ptr submenu_poweroff = std::make_unique("poweroff",DisType::Dis_Set_Poweroff); + // m_menu->add_menu_item(std::move(submenu_poweroff)); + // } +} + +void MenuComponent::select() +{ + if (m_menu.get()) + { + m_menu->select(); + } +} + +void MenuComponent::option(int key) +{ + switch (key) + { +#ifdef G200 + case 85: //Key_Menu + cur_index = m_keytable[cur_index].enter; + break; + case 86: //Key_Left + cur_index = m_keytable[cur_index].up; + break; + case 76: //Key_Right + cur_index = m_keytable[cur_index].down; + break; +#else + case 76: //Key_Menu + cur_index = m_keytable[cur_index].enter; + break; + case 77: //Key_Right + cur_index = m_keytable[cur_index].down; + break; +#endif + default: + break; + } +} + +DisType MenuComponent::getcurtype() +{ + return m_keytable[cur_index].m_type; +} + +void MenuComponent::setcurindex(int x) +{ + if(x < 0 || x >= m_keytable.size()) + return ; + cur_index = x; + printf("\n MenuComponent setcurindex %d",x); +} + +int MenuComponent::getcurindex() +{ + return cur_index; +} \ No newline at end of file diff --git a/motorcontroller/MenuComponent.h b/motorcontroller/MenuComponent.h new file mode 100644 index 0000000..606d702 --- /dev/null +++ b/motorcontroller/MenuComponent.h @@ -0,0 +1,33 @@ +#pragma once +#include +#include "Displaydef.h" +class Menu; +class Menu_Item; + +struct keypause{ + int up; + int down; + int enter; + DisType m_type; +}; + +class MenuComponent +{ +private: + /* data */ +public: + MenuComponent(/* args */); + ~MenuComponent(); + void initmenu(); + void select(); + void option(int key); + DisType getcurtype(); + void setcurindex(int x); + int getcurindex(); +private: + + std::shared_ptr m_menu; + DisType current_distype; + std::vector m_keytable; + int cur_index; +}; diff --git a/motorcontroller/Menu_Item.cpp b/motorcontroller/Menu_Item.cpp new file mode 100644 index 0000000..0818e0a --- /dev/null +++ b/motorcontroller/Menu_Item.cpp @@ -0,0 +1,24 @@ +#include "Menu_Item.h" + +Menu_Item::Menu_Item(const char *const name,DisType dt) : name_{name} +{ + +} + +Menu_Item::~Menu_Item() +{ + std::cout<<"Menu_Item Name "<(&MotorController::runloop,this); + auto keycall=[&](int key) + { + auto iter = m_keystats.find((HgBtn)key); + if(iter!=m_keystats.end()) + { + m_msg.Put(iter->second); + } + }; + m_keyMinitor= make_shared(keycall); +} + +MotorController::~MotorController() +{ + + if(m_threadmsgloop.get() && m_threadmsgloop->joinable()) + { + m_bloop = false; + m_threadmsgloop->join(); + m_threadmsgloop.reset(); + } + LOG_TRACE("MotorController ~ctor exit \n"); +} + +void MotorController::runloop() +{ + m_bloop = true; + IState* mtstate = StateManager::GetState(); + m_msg.Put({HGScannerStatus::Mode_Idel,0}); + while (m_bloop) + { + auto msg = m_msg.Take(); + printf("\n msg status = %d ",msg.status); + if(msg.status == HGScannerStatus::Mode_Scan_Start) + mtstate = StateManager::GetState(); + if(msg.status == HGScannerStatus::Mode_Count) + mtstate = StateManager::GetState(msg.value); + if(msg.status == HGScannerStatus::Mode_Set_Key_Manual) + mtstate = StateManager::GetState(); + if(msg.status >= HGScannerStatus::Mode_Error_Jam && msg.status <= HGScannerStatus::Mode_Error_DogEar || msg.status == HGScannerStatus::Mode_Error_FeedError) + mtstate = StateManager::GetState((int)msg.status); + if(msg.status == HGScannerStatus::Mode_Idel) + mtstate = StateManager::GetState(); + //mtstate = mtstate->OnState(msg); + } +} + +void MotorController::PutMsg(StateInfo mode) +{ + m_msg.Put(mode); +} + + +void MotorController::SendMsg() +{ + +} + + diff --git a/motorcontroller/MotorController.h b/motorcontroller/MotorController.h new file mode 100644 index 0000000..48b6864 --- /dev/null +++ b/motorcontroller/MotorController.h @@ -0,0 +1,36 @@ +#pragma once +#include "StateManager.h" +#include "IState.h" +#include "BlockingQueue.h" +#include "keymonitor.h" + +using HgBtn = KeyMonitor::HGKey; + +class MotorController +{ +public: + MotorController(/* args */); + ~MotorController(); + void PutMsg(StateInfo mode); +private: + void runloop(); + void SendMsg(); + void procmsg(); + +private: + std::atomic m_bloop; + BlockingQueue m_msg; + std::shared_ptr m_threadmsgloop; + std::shared_ptr m_keyMinitor; + const std::map m_keystats={ + {HgBtn::Key_Enter,{HGScannerStatus::Mode_Set_Key_Enter,0}}, + {HgBtn::Key_Cancle,{HGScannerStatus::Mode_Set_Key_Back,0}}, + {HgBtn::Key_Count,{HGScannerStatus::Mode_Set_Key_Count,0}}, + {HgBtn::Key_Handle,{HGScannerStatus::Mode_Set_HandMode,0}}, + {HgBtn::Key_DoubleFeed,{HGScannerStatus::Mode_Set_Key_EnDoubleFeed,0}}, + {HgBtn::Key_Left,{HGScannerStatus::Mode_Set_Key_Left,0}}, + {HgBtn::Key_Menu,{HGScannerStatus::Mode_Set_Key_Manual,0}}, + {HgBtn::Key_Right,{HGScannerStatus::Mode_Set_Key_Right,0}}, + {HgBtn::Key_Clear,{HGScannerStatus::Mode_Set_Key_ClearCount,0}} + }; +}; diff --git a/motorcontroller/MotorboardParam.cpp b/motorcontroller/MotorboardParam.cpp new file mode 100644 index 0000000..40337f4 --- /dev/null +++ b/motorcontroller/MotorboardParam.cpp @@ -0,0 +1,176 @@ +#include "MotorboardParam.h" +#include +#include +#include +#include "commondef.h" +#include +MotorboardParam::MotorboardParam(/* args */) +{ +} + +MotorboardParam::~MotorboardParam() +{ +} + +int MotorboardParam::GetOrSetEnableAutomaticControlFeedMode(bool isget,int value){ + std::lock_guard lc(m_setlock); + if(isget) + { + auto js = getjson(); + if(!js[automaticcontrol_feedmode].is_null() && js[automaticcontrol_feedmode].is_number()) + return js[automaticcontrol_feedmode]; + else{ + printf("\nread motorboardparam error : feedmode!!! "); + return 1; + } + } + else{ + auto js = getjson(); + if(!js[automaticcontrol_feedmode].is_null() && js[automaticcontrol_feedmode].is_number()) + { + js[automaticcontrol_feedmode] = value; + savejson(js); + } + return 0; + } +} + +int MotorboardParam::GetOrSetFeedMode(bool isget,int value){ + std::lock_guard lc(m_setlock); + if(isget) + { + auto js = getjson(); + if(!js[feed_mode].is_null() && js[feed_mode].is_number()) + return js[feed_mode]; + else{ + printf("\nread motorboardparam error : feedmode!!! "); + return 1; + } + } + else{ + if(value < 0 || value > 2) + return 0; + auto js = getjson(); + if(!js[feed_mode].is_null() && js[feed_mode].is_number()) + { + js[feed_mode] = value; + savejson(js); + } + return 0; + } +} + +int MotorboardParam::GetOrSetTrayPosition(bool isget,int value){ + std::lock_guard lc(m_setlock); + if(isget) + { + auto js = getjson(); + if(!js[trayposition].is_null() && js[trayposition].is_number()) + return js[trayposition]; + else{ + printf("\nread motorboardparam error : feedmode!!! "); + return 0; + } + } + else{ + if(value < 0 || value > 2) + return 0; + auto js = getjson(); + if(!js[trayposition].is_null() && js[trayposition].is_number()) + { + js[trayposition] = value; + savejson(js); + } + return 0; + } +} + +void MotorboardParam::savejson(json js){ + remove(ParamPath.c_str()); + std::ofstream o(ParamPath); + o << std::setw(4) << js < lc(m_setlock); + json tmp = getjson(); + return json2struct(tmp); +} + +void MotorboardParam::SaveParam(MotorboardParam::MBParam param){ + std::lock_guard lc(m_setlock); + auto tmp = struct2json(param); + savejson(tmp); +} + +json MotorboardParam::getdefaultjson(){ + json m_json; + m_json[feed_mode] = 1; //0 low 1 mid 2 high + m_json[automaticcontrol_feedmode] = 0; + m_json[automaticcontrolfeedmode_threshold] = 0.5; + m_json[trayposition] = 0; + return m_json; +} + +json MotorboardParam::struct2json(MotorboardParam::MBParam param){ + json js; + js[feed_mode] = param.feedmode; //0 low 1 mid 2 high + js[automaticcontrol_feedmode] = param.automaticcontrolfeedmode; + js[automaticcontrolfeedmode_threshold] = param.automaticcontrolfeedmode_threshold; + js[trayposition] = param.trayposition; + return js; +} + +MotorboardParam::MBParam MotorboardParam::json2struct(json js){ + MotorboardParam::MBParam param{0}; + if(js[feed_mode].is_number()) + param.feedmode = js[feed_mode]; + else + param.feedmode = 1; + if(js[automaticcontrol_feedmode].is_number()) + param.automaticcontrolfeedmode = js[automaticcontrol_feedmode]; + else + param.automaticcontrolfeedmode = 0; + if(js[automaticcontrolfeedmode_threshold].is_number_float()) + param.automaticcontrolfeedmode_threshold = js[automaticcontrolfeedmode_threshold]; + else + param.automaticcontrolfeedmode_threshold = 0.5 ; + if(js[trayposition].is_number()) + param.trayposition = js[trayposition]; + else + param.trayposition = 0; + return param; +} + +json MotorboardParam::getjson(){ + if(access(JSON_CORRECTDIR_PATH,0) == -1) + { + auto ret = mkdir(JSON_CORRECTDIR_PATH, 0777); + if (ret != 0) + { + printf("make dir failed .path=%s \n", JSON_CORRECTDIR_PATH); + } + } + if (access(ParamPath.c_str(), F_OK) != 0) + { + auto cfs = getdefaultjson(); + savejson(cfs); + return cfs; + } + std::ifstream i(ParamPath); + auto pos = i.tellg(); + i.seekg(0, std::ios::end); + if (i.tellg() <= 2) + { + auto cfs = getdefaultjson(); + savejson(cfs); + return cfs; + } + i.seekg(pos); + json m_json; + i >> m_json; + i.close(); + return m_json; +} + diff --git a/motorcontroller/MotorboardParam.h b/motorcontroller/MotorboardParam.h new file mode 100644 index 0000000..89374bf --- /dev/null +++ b/motorcontroller/MotorboardParam.h @@ -0,0 +1,39 @@ +#pragma once +#include +#include +#include +using json = nlohmann::json; + + +class MotorboardParam +{ +private: + const std::string ParamPath ="/usr/local/huago/motorboardparam.json"; + const std::string feed_mode = "feedmode"; + const std::string automaticcontrol_feedmode = "automaticcontrolfeedmode"; + const std::string automaticcontrolfeedmode_threshold = "automaticcontrolfeedmodethreshold"; + const std::string trayposition = "trayposition"; +public: + struct MBParam + { + int feedmode; + int automaticcontrolfeedmode; + float automaticcontrolfeedmode_threshold; + int trayposition; + }; + MotorboardParam(/* args */); + ~MotorboardParam(); + MotorboardParam::MBParam GetParam(); + void SaveParam(MotorboardParam::MBParam param); + int GetOrSetTrayPosition(bool isget,int value); + int GetOrSetFeedMode(bool isget,int value); + int GetOrSetEnableAutomaticControlFeedMode(bool isget,int value); +private: + void savejson(json js); + json struct2json(MotorboardParam::MBParam param); + MotorboardParam::MBParam json2struct(json js); + json getjson(); + json getdefaultjson(); + std::mutex m_setlock; +}; + diff --git a/motorcontroller/Mt_Count.cpp b/motorcontroller/Mt_Count.cpp new file mode 100644 index 0000000..ab206f1 --- /dev/null +++ b/motorcontroller/Mt_Count.cpp @@ -0,0 +1,26 @@ +#include "Mt_Count.h" + +Mt_Count::Mt_Count() +{ +} + +Mt_Count::~Mt_Count() +{ +} + +void Mt_Count::InitState(int state) +{ + printf("\nDis_Scan_Page %d",state); + display->DisplayState(DisType::Dis_Scan_Page,state,ClearScreen::BOT); +} + +IState *Mt_Count::OnState(StateInfo mode) +{ + return nullptr; +} + + +void Mt_Count::SetBtnCall(std::function call) +{ + +} \ No newline at end of file diff --git a/motorcontroller/Mt_Count.h b/motorcontroller/Mt_Count.h new file mode 100644 index 0000000..2ae3036 --- /dev/null +++ b/motorcontroller/Mt_Count.h @@ -0,0 +1,12 @@ +#pragma once +#include "IState.h" + +class Mt_Count : public IState +{ +public: + Mt_Count(/* args */); + virtual ~Mt_Count(); + virtual void InitState(int state=0) override; + virtual IState* OnState(StateInfo mode) override; + virtual void SetBtnCall(std::function call) override; +}; diff --git a/motorcontroller/Mt_Error.cpp b/motorcontroller/Mt_Error.cpp new file mode 100644 index 0000000..24bf43a --- /dev/null +++ b/motorcontroller/Mt_Error.cpp @@ -0,0 +1,42 @@ +#include "Mt_Error.h" + +Mt_Error::Mt_Error() +{ + +} + +Mt_Error::~Mt_Error() +{ + +} + +void Mt_Error::InitState(int state) +{ + if(state == (int)HGScannerStatus::Mode_Error_Jam) + display->DisplayState(DisType::Dis_Err_JamIn,0,ClearScreen::All); + if(state == (int)HGScannerStatus::Mode_Error_DoublePaper) + display->DisplayState(DisType::Dis_Err_DoubleFeed,0,ClearScreen::All); + if(state == (int)HGScannerStatus::Mode_Error_Screw) + display->DisplayState(DisType::Dis_Err_PaperScrew,0,ClearScreen::All); + if(state == (int)HGScannerStatus::Mode_Error_Stable) + display->DisplayState(DisType::Dis_Err_Stable,0,ClearScreen::All); + if(state == (int)HGScannerStatus::Mode_Error_AquireTimeout) + display->DisplayState(DisType::Dis_Err_AqrImgTimeout,0,ClearScreen::All); + if(state == (int)HGScannerStatus::Mode_Error_CoverOpen) + display->DisplayState(DisType::Dis_Err_CoverOpen,0,ClearScreen::All); + if(state == (int)HGScannerStatus::Mode_Error_FeedError) + display->DisplayState(DisType::Dis_Err_FeedError,0,ClearScreen::All); + if(state == (int)HGScannerStatus::Mode_Error_NoFeed) + display->DisplayState(DisType::Dis_Err_NoPaper,0,ClearScreen::All); +} + +IState* Mt_Error::OnState(StateInfo mode) +{ + return nullptr; +} + + +void Mt_Error::SetBtnCall(std::function call) +{ + +} \ No newline at end of file diff --git a/motorcontroller/Mt_Error.h b/motorcontroller/Mt_Error.h new file mode 100644 index 0000000..e895dc1 --- /dev/null +++ b/motorcontroller/Mt_Error.h @@ -0,0 +1,12 @@ +#pragma once +#include "IState.h" + +class Mt_Error : public IState +{ +public: + Mt_Error(/* args */); + virtual ~Mt_Error(); + virtual void InitState(int state=0) override; + virtual IState* OnState(StateInfo mode) override; + virtual void SetBtnCall(std::function call) override; +}; \ No newline at end of file diff --git a/motorcontroller/Mt_Idel.cpp b/motorcontroller/Mt_Idel.cpp new file mode 100644 index 0000000..47b4165 --- /dev/null +++ b/motorcontroller/Mt_Idel.cpp @@ -0,0 +1,41 @@ +#include "Mt_Idel.h" +#include "Mt_Scan.h" +#include "Mt_Set.h" +#include "Mt_Count.h" +#include "Mt_Error.h" +#include "StateManager.h" + +Mt_Idel::Mt_Idel() +{ + +} + +Mt_Idel::~Mt_Idel() +{ + +} + +void Mt_Idel::InitState(int state) +{ + // display->DisplayState(DisType::Dis_Welcome,0); + // std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + display->DisplayState(DisType::Dis_Idel,0,ClearScreen::All); +} + +IState* Mt_Idel::OnState(StateInfo mode) +{ + if(mode.status == HGScannerStatus::Mode_Scan_Start) + return StateManager::GetState(); + if(mode.status == HGScannerStatus::Mode_Count) + return StateManager::GetState(); + if(mode.status == HGScannerStatus::Mode_Set_Key_Manual) + return StateManager::GetState(); + if(mode.status >= HGScannerStatus::Mode_Error_Jam && mode.status <= HGScannerStatus::Mode_Error_DogEar) + return StateManager::GetState(); + return this; +} + +void Mt_Idel::SetBtnCall(std::function call) +{ + +} \ No newline at end of file diff --git a/motorcontroller/Mt_Idel.h b/motorcontroller/Mt_Idel.h new file mode 100644 index 0000000..dbb4106 --- /dev/null +++ b/motorcontroller/Mt_Idel.h @@ -0,0 +1,14 @@ +#pragma once +#include "IState.h" + +class Mt_Idel: public IState +{ +private: + /* data */ +public: + Mt_Idel(/* args */); + virtual ~Mt_Idel(); + virtual void InitState(int state=0) override; + virtual IState* OnState(StateInfo mode) override; + virtual void SetBtnCall(std::function call) override; +}; diff --git a/motorcontroller/Mt_Scan.cpp b/motorcontroller/Mt_Scan.cpp new file mode 100644 index 0000000..a39d1b6 --- /dev/null +++ b/motorcontroller/Mt_Scan.cpp @@ -0,0 +1,27 @@ +#include "Mt_Scan.h" + +Mt_Scan::Mt_Scan() +{ + +} + +Mt_Scan::~Mt_Scan() +{ + +} + +void Mt_Scan::InitState(int state) +{ + display->DisplayState(DisType::Dis_Scan,0,ClearScreen::All); +} + +IState* Mt_Scan::OnState(StateInfo mode) +{ + return nullptr; +} + + +void Mt_Scan::SetBtnCall(std::function call) +{ + +} \ No newline at end of file diff --git a/motorcontroller/Mt_Scan.h b/motorcontroller/Mt_Scan.h new file mode 100644 index 0000000..1b42165 --- /dev/null +++ b/motorcontroller/Mt_Scan.h @@ -0,0 +1,12 @@ +#pragma once +#include "IState.h" + +class Mt_Scan: public IState +{ +public: + Mt_Scan(/* args */); + virtual ~Mt_Scan(); + virtual void InitState(int state=0) override; + virtual IState* OnState(StateInfo mode) override; + virtual void SetBtnCall(std::function call) override; +}; \ No newline at end of file diff --git a/motorcontroller/Mt_Set.cpp b/motorcontroller/Mt_Set.cpp new file mode 100644 index 0000000..be5c6d8 --- /dev/null +++ b/motorcontroller/Mt_Set.cpp @@ -0,0 +1,42 @@ +#include "Mt_Set.h" +#include "Mt_Idel.h" +#include "Mt_Scan.h" +#include "Mt_Set.h" +#include "Mt_Count.h" +#include "StateManager.h" +#include "MenuComponent.h" + +Mt_Set::Mt_Set() +{ + if(!m_menu.get()) + m_menu.reset(new MenuComponent()); +} + +Mt_Set::~Mt_Set() +{ +} + +void Mt_Set::InitState(int state) +{ + m_menu->initmenu(); + display->DisplayState(DisType::Dis_Set_ClearPaperPass, 0,ClearScreen::All); +} + +IState *Mt_Set::OnState(StateInfo mode) +{ + if (mode.status >= HGScannerStatus::Mode_Set_Key_ClearCount && + mode.status <= HGScannerStatus::Mode_Set_Key_Enter) + { + + return this; + } + else{ + + } + +} + +void Mt_Set::SetBtnCall(std::function call) +{ + m_call = call; +} \ No newline at end of file diff --git a/motorcontroller/Mt_Set.h b/motorcontroller/Mt_Set.h new file mode 100644 index 0000000..63f0572 --- /dev/null +++ b/motorcontroller/Mt_Set.h @@ -0,0 +1,20 @@ +#pragma once +#include "IState.h" + +class MenuComponent; + +class Mt_Set : public IState +{ +private: + /* data */ +public: + Mt_Set(/* args */); + virtual ~Mt_Set(); + virtual void InitState(int state=0) override; + virtual IState* OnState(StateInfo mode) override; + virtual void SetBtnCall(std::function call) override; +private: + std::function m_call; + std::shared_ptr m_menu; +}; + diff --git a/motorcontroller/Mt_Welcome.cpp b/motorcontroller/Mt_Welcome.cpp new file mode 100644 index 0000000..5b881c7 --- /dev/null +++ b/motorcontroller/Mt_Welcome.cpp @@ -0,0 +1,27 @@ +#include "Mt_Welcome.h" +#include "StateManager.h" +#include "Mt_Idel.h" + +Mt_Welcome::Mt_Welcome() +{ +} + +Mt_Welcome::~Mt_Welcome() +{ +} + +void Mt_Welcome::InitState(int state) +{ + display->DisplayState(DisType::Dis_Welcome,0,ClearScreen::All); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + display->DisplayState(DisType::Dis_Init,0,ClearScreen::All); +} + +IState *Mt_Welcome::OnState(StateInfo mode) +{ + return StateManager::GetState(); +} + +void Mt_Welcome::SetBtnCall(std::function call) +{ +} \ No newline at end of file diff --git a/motorcontroller/Mt_Welcome.h b/motorcontroller/Mt_Welcome.h new file mode 100644 index 0000000..adbda28 --- /dev/null +++ b/motorcontroller/Mt_Welcome.h @@ -0,0 +1,14 @@ +#pragma once +#include "IState.h" + +class Mt_Welcome:public IState +{ +private: + /* data */ +public: + Mt_Welcome(/* args */); + ~Mt_Welcome(); + virtual void InitState(int state=0) override; + virtual IState* OnState(StateInfo mode) override; + virtual void SetBtnCall(std::function call) override; +}; diff --git a/motorcontroller/Selectable.h b/motorcontroller/Selectable.h new file mode 100644 index 0000000..2a55c2e --- /dev/null +++ b/motorcontroller/Selectable.h @@ -0,0 +1,54 @@ +#pragma once +#include +#include +#include +#include +#include +#include "Displaydef.h" + +using namespace std; + +class Selectable +{ +public: + enum class SettingType + { + Set_ClearPass = 1, + Set_Sleep, + Set_FeedStrength, + Set_Poweroff, + Set_ClearCount, + Set_CountMode, + Set_DoubleEn + }; + + enum class SleepTime + { + Sleep_15min = 1, + Sleep_30min, + Sleep_60min, + Sleep_120min, + Sleep_never + }; + + enum class MtStrength + { + Strength_Low = 1, + Strength_Mid, + Strength_High + }; + + + + Selectable() {} + virtual ~Selectable() {} + virtual string get_name() = 0; + virtual int select() = 0; + void setconfirmcall(std::function confirmcall) + { + g_call = confirmcall; + } + +protected: + std::function g_call; +}; diff --git a/motorcontroller/StateControl.cpp b/motorcontroller/StateControl.cpp new file mode 100644 index 0000000..c4dc0a3 --- /dev/null +++ b/motorcontroller/StateControl.cpp @@ -0,0 +1,473 @@ +#include "MenuComponent.h" +#include "DisplayCenter.h" +#include "keymonitor.h" +#include "regsaccess.h" +#include "StateControl.h" +#include "wakeup.hpp" +#include "MotorboardParam.h" +#include "jsonconfig.h" +#include "deviceconfig.h" + +StateControl::StateControl(std::shared_ptr m_regsAccess,std::shared_ptr wake):m_regs(m_regsAccess),m_wake(wake), +is_runing(false),is_cover_open(false),is_autopaper(false),en_autopaper_key(false){ + m_menu.reset(new MenuComponent()); + m_menu->initmenu(); + m_discenter.reset(new DisplayCenter()); + uint reg6value = 0; + m_regs->read(0x6,reg6value); + auto reg = *(reg6*)®6value; + MotorboardParam::MBParam mb_param = MotorboardParam().GetParam(); + reg.param.work_mode = 0; + reg.param.lift_init_set = mb_param.trayposition; + switch (mb_param.feedmode) + { + case 0: + reg.param.func_feed_low =1; + reg.param.func_feed_high = reg.param.func_feed_mid = 0; + break; + case 1: + reg.param.func_feed_mid =1; + reg.param.func_feed_high = reg.param.func_feed_low = 0; + break; + case 2: + reg.param.func_feed_high =1; + reg.param.func_feed_mid = reg.param.func_feed_low = 0; + break; + default: + reg.param.func_feed_mid =1; + reg.param.func_feed_high = reg.param.func_feed_low = 0; + break; + } + m_regs->write(0x6,reg.value); + auto keycall = [&](int keyvalye) + { + if(wake.get()) + wake->resettime(); + std::cout << "keycallback keyvalue= " << keyvalye << std::endl; + uint value = 0; + auto key = (KeyMonitor::HGKey)(keyvalye); + if((is_autopaper && (!en_autopaper_key)) || (is_autopaper && en_autopaper_key && (key!=KeyMonitor::HGKey::Key_Cancle))) + return ; + if((is_runing && key!=KeyMonitor::HGKey::Key_Cancle)||is_cover_open) + return ; + value = 0; + switch (key) + { + case KeyMonitor::HGKey::Key_Enter: + { + m_regs->read(0x6,value); + auto reg = *(reg6*)&value; + printf("\n reg.param.work_mode = %d ",reg.param.work_mode); + if(reg.param.work_mode !=1) + break; + m_regs->read(0x02,value); + if(!(value&0x10000)) + { + PutMsg(DisType::Dis_Err_NoPaper,0,ClearScreen::All); + break; + } + setrunstate(true); + reg.param.func_encount = 1; + reg.param.motor_disable = false; + m_regs->write(0x6,reg.value); + reg.param.func_encount = 0; + m_regs->write(0x6,reg.value); + if(m_wake.get()) + m_wake->setsleepfalg(true); + printf("\n m_menu->getcurindex() %d",m_menu->getcurindex()); + m_discenter->PutMsg(DisType::Dis_Set_Count,0,ClearScreen::All); + PutMsg(DisType::Dis_Scan_Page,getpapercount(),ClearScreen::BOT); + break; + } + case KeyMonitor::HGKey::Key_Cancle: + { + reg6 func = {0}; + m_regs->read(0x06,func.value); + m_regs->read(0x0a,value); + m_menu->setcurindex(0); + m_discenter->PutMsg(func.param.work_mode == 0? (is_runing?DisType::Dis_Scan : DisType::Dis_Idel):(func.param.work_mode == 1?DisType::Dis_Set_Count:DisType::Dis_HandMode),0,ClearScreen::All); + if(m_discenter->getcurdistype() == DisType::Dis_Scan || m_discenter->getcurdistype() == DisType::Dis_Set_Count) + { + PutMsg(DisType::Dis_Scan_Page,getpapercount(),ClearScreen::BOT); + } + autopaperstop?autopaperstop():void(); + if(!is_runing) + break; + func.param.key_stop_enable = true; + m_regs->write(0x06,func.value); + func.param.key_stop_enable = false; + func.param.motor_disable = value > 0 ? true:false; + m_regs->write(0x06,func.value); + if(m_wake.get()) + m_wake->setsleepfalg(false); + //is_runing = false; + // if(int(m_discenter->getcurdistype()) > 4 && int(m_discenter->getcurdistype())<14) + // m_discenter->PutMsg(DisType::Dis_Idel,0,ClearScreen::All); + break; + } + case KeyMonitor::HGKey::Key_Count: + { + if(m_discenter->getcurdistype() != DisType::Dis_Idel) + { + m_menu->setcurindex(0); + m_discenter->PutMsg(DisType::Dis_Idel, 0,ClearScreen::All); + } + m_regs->read(0x6,value); + auto reg = *(reg6*)&value; + printf("\n reg.param.work_mode = %d ",reg.param.work_mode); + if(reg.param.work_mode!= 0 && reg.param.work_mode !=1) + break; + if(reg.param.work_mode == 1){ + reg.param.work_mode = 0; + m_keymonitor->setled(KeyMonitor::HGLed::Led_Count_close); + } + else{ + reg.param.work_mode = 1; + clearcount(); + getpapercount(); + PutMsg(DisType::Dis_Scan_Page,getpapercount(),ClearScreen::BOT); + m_keymonitor->setled(KeyMonitor::HGLed::Led_Count_open); + } + m_regs->write(0x6,reg.value); + m_discenter->PutMsg(reg.param.work_mode == 1?DisType::Dis_Set_Count:DisType::Dis_Idel,0, reg.param.work_mode == 1?ClearScreen::TOP : ClearScreen::All); + break; + } + // case KeyMonitor::HGKey::Key_Handle: + // { + // m_regs->read(0x6,value); + // auto reg = *(reg6*)&value; + // printf("\n reg.param.work_mode = %d ",reg.param.work_mode); + // if(reg.param.work_mode!= 0 && reg.param.work_mode !=5) + // break; + // if(reg.param.work_mode == 5){ + // reg.param.work_mode = 0; + // m_keymonitor->setled(KeyMonitor::HGLed::Led_Handle_close); + // } + // else{ + // reg.param.work_mode = 5; + // m_keymonitor->setled(KeyMonitor::HGLed::Led_Handle_open); + // } + // m_regs->write(0x6,reg.value); + // m_discenter->PutMsg(reg.param.work_mode == 5?DisType::Dis_HandMode:DisType::Dis_Idel,0,ClearScreen::All); + // break; + // } + case KeyMonitor::HGKey::Key_DoubleFeed: + { + m_regs->read(0x6,value); + auto reg = *(reg6*)&value; + printf("\n reg.param.key_endouble_feed =%d ",reg.param.key_endouble_feed); + if(reg.param.key_endouble_feed){ + reg.param.key_endouble_feed = 0; + m_keymonitor->setled(KeyMonitor::HGLed::Led_DoubleFeed_close); + } + else{ + reg.param.key_endouble_feed = 1; + m_keymonitor->setled(KeyMonitor::HGLed::Led_DoubleFeed_open); + } + m_regs->write(0x6,reg.value); + break; + } + case KeyMonitor::HGKey::Key_Left: + case KeyMonitor::HGKey::Key_Menu: + case KeyMonitor::HGKey::Key_Right: + { + m_regs->read(0x6,value); + auto reg = *(reg6*)&value; + if(reg.param.work_mode != 0) + break; + if(keyvalye == (int)KeyMonitor::HGKey::Key_Menu) + menu_func(m_menu->getcurtype()); + printf("\n m_menu->getcurindex() %d",m_menu->getcurindex()); + printf("\n mb 6 value%d",reg.value); + if(keyvalye == (int)KeyMonitor::HGKey::Key_Menu && m_menu->getcurindex() == 2) //2 分纸强度项 + m_menu->setcurindex(reg.param.func_feed_high?9:(reg.param.func_feed_mid?10:11)); //8分纸强度高 9 分纸强度中 10 分纸强度弱 + else if(keyvalye == (int)KeyMonitor::HGKey::Key_Menu && m_menu->getcurindex() == 4) //2 分纸强度项 + m_menu->setcurindex(reg.param.lift_init_set == 2?22:(reg.param.lift_init_set == 1?23:24)); //7 分纸强度高 8 分纸强度中 9 分纸强度弱 + else + m_menu->option(keyvalye); + if(m_menu->getcurindex() >=26 && m_menu->getcurindex()<= 27) + { + m_discenter->PutMsg(m_menu->getcurtype(), + m_menu->getcurindex() ==26 ? Get_static_jsonconfig().getmemparam().RollerNum : Get_static_jsonconfig().getmemparam().TotalScanned,ClearScreen::BOT); + } + else if(m_menu->getcurindex() >=9 && m_menu->getcurindex()<= 36) + m_discenter->PutMsg(m_menu->getcurtype(),0,ClearScreen::BOT); + else + m_discenter->PutMsg(m_menu->getcurtype(),0,ClearScreen::All); + break; + } + case KeyMonitor::HGKey::Key_Clear: + { + clearcount(); + if(m_discenter->getcurdistype() == DisType::Dis_Count_Page || m_discenter->getcurdistype() == DisType::Dis_Scan_Page) + m_discenter->PutMsg(DisType::Dis_Count_Page,0,ClearScreen::BOT); + break; + } + default: + break; + } + value = 0; + m_regs->read(0x6, value); + m_regs->write(0x6, value | 128); + m_regs->write(0x6, value & 0xffffff7f); + }; + m_keymonitor.reset(new KeyMonitor(keycall)); +} + +StateControl::~StateControl() +{ + uint value; + m_regs->read(0x06,value); + reg6 func = *(reg6*)&value; + func.param.key_stop_enable = true; + m_regs->write(0x06,func.value); + func.param.key_stop_enable = false; + m_regs->write(0x06,func.value); + if(m_menu.get()) + m_menu.reset(); + if(m_discenter.get()) + m_discenter.reset(); + if(m_keymonitor.get()) + m_keymonitor.reset(); +} + +void StateControl::PutMsg(DisType type,int value,ClearScreen clearscreen) +{ + if(m_discenter) + { + if(type == DisType::Dis_Idel) + { + uint value = 0; + m_regs->read(0x6,value); + auto tmp = *(reg6*)&value; + switch (tmp.param.work_mode) + { + case 1: + m_discenter->PutMsg(DisType::Dis_Set_Count,0,ClearScreen::All); + m_discenter->PutMsg(DisType::Dis_Scan_Page,getpapercount(),ClearScreen::BOT); + return ; + case 5: + m_discenter->PutMsg(DisType::Dis_HandMode,0,ClearScreen::All); + return; + default: + m_discenter->PutMsg(type,value,clearscreen); + break; + } + } + else + m_discenter->PutMsg(type,value,clearscreen); + } +} + +void StateControl::menu_func(DisType type) +{ + uint value = 0; + MotorboardParam func_feed; + m_regs->read(0x6,value); + auto tmp = *(reg6*)&value; + switch (type) + { + case DisType::Dis_Set_Poweroff: + system("poweroff"); + break; + case DisType::Dis_Set_ClearPaperPass: + tmp.param.func_clean_passthro = 1; + tmp.param.motor_disable = false; + m_regs->write(0x6,tmp.value); + tmp.param.func_clean_passthro = 0; + m_regs->write(0x6,tmp.value); + break; + case DisType::Dis_Set_PollPI_High: + tmp.param.func_feed_high = 1; + tmp.param.func_feed_low = tmp.param.func_feed_mid = 0; + m_regs->write(0x6,tmp.value); + func_feed.GetOrSetFeedMode(false,2); + break; + case DisType::Dis_Set_PollPI_Mid: + tmp.param.func_feed_mid = 1; + tmp.param.func_feed_low = tmp.param.func_feed_high = 0; + m_regs->write(0x6,tmp.value); + func_feed.GetOrSetFeedMode(false,1); + break; + case DisType::Dis_Set_PollPI_Low: + tmp.param.func_feed_low = 1; + tmp.param.func_feed_mid = tmp.param.func_feed_high = 0; + m_regs->write(0x6,tmp.value); + func_feed.GetOrSetFeedMode(false,0); + break; + case DisType::Dis_Set_SleepMode_5M: + if(m_wake.get()) + m_wake->settime(300); + break; + case DisType::Dis_Set_SleepMode_10M: + if(m_wake.get()) + m_wake->settime(600); + break; + case DisType::Dis_Set_SleepMode_20M: + if(m_wake.get()) + m_wake->settime(1200); + break; + case DisType::Dis_Set_SleepMode_30M: + if(m_wake.get()) + m_wake->settime(1800); + break; + case DisType::Dis_Set_SleepMode_1H: + if(m_wake.get()) + m_wake->settime(3600); + break; + case DisType::Dis_Set_SleepMode_2H: + if(m_wake.get()) + m_wake->settime(7200); + break; + case DisType::Dis_Set_SleepMode_4H: + if(m_wake.get()) + m_wake->settime(14400); + break; + case DisType::Dis_Set_SleepMode_NEVER: + if(m_wake.get()) + m_wake->settime(-1); + break; + case DisType::Dis_Set_TrayPosition_High: + tmp.param.lift_init_set = 2; + m_regs->write(0x6,tmp.value); + func_feed.GetOrSetTrayPosition(false,2); + break; + case DisType::Dis_Set_TrayPosition_Mid: + tmp.param.lift_init_set = 1; + m_regs->write(0x6,tmp.value); + func_feed.GetOrSetTrayPosition(false,1); + break; + case DisType::Dis_Set_TrayPosition_Low: + tmp.param.lift_init_set = 0; + m_regs->write(0x6,tmp.value); + func_feed.GetOrSetTrayPosition(false,0); + break; + case DisType::Dis_Set_Clear_Roller_ScanNum: + { + PutMsg(DisType::Dis_Set_Is_Sure,0,ClearScreen::BOT); + break; + } + case DisType::Dis_Set_YES: + { + if(m_menu->getcurindex() == 30) + { + auto tmp = Get_static_jsonconfig().getscannerinfo(); + tmp.RollerNum =0; + Get_static_jsonconfig().savescannerinfo(tmp); + PutMsg(DisType::Dis_Set_ScanNum_Option,0,ClearScreen::TOP); + } + break; + } + case DisType::Dis_Set_No: + { + if(m_menu->getcurindex() == 31) + PutMsg(DisType::Dis_Set_ScanNum_Option,0,ClearScreen::TOP); + break; + } + case DisType::Dis_Set_Item_Return: + { + if(m_menu->getcurindex() == 32) + PutMsg(DisType::Dis_Set_ScanNum_Option,0,ClearScreen::TOP); + break; + } + case DisType::Dis_Language_Chinese: + { + auto param = Get_static_deviceconfig().GetParam(); + if(param.language!=0){ + param.language = 0; + Get_static_deviceconfig().SaveParam(param); + } + m_discenter->set_language(LCDDisplay::Language::Chinese); + break; + } + case DisType::Dis_Language_Chinese_Traditional: + { + auto param = Get_static_deviceconfig().GetParam(); + if(param.language!=1){ + param.language = 1; + Get_static_deviceconfig().SaveParam(param); + } + m_discenter->set_language(LCDDisplay::Language::TraditionalChinese); + break; + } + case DisType::Dis_Language_English: + { + auto param = Get_static_deviceconfig().GetParam(); + if(param.language!=2){ + param.language = 2; + Get_static_deviceconfig().SaveParam(param); + } + m_discenter->set_language(LCDDisplay::Language::English); + break; + } + default: + break; + } +} + +void StateControl::lcdcontrol(int led){ + if(m_keymonitor) + m_keymonitor->setled((KeyMonitor::HGLed)led); +} + +void StateControl::setrunstate(bool value) +{ + is_runing = value; + if(is_runing){ + m_keymonitor->setled(KeyMonitor::HGLed::Led_Enter_open); + m_menu->setcurindex(0); + } + else + { + uint value = 0; + m_regs->read(0x6,value); + auto tmp = *(reg6*)&value; + m_keymonitor->setled(tmp.param.key_endouble_feed?KeyMonitor::HGLed::Led_DoubleFeed_open : KeyMonitor::HGLed::Led_DoubleFeed_close); + m_keymonitor->setled(KeyMonitor::HGLed::Led_Enter_close); + } +} + +bool StateControl::getrunstate() +{ + return is_runing; +} + +void StateControl::setcoverstate(bool value) +{ + is_cover_open = value; +} +bool StateControl::getcoverstate() +{ + return is_cover_open; +} +void StateControl::setmenuindex(int menu){ + m_menu->setcurindex(menu); +} + +uint StateControl::getpapercount(){ + unsigned int papercount = 0; + m_regs->read(0x02,papercount); + printf("\nmotorcount = %d ",papercount&0x3fff); + return papercount&0x3fff; +} + +void StateControl::clearcount(){ + uint value = 0; + m_regs->read(0x6,value); + auto reg = *(reg6*)&value; + reg.param.func_clear_count = 1; + m_regs->write(0x6,reg.value); + reg.param.func_clear_count = 0; + m_regs->write(0x6,reg.value); +} + +void StateControl::setautopaperflag(bool enable,bool enkey){ + is_autopaper = enable; + en_autopaper_key = enkey; +} + + void StateControl::setautopaperstopcallback(std::function func) + { + if(func) + autopaperstop = func; + } \ No newline at end of file diff --git a/motorcontroller/StateControl.h b/motorcontroller/StateControl.h new file mode 100644 index 0000000..8d44bc0 --- /dev/null +++ b/motorcontroller/StateControl.h @@ -0,0 +1,63 @@ +#pragma once +#include +#include +class MenuComponent; +class DisplayCenter; +class KeyMonitor; +class IRegsAccess; +class WakeUp; +enum class DisType; +enum class ClearScreen; + +class StateControl{ +typedef union reg6 +{ + struct{ + unsigned int work_mode : 3; + unsigned int func_clean_passthro : 1; + unsigned int func_feed_low : 1; + unsigned int func_feed_mid : 1; + unsigned int func_feed_high : 1; + unsigned int key_sound : 1; + unsigned int key_endouble_feed : 1; + unsigned int func_encount : 1; + unsigned int func_clear_count : 1; + unsigned int motor_choose : 2; + unsigned int wr_en : 1; + unsigned int motor_addr : 8; + unsigned int key_stop_enable : 1; + unsigned int lift_init_set: 2; + unsigned int unused: 3; + unsigned int motor_disable : 1; + }param; + unsigned int value; +} REG6; + +public: + StateControl(std::shared_ptr m_regsAccess,std::shared_ptr wake); + ~StateControl(); + void PutMsg(DisType type,int value,ClearScreen clearscreen); + void setrunstate(bool value); + bool getrunstate(); + void setcoverstate(bool value); + bool getcoverstate(); + void setmenuindex(int menu); + void lcdcontrol(int led); + void setautopaperflag(bool enable,bool enkey); + void setautopaperstopcallback(std::function func); + +private: + void menu_func(DisType type); + uint getpapercount(); + void clearcount(); + std::shared_ptr m_menu; + std::shared_ptr m_discenter; + std::shared_ptr m_keymonitor; + std::shared_ptr m_regs; + std::shared_ptr m_wake; + std::function autopaperstop; + volatile bool is_runing; + volatile bool is_cover_open; + volatile bool is_autopaper; + volatile bool en_autopaper_key; +}; \ No newline at end of file diff --git a/motorcontroller/StateManager.cpp b/motorcontroller/StateManager.cpp new file mode 100644 index 0000000..9ee61c9 --- /dev/null +++ b/motorcontroller/StateManager.cpp @@ -0,0 +1,4 @@ +#include "StateManager.h" + + +std::map> StatePreManager::motorState; \ No newline at end of file diff --git a/motorcontroller/StateManager.h b/motorcontroller/StateManager.h new file mode 100644 index 0000000..aa97a32 --- /dev/null +++ b/motorcontroller/StateManager.h @@ -0,0 +1,30 @@ +#pragma once +#include "IState.h" +#include +#include + +class StatePreManager +{ +protected: + static std::map> motorState; +}; + + +template +class StateManager:public StatePreManager +{ +public: + StateManager(/* args */) = delete; + StateManager(const StateManager&) = delete; + StateManager& operator=(const StateManager&) = delete; + static IState* GetState(int state=0) + { + std::string type_name = typeid(T).name(); + std::map>::iterator iter = motorState.find(type_name); + if (iter == motorState.end()) { + motorState.insert(std::pair>(type_name, std::shared_ptr(new T))); + } + motorState[type_name]->InitState(state); + return motorState[type_name].get(); + } +}; diff --git a/motorcontroller/Statedef.h b/motorcontroller/Statedef.h new file mode 100644 index 0000000..8a62c1e --- /dev/null +++ b/motorcontroller/Statedef.h @@ -0,0 +1,38 @@ +#pragma once + + enum class HGScannerStatus + { + Mode_Welcome, + Mode_Idel, + Mode_Count, + Mode_Scan_Start, + Mode_Scanning, + Mode_Error_Jam, + Mode_Error_DoublePaper, + Mode_Error_Screw, + Mode_Error_Stable, + Mode_Error_AquireTimeout, + Mode_Error_AquireFailed, + Mode_Error_NoFeed, + Mode_Error_CoverOpen, + Mode_Flatting, + Mode_Error_Size, + Mode_Error_DogEar, + Mode_Set_Key_ClearCount, + Mode_Set_Key_Left, + Mode_Set_Key_Manual, + Mode_Set_Key_Right, + Mode_Set_Key_Count, + Mode_Set_HandMode, + Mode_Set_Key_EnDoubleFeed, + Mode_Set_Key_Back, + Mode_Set_Key_Enter, //如需增加状态显示 在之后添加 请勿在此之前添加 避免影响其他代码 + Mode_Error_FeedError + }; + + struct StateInfo + { + HGScannerStatus status; + unsigned int value; + }; + \ No newline at end of file diff --git a/motorcontroller/Subject.h b/motorcontroller/Subject.h new file mode 100644 index 0000000..624dbd9 --- /dev/null +++ b/motorcontroller/Subject.h @@ -0,0 +1,17 @@ +#pragma once +#include +#include +#include +#include +#include "Observer.h" + +using namespace std; + +class Subject +{ +public: + virtual ~Subject(){} + virtual void notify() = 0; + virtual void attach(Observer* this_observer) = 0; + virtual void dettach(Observer* this_observer) = 0; +}; \ No newline at end of file diff --git a/out.text b/out.text new file mode 100644 index 0000000..9a32dd3 --- /dev/null +++ b/out.text @@ -0,0 +1 @@ +测试次数 = 1 异常次数 = 1 \ No newline at end of file diff --git a/packages/common.pkg/include/BlockingQueue.h b/packages/common.pkg/include/BlockingQueue.h new file mode 100644 index 0000000..327a881 --- /dev/null +++ b/packages/common.pkg/include/BlockingQueue.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include +#include +#include +#include + +template +class BlockingQueue +{ +private: + BlockingQueue(const BlockingQueue &rhs); + BlockingQueue &operator=(const BlockingQueue &rhs); + mutable std::mutex _mutex; + std::condition_variable _condvar; + std::deque _queue; + bool isShutDown = false; + T tRet; + +public: + BlockingQueue() + : _mutex(), _condvar(), _queue() + { + } + + ~BlockingQueue() + { + ShutDown(); + } + + void ShutDown() + { + isShutDown = true; + _condvar.notify_all(); + _queue.clear(); + } + + bool IsShutDown() + { + return isShutDown; + } + + void Put(const T task) + { + std::lock_guard lock(_mutex); + if (!isShutDown) + { + { + _queue.push_back(task); + } + _condvar.notify_all(); + } + } + + T Take() + { + std::unique_lock lock(_mutex); + if (_queue.size() <= 0) + _condvar.wait(lock); + + if (isShutDown || _queue.empty()) + { + return tRet; + } + + T front(_queue.front()); + _queue.pop_front(); + + return front; + } + + T Front() + { + std::unique_lock lock(_mutex); + if (_queue.size() <= 0) + _condvar.wait(lock); + + if (isShutDown || _queue.empty()) + { + return tRet; + } + + T front(_queue.front()); + return front; + } + + size_t Size() const + { + std::lock_guard lock(_mutex); + return _queue.size(); + } + + void Clear() + { + std::unique_lock lock(_mutex); + if (_queue.size() <= 0) + return; + if (_queue.size()>0) + { + _queue.clear(); + } + } +}; \ No newline at end of file diff --git a/packages/common.pkg/include/StopWatch.h b/packages/common.pkg/include/StopWatch.h new file mode 100644 index 0000000..bb8aede --- /dev/null +++ b/packages/common.pkg/include/StopWatch.h @@ -0,0 +1,81 @@ +#pragma once +#include +#include + +static std::string GetCurrentTimeStamp(int time_stamp_type ) +{ + std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + + std::time_t now_time_t = std::chrono::system_clock::to_time_t(now); + std::tm* now_tm = std::localtime(&now_time_t); + + char buffer[128]; + strftime(buffer, sizeof(buffer), "%F %T", now_tm); + + std::ostringstream ss; + ss.fill('0'); + + std::chrono::milliseconds ms; + std::chrono::microseconds cs; + std::chrono::nanoseconds ns; + + switch (time_stamp_type) + { + case 0: + ss << buffer; + break; + case 1: + ms = std::chrono::duration_cast(now.time_since_epoch()) % 1000; + ss << buffer << ":" << ms.count(); + break; + case 2: + ms = std::chrono::duration_cast(now.time_since_epoch()) % 1000; + cs = std::chrono::duration_cast(now.time_since_epoch()) % 1000000; + ss << buffer << ":" << ms.count() << ":" << cs.count() % 1000; + break; + case 3: + ms = std::chrono::duration_cast(now.time_since_epoch()) % 1000; + cs = std::chrono::duration_cast(now.time_since_epoch()) % 1000000; + ns = std::chrono::duration_cast(now.time_since_epoch()) % 1000000000; + ss << buffer << ":" << ms.count() << ":" << cs.count() % 1000 << ":" << ns.count() % 1000; + break; + default: + ss << buffer; + break; + } + + return ss.str(); +} + + +class StopWatch +{ +public: + StopWatch() { + _start = std::chrono::steady_clock::now(); + } + + void reset() { + _start = std::chrono::steady_clock::now(); + } + + double elapsed_s() { + return std::chrono::duration(std::chrono::steady_clock::now() - _start).count(); + } + + double elapsed_ms() { + return std::chrono::duration(std::chrono::steady_clock::now() - _start).count(); + } + + double elapsed_us() { + return std::chrono::duration(std::chrono::steady_clock::now() - _start).count(); + } + + double elapsed_ns() { + return std::chrono::duration(std::chrono::steady_clock::now() - _start).count(); + } + +private: + std::chrono::steady_clock::time_point _start; +}; + diff --git a/packages/common.pkg/include/ThreadPool.h b/packages/common.pkg/include/ThreadPool.h new file mode 100644 index 0000000..4183203 --- /dev/null +++ b/packages/common.pkg/include/ThreadPool.h @@ -0,0 +1,98 @@ +#ifndef THREAD_POOL_H +#define THREAD_POOL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class ThreadPool { +public: + ThreadPool(size_t); + template + auto enqueue(F&& f, Args&&... args) + -> std::future::type>; + ~ThreadPool(); +private: + // need to keep track of threads so we can join them + std::vector< std::thread > workers; + // the task queue + std::queue< std::function > tasks; + + // synchronization + std::mutex queue_mutex; + std::condition_variable condition; + bool stop; +}; + +// the constructor just launches some amount of workers +inline ThreadPool::ThreadPool(size_t threads) + : stop(false) +{ + for(size_t i = 0;i task; + + { + std::unique_lock lock(this->queue_mutex); + this->condition.wait(lock, + [this]{ return this->stop || !this->tasks.empty(); }); + if(this->stop && this->tasks.empty()) + return; + task = std::move(this->tasks.front()); + this->tasks.pop(); + } + + task(); + } + } + ); +} + +// add new work item to the pool +template +auto ThreadPool::enqueue(F&& f, Args&&... args) + -> std::future::type> +{ + using return_type = typename std::result_of::type; + + auto task = std::make_shared< std::packaged_task >( + std::bind(std::forward(f), std::forward(args)...) + ); + + std::future res = task->get_future(); + { + std::unique_lock lock(queue_mutex); + + // don't allow enqueueing after stopping the pool + if(stop) + throw std::runtime_error("enqueue on stopped ThreadPool"); + + tasks.emplace([task](){ (*task)(); }); + } + condition.notify_one(); + return res; +} + +// the destructor joins all threads +inline ThreadPool::~ThreadPool() +{ + { + std::unique_lock lock(queue_mutex); + stop = true; + } + condition.notify_all(); + for(std::thread &worker: workers) + worker.join(); +} + +#endif diff --git a/packages/common.pkg/include/autoevent.hpp b/packages/common.pkg/include/autoevent.hpp new file mode 100644 index 0000000..0b5e932 --- /dev/null +++ b/packages/common.pkg/include/autoevent.hpp @@ -0,0 +1,70 @@ +#pragma once +#include +#include + +class AutoSemaphore +{ +public: + AutoSemaphore() + { + } + + virtual ~AutoSemaphore() + { + notify_all(); + } + + virtual void notify_all() + { + std::lock_guard lck(mutx); + cv.notify_all(); + } + + virtual bool wait(int timeout_ms) + { + std::unique_lock lck(mutx); + return cv.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::no_timeout; + } + +protected: + std::mutex mutx; + std::condition_variable cv; +}; + +class AutoEvent : public AutoSemaphore +{ +public: + AutoEvent() + : bNotify(false) + { + } + + virtual ~AutoEvent() + { + notify_all(); + } + + virtual void notify_all() + { + std::lock_guard lck(mutx); + bNotify = true; + cv.notify_all(); + } + + virtual bool wait(int timeout_ms) + { + std::unique_lock lck(mutx); + if (bNotify) + { + bNotify = false; + return true; + } + + bool ret = cv.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::no_timeout; + bNotify = false; + return ret; + } + +private: + volatile bool bNotify; +}; \ No newline at end of file diff --git a/packages/common.pkg/include/base64.hpp b/packages/common.pkg/include/base64.hpp new file mode 100644 index 0000000..c83c601 --- /dev/null +++ b/packages/common.pkg/include/base64.hpp @@ -0,0 +1,115 @@ +#include +#include +/** + * Base64 编码/解码 + * @author liruixing + */ +class Base64{ +private: + std::string _base64_table; + static const char base64_pad = '='; +public: + Base64() + { + _base64_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /*这是Base64编码使用的标准字典*/ + } + /** + * 这里必须是unsigned类型,否则编码中文的时候出错 + */ + std::string Encode(const unsigned char * str,int bytes) { + int num = 0,bin = 0,i; + std::string _encode_result; + const unsigned char * current; + current = str; + while(bytes > 2) { + _encode_result += _base64_table[current[0] >> 2]; + _encode_result += _base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)]; + _encode_result += _base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)]; + _encode_result += _base64_table[current[2] & 0x3f]; + + current += 3; + bytes -= 3; + } + if(bytes > 0) + { + _encode_result += _base64_table[current[0] >> 2]; + if(bytes%3 == 1) { + _encode_result += _base64_table[(current[0] & 0x03) << 4]; + _encode_result += "=="; + } else if(bytes%3 == 2) { + _encode_result += _base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)]; + _encode_result += _base64_table[(current[1] & 0x0f) << 2]; + _encode_result += "="; + } + } + return _encode_result; + } + std::string Decode(const char *str,int length) { + //解码表 + const std::int8_t DecodeTable[] = + { + -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -1, -2, -2, -1, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 62, -2, -2, -2, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -2, -2, -2, -2, -2, -2, + -2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -2, -2, -2, -2, -2, + -2, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -2, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2 + }; + int bin = 0,i=0,pos=0; + std::string _decode_result; + const char *current = str; + char ch; + while( (ch = *current++) != '\0' && length-- > 0 ) + { + if (ch == base64_pad) { // 当前一个字符是“=”号 + /* + 先说明一个概念:在解码时,4个字符为一组进行一轮字符匹配。 + 两个条件: + 1、如果某一轮匹配的第二个是“=”且第三个字符不是“=”,说明这个带解析字符串不合法,直接返回空 + 2、如果当前“=”不是第二个字符,且后面的字符只包含空白符,则说明这个这个条件合法,可以继续。 + */ + if (*current != '=' && (i % 4) == 1) { + return NULL; + } + continue; + } + ch = DecodeTable[ch]; + //这个很重要,用来过滤所有不合法的字符 + if (ch < 0 ) { /* a space or some other separator character, we simply skip over */ + continue; + } + switch(i % 4) + { + case 0: + bin = ch << 2; + break; + case 1: + bin |= ch >> 4; + _decode_result += bin; + bin = ( ch & 0x0f ) << 4; + break; + case 2: + bin |= ch >> 2; + _decode_result += bin; + bin = ( ch & 0x03 ) << 6; + break; + case 3: + bin |= ch; + _decode_result += bin; + break; + } + i++; + } + return _decode_result; + } +}; diff --git a/packages/common.pkg/include/commondef.h b/packages/common.pkg/include/commondef.h new file mode 100644 index 0000000..3e888ca --- /dev/null +++ b/packages/common.pkg/include/commondef.h @@ -0,0 +1,903 @@ +#pragma once +#include +#include +#include + +#define FWVersionEN + +#define G200 + +#ifdef G200 +#define FWVersion "G2393D0228" +#define SERIALNUM "G2396021071101" +#else +#define FWVersion "G1393D0228" +#define SERIALNUM "G1396021071101" +#endif + +//#ifdef FWVersionEN +//#pragma warnning("WARNNING! current fareware version is :" FWVersion) +//#endif +typedef unsigned int u32; +typedef unsigned char u8; +typedef unsigned char byte; +typedef unsigned short u16; + +typedef struct Size +{ + long x; + long y; +}; + +typedef enum Error_Status : uint32_t +{ + NO_error = 0, + Dog_error = 1, + Size_error = 2, + Img_Detecting = 0xffff, +}; + +typedef struct ImgStatus +{ + Error_Status status; + uint32_t scannum; +}; + +typedef union HG_ScanConfig +{ + unsigned int value; + struct + { + unsigned int paper : 5; + unsigned int color : 1; + unsigned int dpi : 2; + unsigned int double_feed_enbale : 1; + unsigned int stable_enbale : 1; + unsigned int screw_detect_enable : 1; + unsigned int screw_detect_level : 3; //第十四位 + unsigned int iscorrect_mode : 1; + unsigned int is_autopaper : 1; + unsigned int is_textcorrect : 1; + unsigned int is_fixedpaper : 1; + unsigned int en_anlogic_key : 1; + unsigned int en_autosize : 1; + unsigned int pc_correct : 1; + //unsigned int enable_sizecheck : 1; + unsigned int double_out_en : 1; + unsigned int enabledsp_cache : 1; + unsigned int sizeerror_errorratio : 9; + } g200params; + struct + { + unsigned int pageSize : 5; + unsigned int isColor : 1; + unsigned int dpi : 2; + unsigned int doubleFeeded : 1; + unsigned int enableStable : 1; + unsigned int enableLed : 1; + unsigned int reversed1 : 6; + unsigned int isCorrect : 1; + unsigned int dstHeight : 8; + unsigned int reversed2 : 6; + } g400params; +} HGScanConfig; + +typedef enum SCAN_STATUS +{ + SCAN_NORMAL, + SCAN_SCANNING, + SCAN_COVEROPEN, + SCAN_FEEDERROR, + SCAN_PAPERJAM, + SCAN_DOUBLEFEED, + SCAN_AQUIREIMGTIMEOUT, + SCAN_AQUIREIMGSIZEERROR, + SCAN_DETECTSKREW, + SCAN_DETECTSTABLE, + SCAN_COUNTMODE, + SCAN_NOFEED, + SCAN_AUTOCORRECT_DONE, + SCAN_STOPED +} SCAN_STATUS; + +enum img_status : uint32_t +{ + IMG_STATUS_OK = 0, // normal + IMG_STATUS_DOUBLE = 1 << 0, // double-feeded paper + IMG_STATUS_JAM = 1 << 1, // jammed paper + IMG_STATUS_STAPLE = 1 << 2, // staples on the paper + IMG_STATUS_SIZE_ERR = 1 << 3, // size check failed + IMG_STATUS_DOGEAR = 1 << 4, // paper has dogear - common + IMG_STATUS_DOGEAR_PARTIAL = 1 << 5, // dogear - scanned partial + IMG_STATUS_BLANK = 1 << 6, // blank image +}; + +struct MotorBoardGlue +{ + MotorBoardGlue(const std::function error_call, + const std::function scan_done_call, + const std::function os_mode_call, + const std::function set_sleepmode_call, + const std::function mltop_call, + std::function auto_paper, + const std::function coveropen) + : m_error_call(error_call), + m_scan_done_call(scan_done_call), + m_os_mode_call(os_mode_call), + m_set_sleepmode_call(set_sleepmode_call), + m_mltop_call(mltop_call), + m_auto_paper(auto_paper), + m_coveropen_call(coveropen) + { + } + + std::function m_error_call; + std::function m_scan_done_call; + std::function m_os_mode_call; + std::function m_set_sleepmode_call; + std::function m_mltop_call; + std::function m_auto_paper; + std::function m_coveropen_call; +}; + + +struct ScannerNativeParam +{ + u32 TotalScanned; //扫描总计�? + u32 RollerNum; //滚轴计数 + u32 H_ratio; //横向修正系数 + u32 V_ratio; //纵向修正系数 + u32 JamTimes; //卡纸次数 + u32 FeedErrorTimes; //搓纸失败次数 + u32 DoubleFeedTimes; //双张次数 + u32 ScanSessionsCount; //总计扫描次数 + u16 gray_sp; //灰度sp�? + u16 color_sp; //彩色sp�? + int sleeptime; //休眠模式时间 -1 不休�? + std::string SerialNum; //序列�? + std::string Token; //识别�? + u32 clr_maxbright; //彩色平场校正最大亮�? + u32 gray_maxbright; //灰度平场校正最大亮�? + u32 speedmode; //速度模式 G100 0->70 1->80 2->90 3->100 G200 0->100 1->110 2->120 3->130 + u16 Vid; //USB vid + u16 Pid; //USB Pid + std::uint32_t chu_motor_speed_200; // G100 G200 出纸电机速度 + std::uint32_t chu_motor_speed_300; // G100 G200 出纸电机速度 + std::uint32_t chu_motor_speed_600; // G100 G200 出纸电机速度 +}; + +enum TwSS : unsigned short +{ + None = 0, + A4Letter = 1, + A4 = 1, + B5Letter = 2, + JISB5 = 2, + B5 = 2, + USLetter = 3, + USLegal = 4, + A5 = 5, + B4 = 6, + ISOB4 = 6, + B6 = 7, + ISOB6 = 7, + USLedger = 9, + USExecutive = 10, + A3 = 11, + B3 = 12, + ISOB3 = 12, + A6 = 13, + C4 = 14, + C5 = 15, + C6 = 16, + _4A0 = 17, + _2A0 = 18, + A0 = 19, + A1 = 20, + A2 = 21, + A7 = 22, + A8 = 23, + A9 = 24, + A10 = 25, + ISOB0 = 26, + ISOB1 = 27, + ISOB2 = 28, + ISOB5 = 29, + ISOB7 = 30, + ISOB8 = 31, + ISOB9 = 32, + ISOB10 = 33, + JISB0 = 34, + JISB1 = 35, + JISB2 = 36, + JISB3 = 37, + JISB4 = 38, + JISB6 = 39, + JISB7 = 40, + JISB8 = 41, + JISB9 = 42, + JISB10 = 43, + C0 = 44, + C1 = 45, + C2 = 46, + C3 = 47, + C7 = 48, + C8 = 49, + C9 = 50, + C10 = 51, + USStatement = 52, + BusinessCard = 53, + MaxSize = 54, + K8 = 0x81, + K16 = 0x82, + Trigeminy = 0x83, +}; + +enum class PaperSize +{ + G400_A3 = 0, + G400_A4, + G400_A4R, + G400_A5, + G400_A5R, + G400_A6, + G400_A6R, + G400_B4, + G400_B5, + G400_B5R, + G400_B6, + G400_B6R, + G400_DOUBLELETTER, + G400_LEGAL, + G400_LETTER, + G400_LETTERR, + G400_LONGLETTER = 16, + G400_MAXSIZE = 17, + G400_AUTO = 16, + G400_MAXAUTO = 18 +}; + +struct HGSize +{ + unsigned int width; + unsigned int height; + + bool operator<(HGSize const &right) const + { + if (width < right.width && height < right.height) + return true; + return false; + } +}; + +//usb int 端点 返回消息的生产�? +enum HGType +{ + MtBoard = 1, + FPGA, + V4L2, + IMG, + AutoCorrect, + STOPSCAN, + CMD_OUT, +}; + +//usb int 端点通信结构�? +struct HGIntInfo +{ + HGType From; + unsigned int Code; + unsigned int Img_Index; + img_status Img_Status; +}; + +enum SpeedMode +{ + PPM70 = 70, + PPM80 = 80, + PPM90 = 90, + PPM100 = 100, + PPM110 = 110, + PPM120 = 120, + PPM130 = 130 +}; + +typedef struct frame_data_info +{ + unsigned int offset; + unsigned int total; + unsigned int frame_count; + unsigned int img_w; + unsigned int img_h; + void* pdata; + bool empty() + { + return (offset *total*frame_count*img_w*img_h== 0) || (pdata == nullptr); + } + std::string to_str() + { + return "offset = " + std::to_string(offset)+ " total = "+ std::to_string(total) + " frame_count = "+ std::to_string(frame_count) + + " img_w = "+ std::to_string(img_w) + " img_h = "+ std::to_string(img_h); + } +}; + +typedef struct +{ + u32 colorSp_200; + u32 graySp_200; + u32 colorSp_300; + u32 graySp_300; + u32 colorSp_600; + u32 graySp_600; + u32 motorSpeed; +} DunNanCisSp; + +typedef struct +{ + u32 colorSp; + u32 graySp; + u32 motorSpeed; +} CisSp; + + +static std::map cameraparmSp = { +#ifdef G100 + {PPM70, {.colorSp_200 = 1150 , .graySp_200= 3450,.colorSp_300 = 1207 ,.graySp_300 = 3621,.colorSp_600 = 1822 ,.graySp_600 = 5466 , 1}}, + {PPM80, {.colorSp_200 = 1150 , .graySp_200= 3450,.colorSp_300 = 1207 ,.graySp_300 = 3621,.colorSp_600 = 1822 ,.graySp_600 = 5466 , 2}}, + {PPM90, {.colorSp_200 = 944 , .graySp_200= 2834,.colorSp_300 = 1019 ,.graySp_300 = 3059,.colorSp_600 = 1822 ,.graySp_600 = 5466 , 0}}, + {PPM100, {.colorSp_200 = 847 , .graySp_200= 2541,.colorSp_300 = 875 ,.graySp_300 = 2626,.colorSp_600 = 1822 ,.graySp_600 = 5466 , 4}},//G100 3399 暂无100 ppm + {PPM110, {.colorSp_200 = 847 , .graySp_200= 2541,.colorSp_300 = 875 ,.graySp_300 = 2626,.colorSp_600 = 1822 ,.graySp_600 = 5466 , 3}}, +#else + {PPM90, {.colorSp_200 = 816 , .graySp_200= 2450,.colorSp_300 = 878 ,.graySp_300 = 2637,.colorSp_600 = 1531 ,.graySp_600 = 4595 , 4}}, + {PPM100, {.colorSp_200 = 816 , .graySp_200= 2450,.colorSp_300 = 878 ,.graySp_300 = 2637,.colorSp_600 = 1531 ,.graySp_600 = 4595 , 0}}, + {PPM110, {.colorSp_200 = 816 , .graySp_200= 2450,.colorSp_300 = 878 ,.graySp_300 = 2637,.colorSp_600 = 1531 ,.graySp_600 = 4595 , 1}}, + {PPM120, {.colorSp_200 = 816 , .graySp_200= 2450,.colorSp_300 = 878 ,.graySp_300 = 2637,.colorSp_600 = 1531 ,.graySp_600 = 4595 , 3}}, + {PPM130, {.colorSp_200 = 816 , .graySp_200= 2450,.colorSp_300 = 878 ,.graySp_300 = 2637,.colorSp_600 = 1531 ,.graySp_600 = 4595 , 2}} //默认 140 +#endif +}; + +//.colorSp_200 = 2606 , .graySp_200= 7818,.colorSp_300 = 2804 ,.graySp_300 = 8412,.colorSp_600 = 3405 ,.graySp_600 = 10215 +static std::map cameraparmSp_8478 = { +#ifdef G100 + {PPM70, {.colorSp_200 = 1150 , .graySp_200= 3450,.colorSp_300 = 1207 ,.graySp_300 = 3621,.colorSp_600 = 1822 ,.graySp_600 = 5466 , 1}}, + {PPM80, {.colorSp_200 = 1150 , .graySp_200= 3450,.colorSp_300 = 1207 ,.graySp_300 = 3621,.colorSp_600 = 1822 ,.graySp_600 = 5466 , 2}}, + {PPM90, {.colorSp_200 = 944 , .graySp_200= 2834,.colorSp_300 = 1019 ,.graySp_300 = 3059,.colorSp_600 = 1822 ,.graySp_600 = 5466 , 0}}, + {PPM100, {.colorSp_200 = 847 , .graySp_200= 2541,.colorSp_300 = 875 , .graySp_300 = 2626,.colorSp_600 = 1822 ,.graySp_600 = 5466 , 4}},//G100 3399 暂无100 ppm + {PPM110, {.colorSp_200 = 847 , .graySp_200= 2541,.colorSp_300 = 875 , .graySp_300 = 2626,.colorSp_600 = 1822 ,.graySp_600 = 5466 , 3}}, +#else + {PPM90, {.colorSp_200 = 7818 , .graySp_200= 7818,.colorSp_300 = 8412 ,.graySp_300 = 8412,.colorSp_600 = 10215 ,.graySp_600 = 10215 , 4}}, + {PPM100, {.colorSp_200 = 7818 , .graySp_200= 7818,.colorSp_300 = 8412 ,.graySp_300 = 8412,.colorSp_600 = 10215 ,.graySp_600 = 10215 , 0}}, + {PPM110, {.colorSp_200 = 7818 , .graySp_200= 7818,.colorSp_300 = 8412 ,.graySp_300 = 8412,.colorSp_600 = 10215 ,.graySp_600 = 10215 , 1}}, + {PPM120, {.colorSp_200 = 7818 , .graySp_200= 7818,.colorSp_300 = 8412 ,.graySp_300 = 8412,.colorSp_600 = 10215 ,.graySp_600 = 10215 , 3}}, + {PPM130, {.colorSp_200 = 7818 , .graySp_200= 7818,.colorSp_300 = 8412 ,.graySp_300 = 8412,.colorSp_600 = 10215 ,.graySp_600 = 10215 , 2}} //默认 140 +#endif +}; + + +static std::map anlogic_freq = { +#ifdef G100 + {PPM70, 1}, + {PPM80, 2}, + {PPM90, 3}, + {PPM110, 4}, +#else + {PPM100, 1}, + {PPM110, 2}, + {PPM120, 3}, + {PPM130, 4} +#endif +}; + +static std::map scannerSp = { +#ifdef G100 + {PPM70, {0x42d, 0xc88, 1}}, + {PPM80, {0x37f, 0xa7f, 2}}, + {PPM90, {0x2B6, 0x822, 0}}, + {PPM100, {0x27C, 0x775, 4}},//G100 3399 暂无100 ppm + {PPM110, {0x24e, 0x706, 3}}, +#else + {PPM90, {0x27C, 0x775, 4}}, + {PPM100, {0x27C, 0x775, 0}}, + {PPM110, {0x27C, 0x775, 1}}, + {PPM120, {0x27C, 0x775, 3}}, + {PPM130, {0x27C, 0x775, 2}} //默认 140 +#endif +}; + +static std::map papersMap = { + {PaperSize::G400_A3, {1632, 10800}}, + {PaperSize::G400_A4, {1632, 8100}}, + {PaperSize::G400_A4R, {1632, 6000}}, + {PaperSize::G400_A5, {1632, 6000}}, + {PaperSize::G400_A5R, {1632, 6000}}, + {PaperSize::G400_A6, {1632, 6000}}, + {PaperSize::G400_A6R, {1632, 6000}}, + {PaperSize::G400_B4, {1632, 10800}}, + {PaperSize::G400_B5, {1632, 8100}}, + {PaperSize::G400_B5R, {1632, 6000}}, + {PaperSize::G400_B6, {1632, 6000}}, + {PaperSize::G400_DOUBLELETTER, {1632, 10800}}, + {PaperSize::G400_B6R, {1632, 6000}}, + {PaperSize::G400_LEGAL, {1632, 10800}}, + {PaperSize::G400_LETTER, {1632, 8100}}, + {PaperSize::G400_LETTERR, {1632, 10800}}, + {PaperSize::G400_MAXSIZE, {1632, 16002}}, + {PaperSize::G400_AUTO, {1632, 10800}}, + {PaperSize::G400_MAXAUTO, {1632, 16002}}, +}; + +// pair unit:mm +static std::map paperHeight={ + {PaperSize::G400_A3, 475}, + {PaperSize::G400_A4, 337}, + {PaperSize::G400_A4R, 240}, + {PaperSize::G400_A5, 247}, + {PaperSize::G400_A5R, 178}, + {PaperSize::G400_A6, 178}, + {PaperSize::G400_A6R, 135}, + {PaperSize::G400_B4, 383}, + {PaperSize::G400_B5, 300}, + {PaperSize::G400_B5R, 226}, + {PaperSize::G400_B6, 226}, + {PaperSize::G400_DOUBLELETTER, 500}, + {PaperSize::G400_B6R, 175}, + {PaperSize::G400_LEGAL, 386}, + {PaperSize::G400_LETTER, 339}, + {PaperSize::G400_LETTERR, 276}, + {PaperSize::G400_MAXSIZE, 1040},//300 dpi max heigth 690 + {PaperSize::G400_AUTO, 1040},//300 dpi max heigth + {PaperSize::G400_MAXAUTO, 1040}//300 dpi max heigth +}; + +enum Scanner_Reg_Defs +{ + SR_CMD, + SR_STATUS, + SR_SCAN_COUNT, + SR_OS, + SR_SENSORS, + SR_MOTOR, + SR_IM_TYPE, + SR_IM_COUNT, + SR_IM_TX, + SR_IM_FRONT_SIZE, + SR_IM_CLEAR, + SR_IM_TXING, + SR_IM_POP, + SR_IM_ABORT, + SR_COUNT, + SR_CONFIG_SCAN_PARAM, + SR_GET_FWVERSION, + SR_SET_FWERSION, + SR_GET_SERIALNUM, + SR_SET_SERIALNUM, + SR_CONFIF_IMGPROCPARAM, + SC_AUTOCORRECT, + SC_GET_CORRECT_PARAM, + SC_SET_CORRECT_PARAM, + SR_GET_H_RATIO, + SR_SET_H_RATIO, + SR_GET_V_RATIO, + SR_SET_V_RATIO, + SR_GET_SERIAL_LEN, + SR_GET_GRAY_SP, + SR_GET_COLOR_SP, + SR_SET_GRAY_SP, + SR_SET_COLOR_SP, + SR_SET_SLEEPTIME, + SR_GET_SLEEPTIME, + SR_GET_SLEEP_STAUTUS, + SR_GET_IMAGEPROCESSDONE, + SR_GET_KEEP_LAST_PAPER, + SR_GET_PAPERON, + SR_SET_SPEEDMODE, + SR_GET_SPEEDMODE, + SR_GET_JOSN_SIZE, + SR_GET_JSON, + SR_SET_JSON_PATH, + SR_SET_JSON, + SR_GET_FILE_POS, + SR_SET_FILE_POS, + SR_NOTIFY_SLEEP, + SR_GET_FEEDMODE, + SR_SET_FEEDMODE, + SR_GET_AUTOMATICCONTROLFEEDMODE_ENABLE, + SR_SET_AUTOMATICCONTROLFEEDMODE_ENABLE, + SR_GET_AUTOMATICCONTROLFEEDMODE_THRESHOLD, + SR_SET_AUTOMATICCONTROLFEEDMODE_THRESHOLD, + SR_GET_TRAYPOSITION, + SR_SET_TRAYPOSITION, + SR_GET_LOCK_STATES, + SR_SET_LOCK_STATES, + SR_GET_TOKEN, + SR_SET_TOKEN, + SR_GET_TOKEN_LENGHT, + SR_DECODE_TOKEN, + SR_CLEAN_PAPER_ROAD, + SR_EXECUTE_CMD, + SR_EXECUTE_CMD_OUT_LENGHT, + SR_GET_EXECUTE_CMD_OUT, + SR_SET_Corrective_Restoration, + SR_BACKUP_RESTORES_HUAGODIR, + SR_SINGLE_CORRECT_MODE, + SR_GET_DAIL_CODE, + SR_GET_CUO_ERROR = 0x50, + SR_GET_DOU_ERROR, + SR_GET_JAM_ERROR, + SR_GET_SCANN_NUM, + SR_CLR_ROLLER_NUM, + SR_GET_ROLLER_NUM, + SR_CLR_SCANN_NUM, + SR_GET_H_200_RATIO, //非敦南cis需返回false + SR_SET_H_200_RATIO, + SR_GET_V_200_RATIO, + SR_SET_V_200_RATIO, + SR_GET_H_300_RATIO, + SR_SET_H_300_RATIO, + SR_GET_V_300_RATIO, + SR_SET_V_300_RATIO, + SR_GET_H_600_RATIO, + SR_SET_H_600_RATIO, + SR_GET_V_600_RATIO, + SR_SET_V_600_RATIO, + SR_SET_GRAYCORRECT_MODE, + SR_GET_GRAYCORRECT_MODE, + SR_GET_ARM_DATETIME, + SR_GET_ARM_DATETIME_LENGHT, + SR_SET_ARM_DATETIME, + SR_SET_SENSOR_PARAM, + SR_GET_SENSOR_PARAM, + SR_SET_LCD_LANGUAGE, + SR_GET_LCD_LANGUAGE, + SR_UPDATA_START = 0x100, + SR_UPDATA_STAUTUS = 0x101, + SR_UPDATA_MD5_RELUST = 0x102, + SR_UPDATA_RECOVERY = 0x103, + SR_UPDATA_REBOOT = 0x104, + SR_POWEROFF = 0x105, + SR_REBOOT = 0x106, + SR_FLAT_CLR_MAX_BRIGHT, + SR_FLAT_GRAY_MAX_BRIGHT, + SR_KERNEL_VERSION_INFO_LENGTH, + SR_GET_KERNEL_VERSION, + SR_GET_MBSTATUS, + SR_GET_IPADDR_LENGHT = 0x200, + SR_GET_MACADDR, + SR_GET_IPADDR, + SR_GET_MBVERSION_LENGHT, + SR_GET_MBVERSION, + SR_GET_USBVIDPID, + SR_SET_USBVIDPID, + SR_SET_STARTBACKUP,//开始备份 + SR_GET_BACKUPSTATUS//备份状态 +}; + +typedef union Ctrol_Description{ + std::uint32_t value; + struct{ + std::uint32_t direction : 1; + std::uint32_t unused : 31; + }Param; +}CtrolDescription; + +enum Updata_Stautus +{ + Start_updata, + Download_file, + Download_file_error, + Download_file_finish, + MD5_Reovery, + MD5_Rboot, + MD5_Error, + Reboot +}; + +enum Scanner_Cmd_Defs +{ + SC_START, + SC_STOP, + SC_CLEAR, + SC_COUNT +}; + +enum HGScanSide +{ + Duplex, + Single, + DisCardBlankNormal, + DisCardBlacnkVince, + Flod +}; + +enum class HGRotate +{ + Rot_0, + Rot_90, + Rot_180, + Rot_270, + Rot_auto +}; + +typedef union USBVIDPID +{ + struct{ + unsigned short VID; + unsigned short PID; + }param; + unsigned int value; +}; + +typedef union HG_ImgProcParms +{ + unsigned int value; + struct + { + u32 papertype : 5; + u32 scanside : 3; + u32 res : 10; + u32 rotate : 2; + u32 autodescrew : 1; + u32 fillbackground : 1; + u32 filter : 4; + u32 enhancecolor : 2; + u32 fillhole : 1; + u32 reversed : 3; + } imgprocparams; +} HGImgProcParms; + +///用于CIS 自动校正参数保存 +typedef struct +{ + u32 gainF[6]; + u32 gainB[6]; + u32 offsetsF[6]; + u32 offsetsB[6]; + u32 expF[3]; + u32 expB[3]; + u32 sp; +} HGCISConfig; + +typedef struct +{ + HGCISConfig colorCorrect; + HGCISConfig color; + HGCISConfig grayCorrect; + HGCISConfig gray; +} HGCorrectConfigs; + +enum class CISVendor +{ + CIS_UNKNOWUN, + HUALIN_CIS_V0, + DUNNAN_CIS_V0 +}; + +#define STR_CORRECTCOLOR CorrectColor +#define STR_COLOR Color +#define STR_CORRECTGRAY CorrectGray +#define STR_GRAY Gray + +#define STR_GAINF GainF +#define STR_GAINB GainB +#define STR_EXPF ExpF +#define STR_EXPB ExpB +#define STR_OFFSETF OffsetF +#define STR_OFFSETB OffsetB +#define STR_SP Sp + +#define STR(str) #str +#define STRCON(str1, str2) STR(str1) \ +STR(str2) + +#define LUT_COLOR_BLACK_PATH "/usr/local/huago/lut_0.bmp" +#define LUT_COLOR_WHITE_PATH "/usr/local/huago/lut_1.bmp" +#define LUT_GRAY_BLACK_PATH "/usr/local/huago/lut_2.bmp" +#define LUT_GRAY_WHITE_PATH "/usr/local/huago/lut_3.bmp" +#define LUT_COLOR_LUT_PATH "/usr/local/huago/color_lut.bmp" +#define LUT_GRAY_LUT_PATH "/usr/local/huago/gray_lut.bmp" + +#define IMAGE_COLOR 1 +#define IMAGE_GRAY 0 + +#define JSON_CORRECTFILE_PATH "/usr/local/huago/cisconfig.json" +#define JSON_CORRECTDIR_PATH "/usr/local/huago" +#define JSON_SCANNER_INFO_DIR "/usr/local/huago" +#define JSON_SCANNER_INFO_FILE "/usr/local/huago/scannerinfo.json" + +#define S_INFO_TOTALSCANNED "TotalScanned" +#define S_INFO_ROLLERNUM "RollerNum" +#define S_INFO_HRATIO "HRatio" +#define S_INFO_VRATIO "VRatio" +#define S_GRAY_SP "GraySp" +#define S_COLOR_SP "ColorSp" +#define S_INFO_SLEEPTIME "Sleeptime" +#define S_INFO_JAMNUM "JamInNum" +#define S_INFO_FEEDERROR "FeedError" +#define S_INFO_DOUNUM "DoubleNum" +#define S_INFO_SCANSESSIONCOUNT "ScanTimes" +#define S_INFO_SERIALNUM "SerialNum" +#define S_INFO_TOKEN "ScannerToken" +#define S_INFO_CLR_MAXBRT "FlatClrMaxBrt" +#define S_INFO_GRAY_MAXBRT "FlatGrayMaxBrt" +#define S_INFO_SPEEDMODE "SpeedMode" +#define S_INFO_VID "VID" +#define S_INFO_PID "PID" +#define S_INFO_CHUZHI_MOTOR_SPEED_200 "Chu_Motor_Speed_200" +#define S_INFO_CHUZHI_MOTOR_SPEED_300 "Chu_Motor_Speed_300" +#define S_INFO_CHUZHI_MOTOR_SPEED_600 "Chu_Motor_Speed_600" + +#pragma pack(push) +#pragma pack(4) +typedef struct tagFillHole +{ + uint8_t is_fillhole; + int fillholeratio; +} FillHole; + +typedef struct tagDetachNoise +{ + uint8_t is_detachnoise; + int detachnoise; +} DetachNoise; + +enum LowPowerMode : unsigned int +{ + Min_None = 0, + Min_5, + Min_10, + Min_20, + Min_30, + Min_60, + Min_120, + Min_240 +}; + +typedef struct tagHARDWAREPARAMS +{ + byte capturepixtype; + byte en_doublefeed; + byte en_stapledetect; + byte en_skrewdetect; + byte skrewdetectlevel; + LowPowerMode lowpowermode; +#ifdef UV + byte en_uv; +#endif +} HardwareCaps; + +typedef struct Scan_Rect +{ + int width; + int height; + int x; + int y; +} ScanRect; + +enum PaperAlign : unsigned char +{ + Rot0 = 0, + Rot270 = 3, + AutoTextOrientation = 5 +}; + +typedef enum Enchace_Color : short +{ + Enhance_None = 0, + Enhance_Red, + Enhance_Green, + Enhance_Blue +} EnchaceColor; + +typedef enum SharpenBlur : short +{ + Sharpen_None, + Sharpen_Normal, + Sharpen_More, + Sharpen_Blur, + Sharpen_Blur_More +} SharpenBlur; + +typedef struct tagCrop_Rect +{ + int enable; + int x; /*****自定义裁切区域左上角x坐标*/ + int y; /*****自定义裁切区域左上角y坐标*/ + int width; /*****自定义裁切区域宽�?******/ + int height; /*****自定义裁切区域高�?******/ +}CropRect; + +typedef enum tagMulti_Output { + Unused = -1, + All, + ColorGray, + ColorBw, + GrayBw +}MultiOutput; + +typedef struct tagSkew_Detection { + int enable; + int level; +}SkewDetection; + +typedef struct tagHhardware_Params_3399 +{ + int capturepixtype; + int doubleFeedDetection; + int bindingDetection; + int sizeDetection; + SkewDetection skewDetection; +}HardwareCaps_3399; + +struct GScanCap +{ + uint8_t papertype; + PaperAlign paperAlign; + uint8_t en_sizecheck; + float imageRotateDegree; + uint8_t is_duplex; + uint8_t en_fold; + int pixtype; + int automaticcolor; + int automaticcolortype; + //ScanRect scanrect; + float resolution_dst; + float resolution_native; + float gamma; + float contrast; + float brightness; + float threshold; + uint8_t is_autocontrast; + uint8_t is_autocrop; + uint8_t is_autodiscradblank_normal; + int discardblank_percent; + uint8_t is_autodiscradblank_vince; + uint8_t is_switchfrontback; + uint8_t autodescrew; + uint8_t multi_output_red; + uint8_t hsvcorrect; + uint8_t filter; + uint8_t sharpen; + uint8_t enhance_color; + uint8_t fillbackground; + bool is_convex; + int noise; + int indent; + int AutoCrop_threshold; + unsigned short scannum; + uint8_t is_backrotate180; + uint8_t is_dogeardetection; + HardwareCaps hardwarecaps; + FillHole fillhole; + DetachNoise detachnoise; + uint8_t is_autotext; + bool isfillcolor; + int refuseInflow; + int colorCorrection; + int removeMorr; + int errorExtention; + int textureRemove; + int splitImage; + CropRect cropRect; + MultiOutput multiOutput; + bool normalCrop; + uint32_t dogeardistabce; + bool fadeback; + int fadebackrange; + bool isuploadexceptionimage; + int fillholeratio_up; + int fillholeratio_down; + int fillholeratio_left; + int fillholeratio_right; + std::uint8_t fold_concatmode; /*拼接模式*/ + int HsvFilterType; /**< 答题卡留红除杂色功能类型 暂定0 为关闭;1为留红除杂色>*/ + bool is_colorcast; /**< 色偏校正>*/ + int discare_edge; /**< 跳过空白页边缘缩进>*/ + int discare_dilate; /**< 调过空白页纸张杂点阈值>*/ + double discare_meanth; /**< 调过空白页文稿底色阈值>*/ + bool en_contaminationdetection; /**< 脏污检测使能>*/ + bool detect_size_discard_blank; /**< 基于压缩图像大小跳过空白页使能>*/ + uint32_t refuseInflow_level; /**< 防止渗透等级>*/ + uint32_t maxszie_sanp_height; /**< 最大幅面采集高度>*/ + uint32_t reserve[1024]; /**< 预留4096字节做协议扩展*/ +}; +#pragma pack(pop) diff --git a/packages/common.pkg/include/config.h b/packages/common.pkg/include/config.h new file mode 100644 index 0000000..30cb1eb --- /dev/null +++ b/packages/common.pkg/include/config.h @@ -0,0 +1,10 @@ +#pragma once + +#define FPGA_UART "/dev/ttyUSB0" +#define MOTOR_UART "/dev/ttyS4" +/* #undef CIS_TYPE */ +/* #undef TEST_IMAGE_DIR */ +/* #undef CAP_UNFIXED */ +#define TEST_FPGA "ON" +/* #undef LOOP_DEBUG */ +#define VIDEO_CLASS GVideoISP1 diff --git a/packages/common.pkg/include/dailex.hpp b/packages/common.pkg/include/dailex.hpp new file mode 100644 index 0000000..65402a5 --- /dev/null +++ b/packages/common.pkg/include/dailex.hpp @@ -0,0 +1,55 @@ +#pragma once +#include +#include +#include +#include +union HG_Dail_Struct +{ + struct + { + std::uint32_t in_voltage0 : 1 ; + std::uint32_t in_voltage2 : 1 ; + std::uint32_t in_voltage3 : 1 ; + std::uint32_t in_voltage4 : 1 ; + }dails; + std::uint8_t value; +}; + +const std::string voltage0 = "/sys/bus/iio/devices/iio:device0/in_voltage0_raw"; +const std::string voltage2 = "/sys/bus/iio/devices/iio:device0/in_voltage2_raw"; +const std::string voltage3 = "/sys/bus/iio/devices/iio:device0/in_voltage3_raw"; +const std::string voltage4 = "/sys/bus/iio/devices/iio:device0/in_voltage4_raw"; + + +class Dail{ +public: + Dail(){ + dail_value = {0}; + dail_inti(); + } + HG_Dail_Struct GetValue(){ + return dail_value; + } +private: + void dail_inti() + { + std::vector voltages; + voltages.push_back(voltage0); + voltages.push_back(voltage2); + voltages.push_back(voltage3); + voltages.push_back(voltage4); + for(int i = 0 ; i +#include +#include +#include +#include +#include + +class FileTools +{ +private: + std::string mPath; + +public: + FileTools(std::string path) + { + mPath = path; + } + void createLog(std::string log) + { + time_t now = time(0); + tm *ltm = localtime(&now); + char loc_date[30]; + sprintf(loc_date, "%d%02d%02d %d:%d:%d", 1900 + ltm->tm_year, 1 + ltm->tm_mon, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec); + std::ofstream ofs(mPath); + ofs << loc_date << ": " << log << std::endl; + ofs.close(); + } + void append_log(std::string log, bool printTime = true) + { + std::ofstream ofs(mPath, std::ios::app); + if (printTime) + { + time_t now = time(0); + tm *ltm = localtime(&now); + char loc_date[30]; + sprintf(loc_date, "%d%02d%02d %d:%d:%d", 1900 + ltm->tm_year, 1 + ltm->tm_mon, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec); + ofs << loc_date << ": " << log << std::endl; + } + else + { + ofs << " " << log << std::endl; + } + ofs.close(); + } + + void clear() + { + try + { + std::fstream fout(mPath, std::ios::out | std::ios::trunc); + fout.close(); + } + catch (std::exception &e) + { + //LOG("error happened: %s \n", e.what()); + } + } +}; \ No newline at end of file diff --git a/packages/common.pkg/include/json.hpp b/packages/common.pkg/include/json.hpp new file mode 100644 index 0000000..06da815 --- /dev/null +++ b/packages/common.pkg/include/json.hpp @@ -0,0 +1,22875 @@ +/* + __ _____ _____ _____ + __| | __| | | | JSON for Modern C++ +| | |__ | | | | | | version 3.7.3 +|_____|_____|_____|_|___| https://github.com/nlohmann/json + +Licensed under the MIT License . +SPDX-License-Identifier: MIT +Copyright (c) 2013-2019 Niels Lohmann . + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +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 +AUTHORS OR COPYRIGHT HOLDERS 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. +*/ + +#ifndef INCLUDE_NLOHMANN_JSON_HPP_ +#define INCLUDE_NLOHMANN_JSON_HPP_ + +#define NLOHMANN_JSON_VERSION_MAJOR 3 +#define NLOHMANN_JSON_VERSION_MINOR 7 +#define NLOHMANN_JSON_VERSION_PATCH 3 + +#include // all_of, find, for_each +#include // assert +#include // and, not, or +#include // nullptr_t, ptrdiff_t, size_t +#include // hash, less +#include // initializer_list +#include // istream, ostream +#include // random_access_iterator_tag +#include // unique_ptr +#include // accumulate +#include // string, stoi, to_string +#include // declval, forward, move, pair, swap +#include // vector + +// #include + + +#include + +// #include + + +#include // transform +#include // array +#include // and, not +#include // forward_list +#include // inserter, front_inserter, end +#include // map +#include // string +#include // tuple, make_tuple +#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible +#include // unordered_map +#include // pair, declval +#include // valarray + +// #include + + +#include // exception +#include // runtime_error +#include // to_string + +// #include + + +#include // size_t + +namespace nlohmann +{ +namespace detail +{ +/// struct to capture the start position of the current token +struct position_t +{ + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } +}; + +} // namespace detail +} // namespace nlohmann + +// #include + + +#include // pair +// #include +/* Hedley - https://nemequ.github.io/hedley + * Created by Evan Nemerson + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to + * the public domain worldwide. This software is distributed without + * any warranty. + * + * For details, see . + * SPDX-License-Identifier: CC0-1.0 + */ + +#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 11) +#if defined(JSON_HEDLEY_VERSION) + #undef JSON_HEDLEY_VERSION +#endif +#define JSON_HEDLEY_VERSION 11 + +#if defined(JSON_HEDLEY_STRINGIFY_EX) + #undef JSON_HEDLEY_STRINGIFY_EX +#endif +#define JSON_HEDLEY_STRINGIFY_EX(x) #x + +#if defined(JSON_HEDLEY_STRINGIFY) + #undef JSON_HEDLEY_STRINGIFY +#endif +#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) + +#if defined(JSON_HEDLEY_CONCAT_EX) + #undef JSON_HEDLEY_CONCAT_EX +#endif +#define JSON_HEDLEY_CONCAT_EX(a,b) a##b + +#if defined(JSON_HEDLEY_CONCAT) + #undef JSON_HEDLEY_CONCAT +#endif +#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) + +#if defined(JSON_HEDLEY_VERSION_ENCODE) + #undef JSON_HEDLEY_VERSION_ENCODE +#endif +#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) + #undef JSON_HEDLEY_VERSION_DECODE_MAJOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) + #undef JSON_HEDLEY_VERSION_DECODE_MINOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) + #undef JSON_HEDLEY_VERSION_DECODE_REVISION +#endif +#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) + +#if defined(JSON_HEDLEY_GNUC_VERSION) + #undef JSON_HEDLEY_GNUC_VERSION +#endif +#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#elif defined(__GNUC__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) +#endif + +#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) + #undef JSON_HEDLEY_GNUC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GNUC_VERSION) + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION) + #undef JSON_HEDLEY_MSVC_VERSION +#endif +#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) +#elif defined(_MSC_FULL_VER) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) +#elif defined(_MSC_VER) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) + #undef JSON_HEDLEY_MSVC_VERSION_CHECK +#endif +#if !defined(_MSC_VER) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) +#elif defined(_MSC_VER) && (_MSC_VER >= 1200) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) +#else + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION) + #undef JSON_HEDLEY_INTEL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) +#elif defined(__INTEL_COMPILER) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_VERSION) + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION) + #undef JSON_HEDLEY_PGI_VERSION +#endif +#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) + #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) + #undef JSON_HEDLEY_PGI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PGI_VERSION) + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #undef JSON_HEDLEY_SUNPRO_VERSION +#endif +#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) +#elif defined(__SUNPRO_C) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) +#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) +#elif defined(__SUNPRO_CC) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) + #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION +#endif +#if defined(__EMSCRIPTEN__) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION) + #undef JSON_HEDLEY_ARM_VERSION +#endif +#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) +#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) + #undef JSON_HEDLEY_ARM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_ARM_VERSION) + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION) + #undef JSON_HEDLEY_IBM_VERSION +#endif +#if defined(__ibmxl__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) +#elif defined(__xlC__) && defined(__xlC_ver__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) +#elif defined(__xlC__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) + #undef JSON_HEDLEY_IBM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IBM_VERSION) + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_VERSION) + #undef JSON_HEDLEY_TI_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) + #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_VERSION_CHECK) + #undef JSON_HEDLEY_TI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_VERSION) + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION) + #undef JSON_HEDLEY_CRAY_VERSION +#endif +#if defined(_CRAYC) + #if defined(_RELEASE_PATCHLEVEL) + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) + #else + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) + #undef JSON_HEDLEY_CRAY_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_CRAY_VERSION) + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION) + #undef JSON_HEDLEY_IAR_VERSION +#endif +#if defined(__IAR_SYSTEMS_ICC__) + #if __VER__ > 1000 + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) + #else + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(VER / 100, __VER__ % 100, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) + #undef JSON_HEDLEY_IAR_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IAR_VERSION) + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION) + #undef JSON_HEDLEY_TINYC_VERSION +#endif +#if defined(__TINYC__) + #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) + #undef JSON_HEDLEY_TINYC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION) + #undef JSON_HEDLEY_DMC_VERSION +#endif +#if defined(__DMC__) + #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) + #undef JSON_HEDLEY_DMC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_DMC_VERSION) + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #undef JSON_HEDLEY_COMPCERT_VERSION +#endif +#if defined(__COMPCERT_VERSION__) + #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) + #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION) + #undef JSON_HEDLEY_PELLES_VERSION +#endif +#if defined(__POCC__) + #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) + #undef JSON_HEDLEY_PELLES_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PELLES_VERSION) + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION) + #undef JSON_HEDLEY_GCC_VERSION +#endif +#if \ + defined(JSON_HEDLEY_GNUC_VERSION) && \ + !defined(__clang__) && \ + !defined(JSON_HEDLEY_INTEL_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_ARM_VERSION) && \ + !defined(JSON_HEDLEY_TI_VERSION) && \ + !defined(__COMPCERT__) + #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE +#endif +#if \ + defined(__has_cpp_attribute) && \ + defined(__cplusplus) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS +#endif +#if !defined(__cplusplus) || !defined(__has_cpp_attribute) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#elif \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ + (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_BUILTIN) + #undef JSON_HEDLEY_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) +#else + #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) + #undef JSON_HEDLEY_GNUC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) + #undef JSON_HEDLEY_GCC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_FEATURE) + #undef JSON_HEDLEY_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) +#else + #define JSON_HEDLEY_HAS_FEATURE(feature) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) + #undef JSON_HEDLEY_GNUC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) + #undef JSON_HEDLEY_GCC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_EXTENSION) + #undef JSON_HEDLEY_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) +#else + #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) + #undef JSON_HEDLEY_GNUC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) + #undef JSON_HEDLEY_GCC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_WARNING) + #undef JSON_HEDLEY_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) +#else + #define JSON_HEDLEY_HAS_WARNING(warning) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) + #undef JSON_HEDLEY_GNUC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_WARNING) + #undef JSON_HEDLEY_GCC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ +#endif +#if defined(__cplusplus) && JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +#else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x +#endif + +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + defined(__clang__) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) + #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_PRAGMA(value) __pragma(value) +#else + #define JSON_HEDLEY_PRAGMA(value) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) + #undef JSON_HEDLEY_DIAGNOSTIC_PUSH +#endif +#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) + #undef JSON_HEDLEY_DIAGNOSTIC_POP +#endif +#if defined(__clang__) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) + #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) +#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") +#elif JSON_HEDLEY_TI_VERSION_CHECK(8,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_PUSH + #define JSON_HEDLEY_DIAGNOSTIC_POP +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) +#elif JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) +#elif JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") +#elif JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif + +#if defined(JSON_HEDLEY_DEPRECATED) + #undef JSON_HEDLEY_DEPRECATED +#endif +#if defined(JSON_HEDLEY_DEPRECATED_FOR) + #undef JSON_HEDLEY_DEPRECATED_FOR +#endif +#if defined(__cplusplus) && (__cplusplus >= 201402L) + #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) +#elif \ + JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,3,0) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") +#else + #define JSON_HEDLEY_DEPRECATED(since) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) +#endif + +#if defined(JSON_HEDLEY_UNAVAILABLE) + #undef JSON_HEDLEY_UNAVAILABLE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) +#else + #define JSON_HEDLEY_UNAVAILABLE(available_since) +#endif + +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT +#endif +#if defined(__cplusplus) && (__cplusplus >= 201703L) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) +#elif defined(_Check_return_) /* SAL */ + #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ +#else + #define JSON_HEDLEY_WARN_UNUSED_RESULT +#endif + +#if defined(JSON_HEDLEY_SENTINEL) + #undef JSON_HEDLEY_SENTINEL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) + #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) +#else + #define JSON_HEDLEY_SENTINEL(position) +#endif + +#if defined(JSON_HEDLEY_NO_RETURN) + #undef JSON_HEDLEY_NO_RETURN +#endif +#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NO_RETURN __noreturn +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + #define JSON_HEDLEY_NO_RETURN _Noreturn +#elif defined(__cplusplus) && (__cplusplus >= 201103L) + #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(18,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(17,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#else + #define JSON_HEDLEY_NO_RETURN +#endif + +#if defined(JSON_HEDLEY_NO_ESCAPE) + #undef JSON_HEDLEY_NO_ESCAPE +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) + #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) +#else + #define JSON_HEDLEY_NO_ESCAPE +#endif + +#if defined(JSON_HEDLEY_UNREACHABLE) + #undef JSON_HEDLEY_UNREACHABLE +#endif +#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) + #undef JSON_HEDLEY_UNREACHABLE_RETURN +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) + #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) + #define JSON_HEDLEY_UNREACHABLE() __assume(0) +#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) + #if defined(__cplusplus) + #define JSON_HEDLEY_UNREACHABLE() std::_nassert(0) + #else + #define JSON_HEDLEY_UNREACHABLE() _nassert(0) + #endif + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return value +#elif defined(EXIT_FAILURE) + #define JSON_HEDLEY_UNREACHABLE() abort() +#else + #define JSON_HEDLEY_UNREACHABLE() + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return value +#endif +#if !defined(JSON_HEDLEY_UNREACHABLE_RETURN) + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() +#endif + +#if defined(JSON_HEDLEY_ASSUME) + #undef JSON_HEDLEY_ASSUME +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_ASSUME(expr) __assume(expr) +#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) + #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) +#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) + #if defined(__cplusplus) + #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) + #else + #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) + #endif +#elif \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && !defined(JSON_HEDLEY_ARM_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) + #define JSON_HEDLEY_ASSUME(expr) ((void) ((expr) ? 1 : (__builtin_unreachable(), 1))) +#else + #define JSON_HEDLEY_ASSUME(expr) ((void) (expr)) +#endif + +JSON_HEDLEY_DIAGNOSTIC_PUSH +#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") + #pragma clang diagnostic ignored "-Wpedantic" +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) + #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif +#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) + #if defined(__clang__) + #pragma clang diagnostic ignored "-Wvariadic-macros" + #elif defined(JSON_HEDLEY_GCC_VERSION) + #pragma GCC diagnostic ignored "-Wvariadic-macros" + #endif +#endif +#if defined(JSON_HEDLEY_NON_NULL) + #undef JSON_HEDLEY_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) +#else + #define JSON_HEDLEY_NON_NULL(...) +#endif +JSON_HEDLEY_DIAGNOSTIC_POP + +#if defined(JSON_HEDLEY_PRINTF_FORMAT) + #undef JSON_HEDLEY_PRINTF_FORMAT +#endif +#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) +#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) +#else + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) +#endif + +#if defined(JSON_HEDLEY_CONSTEXPR) + #undef JSON_HEDLEY_CONSTEXPR +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) + #endif +#endif +#if !defined(JSON_HEDLEY_CONSTEXPR) + #define JSON_HEDLEY_CONSTEXPR +#endif + +#if defined(JSON_HEDLEY_PREDICT) + #undef JSON_HEDLEY_PREDICT +#endif +#if defined(JSON_HEDLEY_LIKELY) + #undef JSON_HEDLEY_LIKELY +#endif +#if defined(JSON_HEDLEY_UNLIKELY) + #undef JSON_HEDLEY_UNLIKELY +#endif +#if defined(JSON_HEDLEY_UNPREDICTABLE) + #undef JSON_HEDLEY_UNPREDICTABLE +#endif +#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) + #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable(!!(expr)) +#endif +#if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) +# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability(expr, value, probability) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1, probability) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0, probability) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +#if !defined(JSON_HEDLEY_BUILTIN_UNPREDICTABLE) + #define JSON_HEDLEY_BUILTIN_UNPREDICTABLE(expr) __builtin_expect_with_probability(!!(expr), 1, 0.5) +#endif +#elif \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) +# define JSON_HEDLEY_PREDICT(expr, expected, probability) \ + (((probability) >= 0.9) ? __builtin_expect(!!(expr), (expected)) : (((void) (expected)), !!(expr))) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ + (__extension__ ({ \ + JSON_HEDLEY_CONSTEXPR double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ + })) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ + (__extension__ ({ \ + JSON_HEDLEY_CONSTEXPR double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ + })) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +#else +# define JSON_HEDLEY_PREDICT(expr, expected, probability) (((void) (expected)), !!(expr)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_LIKELY(expr) (!!(expr)) +# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) +#endif +#if !defined(JSON_HEDLEY_UNPREDICTABLE) + #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) +#endif + +#if defined(JSON_HEDLEY_MALLOC) + #undef JSON_HEDLEY_MALLOC +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(14, 0, 0) + #define JSON_HEDLEY_MALLOC __declspec(restrict) +#else + #define JSON_HEDLEY_MALLOC +#endif + +#if defined(JSON_HEDLEY_PURE) + #undef JSON_HEDLEY_PURE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_PURE __attribute__((__pure__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") +#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") +#else + #define JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_CONST) + #undef JSON_HEDLEY_CONST +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_CONST __attribute__((__const__)) +#elif \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_CONST _Pragma("no_side_effect") +#else + #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_RESTRICT) + #undef JSON_HEDLEY_RESTRICT +#endif +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT restrict +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + defined(__clang__) + #define JSON_HEDLEY_RESTRICT __restrict +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT _Restrict +#else + #define JSON_HEDLEY_RESTRICT +#endif + +#if defined(JSON_HEDLEY_INLINE) + #undef JSON_HEDLEY_INLINE +#endif +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + (defined(__cplusplus) && (__cplusplus >= 199711L)) + #define JSON_HEDLEY_INLINE inline +#elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) + #define JSON_HEDLEY_INLINE __inline__ +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_INLINE __inline +#else + #define JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_ALWAYS_INLINE) + #undef JSON_HEDLEY_ALWAYS_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + #define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) + #define JSON_HEDLEY_ALWAYS_INLINE __forceinline +#elif JSON_HEDLEY_TI_VERSION_CHECK(7,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") +#else + #define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_NEVER_INLINE) + #undef JSON_HEDLEY_NEVER_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") +#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#else + #define JSON_HEDLEY_NEVER_INLINE +#endif + +#if defined(JSON_HEDLEY_PRIVATE) + #undef JSON_HEDLEY_PRIVATE +#endif +#if defined(JSON_HEDLEY_PUBLIC) + #undef JSON_HEDLEY_PUBLIC +#endif +#if defined(JSON_HEDLEY_IMPORT) + #undef JSON_HEDLEY_IMPORT +#endif +#if defined(_WIN32) || defined(__CYGWIN__) + #define JSON_HEDLEY_PRIVATE + #define JSON_HEDLEY_PUBLIC __declspec(dllexport) + #define JSON_HEDLEY_IMPORT __declspec(dllimport) +#else + #if \ + JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_EABI__) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) + #define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) + #define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) + #else + #define JSON_HEDLEY_PRIVATE + #define JSON_HEDLEY_PUBLIC + #endif + #define JSON_HEDLEY_IMPORT extern +#endif + +#if defined(JSON_HEDLEY_NO_THROW) + #undef JSON_HEDLEY_NO_THROW +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NO_THROW __declspec(nothrow) +#else + #define JSON_HEDLEY_NO_THROW +#endif + +#if defined(JSON_HEDLEY_FALL_THROUGH) + #undef JSON_HEDLEY_FALL_THROUGH +#endif +#if JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(fallthrough,7,0,0) && !defined(JSON_HEDLEY_PGI_VERSION) + #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) +#elif defined(__fallthrough) /* SAL */ + #define JSON_HEDLEY_FALL_THROUGH __fallthrough +#else + #define JSON_HEDLEY_FALL_THROUGH +#endif + +#if defined(JSON_HEDLEY_RETURNS_NON_NULL) + #undef JSON_HEDLEY_RETURNS_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) + #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) +#elif defined(_Ret_notnull_) /* SAL */ + #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ +#else + #define JSON_HEDLEY_RETURNS_NON_NULL +#endif + +#if defined(JSON_HEDLEY_ARRAY_PARAM) + #undef JSON_HEDLEY_ARRAY_PARAM +#endif +#if \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(__STDC_NO_VLA__) && \ + !defined(__cplusplus) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_ARRAY_PARAM(name) (name) +#else + #define JSON_HEDLEY_ARRAY_PARAM(name) +#endif + +#if defined(JSON_HEDLEY_IS_CONSTANT) + #undef JSON_HEDLEY_IS_CONSTANT +#endif +#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) + #undef JSON_HEDLEY_REQUIRE_CONSTEXPR +#endif +/* JSON_HEDLEY_IS_CONSTEXPR_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #undef JSON_HEDLEY_IS_CONSTEXPR_ +#endif +#if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(6,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) + #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) +#endif +#if !defined(__cplusplus) +# if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) +#endif +# elif \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && !defined(JSON_HEDLEY_SUNPRO_VERSION) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ + JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) +#endif +# elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + defined(JSON_HEDLEY_INTEL_VERSION) || \ + defined(JSON_HEDLEY_TINYC_VERSION) || \ + defined(JSON_HEDLEY_TI_VERSION) || \ + defined(__clang__) +# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ + sizeof(void) != \ + sizeof(*( \ + 1 ? \ + ((void*) ((expr) * 0L) ) : \ +((struct { char v[sizeof(void) * 2]; } *) 1) \ + ) \ + ) \ + ) +# endif +#endif +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) +#else + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) (0) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) +#endif + +#if defined(JSON_HEDLEY_BEGIN_C_DECLS) + #undef JSON_HEDLEY_BEGIN_C_DECLS +#endif +#if defined(JSON_HEDLEY_END_C_DECLS) + #undef JSON_HEDLEY_END_C_DECLS +#endif +#if defined(JSON_HEDLEY_C_DECL) + #undef JSON_HEDLEY_C_DECL +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { + #define JSON_HEDLEY_END_C_DECLS } + #define JSON_HEDLEY_C_DECL extern "C" +#else + #define JSON_HEDLEY_BEGIN_C_DECLS + #define JSON_HEDLEY_END_C_DECLS + #define JSON_HEDLEY_C_DECL +#endif + +#if defined(JSON_HEDLEY_STATIC_ASSERT) + #undef JSON_HEDLEY_STATIC_ASSERT +#endif +#if \ + !defined(__cplusplus) && ( \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ + JSON_HEDLEY_HAS_FEATURE(c_static_assert) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + defined(_Static_assert) \ + ) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) +#elif \ + (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ + (defined(__cplusplus) && JSON_HEDLEY_TI_VERSION_CHECK(8,3,0)) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) +#else +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) +#endif + +#if defined(JSON_HEDLEY_CONST_CAST) + #undef JSON_HEDLEY_CONST_CAST +#endif +#if defined(__cplusplus) +# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) +#elif \ + JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_REINTERPRET_CAST) + #undef JSON_HEDLEY_REINTERPRET_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) +#else + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (*((T*) &(expr))) +#endif + +#if defined(JSON_HEDLEY_STATIC_CAST) + #undef JSON_HEDLEY_STATIC_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) +#else + #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_CPP_CAST) + #undef JSON_HEDLEY_CPP_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_CPP_CAST(T, expr) static_cast(expr) +#else + #define JSON_HEDLEY_CPP_CAST(T, expr) (expr) +#endif + +#if defined(JSON_HEDLEY_NULL) + #undef JSON_HEDLEY_NULL +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) + #elif defined(NULL) + #define JSON_HEDLEY_NULL NULL + #else + #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) + #endif +#elif defined(NULL) + #define JSON_HEDLEY_NULL NULL +#else + #define JSON_HEDLEY_NULL ((void*) 0) +#endif + +#if defined(JSON_HEDLEY_MESSAGE) + #undef JSON_HEDLEY_MESSAGE +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_MESSAGE(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(message msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) +#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_WARNING) + #undef JSON_HEDLEY_WARNING +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_WARNING(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(clang warning msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_REQUIRE) + #undef JSON_HEDLEY_REQUIRE +#endif +#if defined(JSON_HEDLEY_REQUIRE_MSG) + #undef JSON_HEDLEY_REQUIRE_MSG +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) +# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") +# define JSON_HEDLEY_REQUIRE(expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), #expr, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), msg, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) +# endif +#else +# define JSON_HEDLEY_REQUIRE(expr) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) +#endif + +#if defined(JSON_HEDLEY_FLAGS) + #undef JSON_HEDLEY_FLAGS +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) + #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) +#endif + +#if defined(JSON_HEDLEY_FLAGS_CAST) + #undef JSON_HEDLEY_FLAGS_CAST +#endif +#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) +# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("warning(disable:188)") \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) +#endif + +#if defined(JSON_HEDLEY_EMPTY_BASES) + #undef JSON_HEDLEY_EMPTY_BASES +#endif +#if JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0) + #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) +#else + #define JSON_HEDLEY_EMPTY_BASES +#endif + +/* Remaining macros are deprecated. */ + +#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK +#endif +#if defined(__clang__) + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) +#else + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) + #undef JSON_HEDLEY_CLANG_HAS_BUILTIN +#endif +#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) + +#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) + #undef JSON_HEDLEY_CLANG_HAS_FEATURE +#endif +#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) + +#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) + #undef JSON_HEDLEY_CLANG_HAS_EXTENSION +#endif +#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) + +#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) + #undef JSON_HEDLEY_CLANG_HAS_WARNING +#endif +#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) + +#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ + + +// This file contains all internal macro definitions +// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them + +// exclude unsupported compilers +#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) + #if defined(__clang__) + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 + #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #endif +#endif + +// C++ language standard detection +#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 +#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 +#endif + +// disable float-equal warnings on GCC/clang +#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + +// disable documentation warnings on clang +#if defined(__clang__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdocumentation" +#endif + +// allow to disable exceptions +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) + #define JSON_THROW(exception) throw exception + #define JSON_TRY try + #define JSON_CATCH(exception) catch(exception) + #define JSON_INTERNAL_CATCH(exception) catch(exception) +#else + #include + #define JSON_THROW(exception) std::abort() + #define JSON_TRY if(true) + #define JSON_CATCH(exception) if(false) + #define JSON_INTERNAL_CATCH(exception) if(false) +#endif + +// override exception macros +#if defined(JSON_THROW_USER) + #undef JSON_THROW + #define JSON_THROW JSON_THROW_USER +#endif +#if defined(JSON_TRY_USER) + #undef JSON_TRY + #define JSON_TRY JSON_TRY_USER +#endif +#if defined(JSON_CATCH_USER) + #undef JSON_CATCH + #define JSON_CATCH JSON_CATCH_USER + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_CATCH_USER +#endif +#if defined(JSON_INTERNAL_CATCH_USER) + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER +#endif + +/*! +@brief macro to briefly define a mapping between an enum and JSON +@def NLOHMANN_JSON_SERIALIZE_ENUM +@since version 3.4.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + } + +// Ugly macros to avoid uglier copy-paste when specializing basic_json. They +// may be removed in the future once the class is split. + +#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ + template class ObjectType, \ + template class ArrayType, \ + class StringType, class BooleanType, class NumberIntegerType, \ + class NumberUnsignedType, class NumberFloatType, \ + template class AllocatorType, \ + template class JSONSerializer> + +#define NLOHMANN_BASIC_JSON_TPL \ + basic_json + + +namespace nlohmann +{ +namespace detail +{ +//////////////// +// exceptions // +//////////////// + +/*! +@brief general exception of the @ref basic_json class + +This class is an extension of `std::exception` objects with a member @a id for +exception ids. It is used as the base class for all exceptions thrown by the +@ref basic_json class. This class can hence be used as "wildcard" to catch +exceptions. + +Subclasses: +- @ref parse_error for exceptions indicating a parse error +- @ref invalid_iterator for exceptions indicating errors with iterators +- @ref type_error for exceptions indicating executing a member function with + a wrong type +- @ref out_of_range for exceptions indicating access out of the defined range +- @ref other_error for exceptions indicating other library errors + +@internal +@note To have nothrow-copy-constructible exceptions, we internally use + `std::runtime_error` which can cope with arbitrary-length error messages. + Intermediate strings are built with static functions and then passed to + the actual constructor. +@endinternal + +@liveexample{The following code shows how arbitrary library exceptions can be +caught.,exception} + +@since version 3.0.0 +*/ +class exception : public std::exception +{ + public: + /// returns the explanatory string + JSON_HEDLEY_RETURNS_NON_NULL + const char* what() const noexcept override + { + return m.what(); + } + + /// the id of the exception + const int id; + + protected: + JSON_HEDLEY_NON_NULL(3) + exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} + + static std::string name(const std::string& ename, int id_) + { + return "[json.exception." + ename + "." + std::to_string(id_) + "] "; + } + + private: + /// an exception object as storage for error messages + std::runtime_error m; +}; + +/*! +@brief exception indicating a parse error + +This exception is thrown by the library when a parse error occurs. Parse errors +can occur during the deserialization of JSON text, CBOR, MessagePack, as well +as when using JSON Patch. + +Member @a byte holds the byte index of the last read character in the input +file. + +Exceptions have ids 1xx. + +name / id | example message | description +------------------------------ | --------------- | ------------------------- +json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position. +json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point. +json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid. +json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects. +json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors. +json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`. +json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character. +json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences. +json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number. +json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read. +json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read. +json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read. +json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet). + +@note For an input with n bytes, 1 is the index of the first character and n+1 + is the index of the terminating null byte or the end of file. This also + holds true when reading a byte vector (CBOR or MessagePack). + +@liveexample{The following code shows how a `parse_error` exception can be +caught.,parse_error} + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref out_of_range for exceptions indicating access out of the defined range +@sa - @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class parse_error : public exception +{ + public: + /*! + @brief create a parse error exception + @param[in] id_ the id of the exception + @param[in] pos the position where the error occurred (or with + chars_read_total=0 if the position cannot be + determined) + @param[in] what_arg the explanatory string + @return parse_error object + */ + static parse_error create(int id_, const position_t& pos, const std::string& what_arg) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + position_string(pos) + ": " + what_arg; + return parse_error(id_, pos.chars_read_total, w.c_str()); + } + + static parse_error create(int id_, std::size_t byte_, const std::string& what_arg) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + + ": " + what_arg; + return parse_error(id_, byte_, w.c_str()); + } + + /*! + @brief byte index of the parse error + + The byte index of the last read character in the input file. + + @note For an input with n bytes, 1 is the index of the first character and + n+1 is the index of the terminating null byte or the end of file. + This also holds true when reading a byte vector (CBOR or MessagePack). + */ + const std::size_t byte; + + private: + parse_error(int id_, std::size_t byte_, const char* what_arg) + : exception(id_, what_arg), byte(byte_) {} + + static std::string position_string(const position_t& pos) + { + return " at line " + std::to_string(pos.lines_read + 1) + + ", column " + std::to_string(pos.chars_read_current_line); + } +}; + +/*! +@brief exception indicating errors with iterators + +This exception is thrown if iterators passed to a library function do not match +the expected semantics. + +Exceptions have ids 2xx. + +name / id | example message | description +----------------------------------- | --------------- | ------------------------- +json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. +json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion. +json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from. +json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid. +json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid. +json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range. +json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key. +json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. +json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. +json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. +json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to. +json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container. +json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered. +json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin(). + +@liveexample{The following code shows how an `invalid_iterator` exception can be +caught.,invalid_iterator} + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref out_of_range for exceptions indicating access out of the defined range +@sa - @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class invalid_iterator : public exception +{ + public: + static invalid_iterator create(int id_, const std::string& what_arg) + { + std::string w = exception::name("invalid_iterator", id_) + what_arg; + return invalid_iterator(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + invalid_iterator(int id_, const char* what_arg) + : exception(id_, what_arg) {} +}; + +/*! +@brief exception indicating executing a member function with a wrong type + +This exception is thrown in case of a type error; that is, a library function is +executed on a JSON value whose type does not match the expected semantics. + +Exceptions have ids 3xx. + +name / id | example message | description +----------------------------- | --------------- | ------------------------- +json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead. +json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types. +json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &. +json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types. +json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types. +json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types. +json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types. +json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types. +json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types. +json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types. +json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types. +json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types. +json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined. +json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers. +json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive. +json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. | +json.exception.type_error.317 | JSON value cannot be serialized to requested format | The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) | + +@liveexample{The following code shows how a `type_error` exception can be +caught.,type_error} + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref out_of_range for exceptions indicating access out of the defined range +@sa - @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class type_error : public exception +{ + public: + static type_error create(int id_, const std::string& what_arg) + { + std::string w = exception::name("type_error", id_) + what_arg; + return type_error(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; + +/*! +@brief exception indicating access out of the defined range + +This exception is thrown in case a library function is called on an input +parameter that exceeds the expected range, for instance in case of array +indices or nonexisting object keys. + +Exceptions have ids 4xx. + +name / id | example message | description +------------------------------- | --------------- | ------------------------- +json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1. +json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it. +json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object. +json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved. +json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value. +json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF. +json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. | +json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. | +json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string | + +@liveexample{The following code shows how an `out_of_range` exception can be +caught.,out_of_range} + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class out_of_range : public exception +{ + public: + static out_of_range create(int id_, const std::string& what_arg) + { + std::string w = exception::name("out_of_range", id_) + what_arg; + return out_of_range(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; + +/*! +@brief exception indicating other library errors + +This exception is thrown in case of errors that cannot be classified with the +other exception types. + +Exceptions have ids 5xx. + +name / id | example message | description +------------------------------ | --------------- | ------------------------- +json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed. + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref out_of_range for exceptions indicating access out of the defined range + +@liveexample{The following code shows how an `other_error` exception can be +caught.,other_error} + +@since version 3.0.0 +*/ +class other_error : public exception +{ + public: + static other_error create(int id_, const std::string& what_arg) + { + std::string w = exception::name("other_error", id_) + what_arg; + return other_error(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + + +#include // not +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type + +namespace nlohmann +{ +namespace detail +{ +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +template +using uncvref_t = typename std::remove_cv::type>::type; + +// implementation of C++14 index_sequence and affiliates +// source: https://stackoverflow.com/a/32223343 +template +struct index_sequence +{ + using type = index_sequence; + using value_type = std::size_t; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +template +struct merge_and_renumber; + +template +struct merge_and_renumber, index_sequence> + : index_sequence < I1..., (sizeof...(I1) + I2)... > {}; + +template +struct make_index_sequence + : merge_and_renumber < typename make_index_sequence < N / 2 >::type, + typename make_index_sequence < N - N / 2 >::type > {}; + +template<> struct make_index_sequence<0> : index_sequence<> {}; +template<> struct make_index_sequence<1> : index_sequence<0> {}; + +template +using index_sequence_for = make_index_sequence; + +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; + +// taken from ranges-v3 +template +struct static_const +{ + static constexpr T value{}; +}; + +template +constexpr T static_const::value; +} // namespace detail +} // namespace nlohmann + +// #include + + +#include // not +#include // numeric_limits +#include // false_type, is_constructible, is_integral, is_same, true_type +#include // declval + +// #include + + +#include // random_access_iterator_tag + +// #include + + +namespace nlohmann +{ +namespace detail +{ +template struct make_void +{ + using type = void; +}; +template using void_t = typename make_void::type; +} // namespace detail +} // namespace nlohmann + +// #include + + +namespace nlohmann +{ +namespace detail +{ +template +struct iterator_types {}; + +template +struct iterator_types < + It, + void_t> +{ + using difference_type = typename It::difference_type; + using value_type = typename It::value_type; + using pointer = typename It::pointer; + using reference = typename It::reference; + using iterator_category = typename It::iterator_category; +}; + +// This is required as some compilers implement std::iterator_traits in a way that +// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. +template +struct iterator_traits +{ +}; + +template +struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> + : iterator_types +{ +}; + +template +struct iterator_traits::value>> +{ + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = T*; + using reference = T&; +}; +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + +// #include + + +#include + +// #include + + +// http://en.cppreference.com/w/cpp/experimental/is_detected +namespace nlohmann +{ +namespace detail +{ +struct nonesuch +{ + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + nonesuch(nonesuch const&&) = delete; + void operator=(nonesuch const&) = delete; + void operator=(nonesuch&&) = delete; +}; + +template class Op, + class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; + +template