diff --git a/firmware/90-hantek.rules b/firmware/90-hantek.rules index b51dabb..487bd84 100644 --- a/firmware/90-hantek.rules +++ b/firmware/90-hantek.rules @@ -18,3 +18,7 @@ ATTRS{idVendor}=="04b5", ATTRS{idProduct}=="5200", MODE="0660", GROUP="plugdev" # Hantek DSO-5200A SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", ENV{PRODUCT}=="4b4/520a/*", RUN+="/sbin/fxload -t fx2 -I /usr/local/share/hantek/dso5200ax86-firmware.hex -s /usr/local/share/hantek/dso5200ax86-loader.hex -D $env{DEVNAME}" ATTRS{idVendor}=="04b5", ATTRS{idProduct}=="520a", MODE="0660", GROUP="plugdev" + +# Hantek DSO-6022BE +SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", ENV{PRODUCT}=="4b4/6022/*", RUN+="/sbin/fxload -t fx2 -I /usr/local/share/hantek/dso6022be-firmware.hex -s /usr/local/share/hantek/dso6022be-loader.hex -D $env{DEVNAME}" +ATTRS{idVendor}=="04b5", ATTRS{idProduct}=="6022", MODE="0660", GROUP="plugdev" diff --git a/firmware/dso6022be-firmware.hex b/firmware/dso6022be-firmware.hex new file mode 100644 index 0000000..e875bd2 --- /dev/null +++ b/firmware/dso6022be-firmware.hex @@ -0,0 +1,405 @@ +:02095e00c105d1 +:100cb80090e6007410f0120f1800000090e612740d +:100cc800a0f0000000e490e613f000000090e614a5 +:100cd80074e0f0000000e490e615f000000090e6f3 +:100ce800047480f00000007402f00000007406f044 +:100cf800000000e4f000000090e61804f000000096 +:100d08007411f000000090e61a7409f000000090d9 +:100d1800e6d27402f000000090e6e214f000000051 +:100d2800e490e671f075b4ff90e670f075b280c299 +:100d3800a4c2a3c2a2c2a7c2a6c2a5f51df51a12d3 +:0a0d4800130990e67ae04401f0225e +:100b7b00e51d64017031751d0290e6f574fff09070 +:100b8b00e6047480f00000007402f00000007406ac +:100b9b00f0000000e4f0000000fffe000fbf0001ba +:100bab000ebe03f7bfe8f4e5bb30e72590e6f4e0b3 +:100bbb0030e01ee5ac20e019e5bb30e7fb90e6d05a +:100bcb007428f0000000e490e6d1f000000075bb43 +:010bdb000613 +:010bdc0022f6 +:02002800d322e1 +:02004000d322c9 +:02004600d322c3 +:10104c0090e680e030e71800000090e6247402f08f +:10105c00000000e490e625f0000000d205801600a8 +:10106c000000e490e624f000000090e6257440f0c7 +:0d107c00000000c20590e6bae0f51bd3228b +:1012dd0090e740e51bf0e490e68af090e68b04f091 +:0212ed00d3220a +:0813010090e6bae0f518d322d2 +:1012ef0090e740e518f0e490e68af090e68b04f082 +:0212ff00d322f8 +:02004800d322c1 +:02004e00d322bb +:02005000d322b9 +:1000560090e678e05410ffc4540f4450f51913e4a9 +:1000660033f51cd20290e6b9e0245e605024f060bd +:100076003024d2b4080040030204d590008f75f0f6 +:1000860003a4c58325f0c5837302024b02029602c0 +:1000960002dc0204460204d50204d50204d5020499 +:1000a60065a205e43390e740f0e490e68af090e636 +:1000b6008b04f090e6a0e04480f00204d790e6ba04 +:1000c600e0752d00f52ea3e0fee4ee422d90e6be8f +:1000d600e0752f00f530a3e0fee4ee422f90e6b87f +:1000e600e064c060030201b3e530452f70030204eb +:1000f600d790e6a0e020e1f9c3e5309440e52f94df +:10010600005008852f3185303280067531007532f2 +:100116004090e6b9e0b4a335e4f533f534c3e534ed +:100126009532e53395315060e52e2534f582e52d7f +:100136003533f583e0ff74402534f582e434e7f582 +:1001460083eff00534e5347002053380d0e4f533ef +:10015600f534c3e5349532e53395315018744025ae +:1001660034f582e434e7f58374cdf00534e5347074 +:1001760002053380ddad327ae779407ee77f40ab1a +:1001860007af2eae2d120fbde490e68af090e68bf7 +:10019600e532f0252ef52ee531352df52dc3e5306a +:1001a6009532f530e52f9531f52f0200ee90e6b841 +:1001b600e0644060030204d7e530452f7003020473 +:1001c600d7e490e68af090e68bf090e6a0e020e196 +:1001d600f990e68be0753100f53290e6b9e0b4a30c +:1001e60035e4f533f534c3e5349532e533953150ce +:1001f6003874402534f582e434e7f583e0ffe52ed4 +:100206002534f582e52d3533f583eff00534e534f5 +:100216007002053380d0ad327ae779407ee77f40c1 +:10022600ab07af2eae2d12112de532252ef52ee59c +:1002360031352df52dc3e5309532f530e52f953165 +:10024600f52f0201bee490e68af090e68bf090e688 +:10025600a0e020e1f990e740e0f53514602914604c +:100266001d24fd601024fb60030204d7c2a4d2a3a0 +:10027600d2a20204d7c2a4c2a3c2a20204d7c2a4b5 +:10028600c2a3d2a20204d7c2a4d2a3c2a20204d796 +:10029600e490e68af090e68bf090e6a0e020e1f9a3 +:1002a60090e740e0f53524fe601a24fd600d24fb3e +:1002b600701bc2a7d2a6d2a50204d7c2a7c2a6c2e5 +:1002c600a50204d7c2a7c2a6d2a50204d7c2a7d246 +:1002d600a6c2a50204d7e490e68af090e68bf090d9 +:1002e600e6a0e020e1f990e740e0f535120ef203d2 +:1002f600880103740403600803c20a034d1003afa8 +:1003060014033b1803291e031730039c3200000315 +:10031600d390e60174eaf090e05074fff0751a018c +:100326000203d390e60174aaf090e05074fff075d2 +:100336001a010203d390e60174caf090e05074fbf0 +:10034600f0751a010203d390e60174caf090e040fa +:100356007401f0a3f0e4f51a807390e60174caf014 +:1003660090e0407402f0a304f0e4f51a805f90e692 +:100376000174caf090e0407405f0a304f0e4f51aa5 +:10038600804b90e60174caf090e0407417f0a30425 +:10039600f0e4f51a803790e60174caf090e04074f4 +:1003a60030f0a3f0e4f51a802490e60174caf090c8 +:1003b600e0407478f0a3f0e4f51a801190e6017439 +:1003c600caf090e04074f0f0a3f0e4f51a90e6f578 +:1003d60074fff090e080e090e6f3f090e081e0902a +:1003e600e6c3f090e082e090e6c1f090e083e09012 +:1003f600e6c2f090e085e090e6c0f090e086e090fe +:10040600e6f4f075af07e51ab4010a74e0f59a74dc +:1004160087f59b800874e0f59a7400f59b759de45a +:10042600e4f59ef533f53490e67be090e67cf00546 +:1004360034e534700205336480453370ea0204d72c +:10044600e490e68af090e68bf090e6a0e020e1f9f1 +:1004560090e740e0f53564017077751d0180729074 +:10046600e6bae0752d00f52ea3e0fee4ee422d90ef +:10047600e6bee0752f00f530a3e0fee4ee422fe580 +:1004860030452f604c90e6a0e020e1f9c3e53094ba +:1004960040e52f94005008852f318530328006754f +:1004a600310075324090e7407401f0e490e68af03e +:1004b60090e68be532f0252ef52ee531352df52d1e +:1004c600c3e5309532f530e52f9531f52f80b0d361 +:0204d60022c33f +:0104d8002201 +:10128100c0e0c083c082d2015391ef90e65d74014a +:08129100f0d082d083d0e032de +:1012b100c0e0c083c0825391ef90e65d7404f0d02a +:0612c10082d083d0e03270 +:1012c700c0e0c083c0825391ef90e65d7402f0d016 +:0612d70082d083d0e0325a +:10108900c0e0c083c08290e680e030e70e850a0e9a +:10109900850b0f851210851311800c85120e85138f +:1010a9000f850a10850b115391ef90e65d7410f0ce +:0710b900d082d083d0e032a9 +:10129900c0e0c083c082d2045391ef90e65d740828 +:0812a900f0d082d083d0e032c6 +:1010c000c0e0c083c08290e680e030e70e850a0e63 +:1010d000850b0f851210851311800c85120e851358 +:1010e0000f850a10850b115391ef90e65d7420f087 +:0710f000d082d083d0e03272 +:01002a0032a3 +:01003200329b +:01004200328b +:01004a003283 +:01005200327b +:010bf90032c9 +:010bfa0032c8 +:010bfb0032c7 +:010bfc0032c6 +:010bfd0032c5 +:010bfe0032c4 +:010bff0032c3 +:010dfa0032c6 +:010dfb0032c5 +:010dfc0032c4 +:010dfd0032c3 +:010dfe0032c2 +:010dff0032c1 +:0113110032a9 +:0113120032a8 +:0113130032a7 +:0113140032a6 +:0113150032a5 +:0113160032a4 +:0113170032a3 +:0113180032a2 +:0113190032a1 +:01131a0032a0 +:01131b00329f +:01131c00329e +:01131d00329d +:01131e00329c +:01131f00329b +:01132000329a +:011321003299 +:011322003298 +:060f7300ab07aa06ac0565 +:100f7900e4fde51c6010ea7e000dee2407f582e42d +:100f890034e1f583eaf0ebae050d74072ef582e442 +:100f990034e1f583ebf0af050d74072ff582e434e6 +:100fa900e1f583ecf07ae17b07af19120ddeaf1999 +:030fb9001210f71c +:010fbc002212 +:0a112d008e368f378d388a398b3ae1 +:10113700e4f53be53bc3953850200537e537ae3638 +:101147007002053614ffe53a253bf582e43539f59b +:0a11570083e0fd120f73053b80d901 +:01116100226b +:0a0fbd008e368f378d388a398b3a53 +:100fc700e4fde51c6012e536ff7e000dee2407f513 +:100fd70082e434e1f583eff0e537ae050d74072eb3 +:100fe700f582e434e1f583e537f07ae17b07af1961 +:0e0ff700120ddeab3aaa39ad38af19120bdd80 +:0110050022c8 +:100960006080e0000e030111010130070100020167 +:1009700000001100fffefffefffeffff0009121244 +:10098000002d123f080301010101010701020401ca +:1009900000000000fffcfffefffeffff090912122e +:1009a000002d363f17180101010101070002010067 +:1009b00000001000fffbfffbfbfbfbfb000912121a +:1009c000002d123f0803013f010101070102000150 +:1009d00000000000fffdffffffffffff09091212eb +:1009e000002d363f6080e087010201013f010107d1 +:1009f00000000200010000000702020707070707c6 +:100a0000000000003f00003f03013f01010101071a +:100a10000202050000000000050707070707070797 +:100a200000003f000000003f010180010101bf07fd +:100a30000202030202021100ffffffffffffffffa0 +:100a400000091212002d123f0101010101010107ed +:100a5000000000000000000007070707070707075e +:100a6000000000000000003f47e080c000000fca07 +:020a70001e0066 +:100f180090e60174caf090e6f574fff090e080e086 +:100f280090e6f3f090e081e090e6c3f090e082e094 +:100f380090e6c1f090e083e090e6c2f090e085e0b2 +:100f480090e6c0f090e086e090e6f4f075af0774a4 +:100f5800e0f59a7400f59b759de4e4f59eff90e634 +:0a0f68007be090e67cf00fbf80f400 +:010f7200225c +:0a00360000010202030304040505a3 +:10077300c204c200c203c201c20275080875090798 +:10078300120cb8c2c975cdf875cc40d2cad2adc26d +:1007930087c2a0d2a17e0e7f008e0c8f0d75140e22 +:1007a300751512750a0e750b1c75120e75133c75b3 +:1007b300160e75175c90e680e030e70e850a0e850d +:1007c3000b0f851210851311800c85120e85130fe4 +:1007d300850a10850b11ee54e070030208f77529a2 +:1007e30000752a807e0e7f008e2b8f2cc374909f02 +:1007f300ff740e9ecf2402cf3400fee48f288e2791 +:10080300f526f525f524f523f522f521af28ae27a6 +:10081300ad26ac25ab24aa23a922a821c3120ee13d +:10082300502ae52a2524f582e5293523f58374cd5d +:10083300f0e4faf9f8e5242401f524ea3523f52355 +:10084300e93522f522e83521f52180c0e4f524f5c8 +:1008530023f522f521af28ae27ad26ac25ab24aa7c +:1008630023a922a821c3120ee15037e52c2524f534 +:1008730082e52b3523f583e0ffe52a2524f582e580 +:10088300293523f583eff0e4faf9f8e5242401f59b +:1008930024ea3523f523e93522f522e83521f5212c +:1008a30080b385290c852a0d74002480ff740e34cf +:1008b300fffec3e5159ff515e5149ef514c3e50f7b +:1008c3009ff50fe50e9ef50ec3e5119ff511e5109b +:1008d3009ef510c3e50b9ff50be50a9ef50ac3e5ec +:1008e300139ff513e5129ef512c3e5179ff517e560 +:1008f300169ef516d2e843d82090e668e04409f046 +:1009030090e65ce0443df0d2af90e680e020e10564 +:10091300d2061211fa90e680e054f7f0538ef8c233 +:10092300043001051204d9c20130042912002850f1 +:1009330024c20412000320001690e682e030e7048c +:10094300e020e1ef90e682e030e604e020e0e4120c +:0a0953001229120040120b7b80c72e +:01095d002277 +:1004d90090e6b9e070030205b514700302065e24c4 +:1004e900fe70030206f324fb70030205af147003c8 +:1004f9000205a914700302059d1470030205a324c3 +:1005090005600302075f120046400302076b90e68d +:10051900bbe024fe602c14604724fd601614603192 +:1005290024067066e50c90e6b3f0e50d90e6b4f0ac +:1005390002076be51490e6b3f0e51590e6b4f00216 +:10054900076be50e90e6b3f0e50f90e6b4f002070d +:100559006be51090e6b3f0e51190e6b4f002076b95 +:1005690090e6bae0ff121255aa06a9077b01ea49eb +:100579004b600dee90e6b3f0ef90e6b4f002076b36 +:1005890090e6a0e04401f002076b90e6a0e0440188 +:10059900f002076b1212ef02076b12130102076bcd +:1005a90012104c02076b1212dd02076b1200484051 +:1005b9000302076b90e6b8e0247f602b14603c24ab +:1005c900026003020654a200e433ff25e0ffa20300 +:1005d900e4334f90e740f0e4a3f090e68af090e628 +:1005e9008b7402f002076be490e740f0a3f090e609 +:1005f9008af090e68b7402f002076b90e6bce05437 +:100609007eff7e00e0d3948040067c007d0180045b +:100619007c007d00ec4efeed4f2436f58274003ee1 +:10062900f583e493ff3395e0feef24a1ffee34e672 +:100639008f82f583e0540190e740f0e4a3f090e65f +:100649008af090e68b7402f002076b90e6a0e04412 +:1006590001f002076b12004e400302076b90e6b8e7 +:10066900e024fe601d2402600302076b90e6bae0f5 +:10067900b40105c20002076b90e6a0e04401f00254 +:10068900076b90e6bae0705990e6bce0547eff7eb5 +:1006990000e0d3948040067c007d0180047c007dcd +:1006a90000ec4efeed4f2436f58274003ef583e4ee +:1006b90093ff3395e0feef24a1ffee34e68f82f538 +:1006c90083e054fef090e6bce05480ff131313540a +:1006d9001fffe0540f2f90e683f0e04420f002075b +:1006e9006b90e6a0e04401f08078120050507390be +:1006f900e6b8e024fe60202402706790e6bae0b410 +:100709000104d200805c90e6bae06402605490e68d +:10071900a0e04401f0804b90e6bce0547eff7e00ef +:10072900e0d3948040067c007d0180047c007d003c +:10073900ec4efeed4f2436f58274003ef583e493ca +:10074900ff3395e0feef24a1ffee34e68f82f583b7 +:10075900e04401f0800c120056500790e6a0e044f6 +:0907690001f090e6a0e04480f0ec +:010772002264 +:0300330002002e9a +:04002e0053d8ef3282 +:03002b0002119629 +:10119600c0e0b287e509150970021508e50945089a +:1011a600701575080475091f300206b2a1d2a08019 +:1011b60004b2a0d2a1c20275cdf875cc40c2cfd080 +:0211c600e03215 +:100e00001201000200000040b5042260000001024f +:100e100000010a0600020000004001000902200053 +:100e200001010080320904000002ff0000000705f4 +:100e300002020002000705860200020009022000eb +:100e400001010080320904000004ff0000000705d2 +:100e50000202400000070586024000000403090466 +:100e60000e034f0044004d0020002000200022030c +:100e7000480061006e00740065006b004400530080 +:100e80004f003600300032003200420045002000a2 +:020e9000000060 +:1012290090e682e030e004e020e60b90e682e030d0 +:10123900e119e030e71590e680e04401f07f147e83 +:0c1249000012100690e680e054fef02237 +:1000030090e682e044c0f090e681f043870100006f +:0400130000000022c7 +:1011fa0030060990e680e0440af0800790e680e035 +:10120a004408f07fdc7e0512100690e65d74fff05c +:0f121a0090e65ff05391ef90e680e054f7f022fa +:08130900e4f541d2e9d2af2264 +:1010f70090e678e020e6f9c2e990e678e04480f0ef +:10110700ef25e090e679f090e678e030e0f990e6b8 +:1011170078e04440f090e678e020e6f990e678e061 +:0611270030e1d6d2e922fe +:1011c800a90790e678e020e6f9e541702390e678f3 +:1011d800e04480f0e925e090e679f08d3caf03a982 +:1011e80007753d018a3e893fe4f540754101d322e8 +:0211f800c32210 +:10116200a90790e678e020e6f9e541702590e67857 +:10117200e04480f0e925e0440190e679f08d3caf4f +:1011820003a907753d018a3e893fe4f54075410395 +:04119200d322c3227f +:03004b00020a7333 +:100a7300c0e0c083c082c085c084c086758600c0c4 +:100a8300d075d000c000c001c002c003c006c007bb +:100a930090e678e030e206754106020b5d90e67859 +:100aa300e020e10ce54164026006754107020b5d3d +:100ab300e54124fe605f14603624fe7003020b4e92 +:100ac30024fc7003020b5a24086003020b5dab3d48 +:100ad300aa3ea93faf4005408f82758300120e9254 +:100ae30090e679f0e540653c7070754105806b9048 +:100af300e679e0ab3daa3ea93fae408e8275830006 +:100b0300120ebf754102e53c6401704e90e678e039 +:100b13004420f08045e53c24feb5400790e678e0ac +:100b23004420f0e53c14b5400a90e678e04440f0f8 +:100b330075410090e679e0ab3daa3ea93fae408ef9 +:100b430082758300120ebf0540800f90e678e04463 +:100b530040f075410080037541005391dfd007d009 +:100b630006d003d002d001d000d0d0d086d084d01c +:080b730085d082d083d0e0326e +:02125500a907e7 +:10125700ae16af178f828e83a3e064037017ad01bc +:1012670019ed7001228f828e83e07c002ffdec3e0a +:09127700feaf0580df7e007f0060 +:01128000224b +:100bdd00121162e54124fa600e146006240770f3c9 +:0c0bed00d322e4f541d322e4f541d322e9 +:100dde001211c8e54124fa600e146006240770f360 +:0c0dee00d322e4f541d322e4f541d322e6 +:101006008e2d8f2e90e600e054187012e52e2401e6 +:10101600ffe4352dc313f52def13f52e801590e65d +:1010260000e05418ffbf100be52e25e0f52ee52d48 +:1010360033f52de52e152eae2d7002152d4e6005bd +:0610460012001780ee22eb +:100017007400f58690fda57c05a3e582458370f9fc +:0100270022b6 +:03004300020c00ac +:03005300020c009c +:100c0000021281000212c7000212b1000212990002 +:100c1000021089000210c00002002a000200320007 +:100c20000200420002004a0002005200020bf900da +:100c3000020bfa00020bfb00020bfc00020bfd0092 +:100c4000020bfe0002003200020bff00020dfa0050 +:100c5000020dfb00020dfc00020dfd00020dfe0066 +:100c6000020dff00020032000200320002003200da +:100c700002131100021312000213130002131400d6 +:100c800002131500021316000213170002131800b6 +:100c90000213190002131a0002131b0002131c0096 +:100ca00002131d0002131e0002131f000213200076 +:080cb0000213210002132200cf +:03000000020d529c +:0c0d5200787fe4f6d8fd758141020d9910 +:100e9200bb010ce58229f582e5833af583e0225015 +:100ea20006e92582f8e622bbfe06e92582f8e2225f +:0d0eb200e58229f582e5833af583e4932279 +:100ebf00f8bb010de58229f582e5833af583e8f069 +:100ecf00225006e92582c8f622bbfe05e92582c815 +:020edf00f222fd +:100ee100eb9ff5f0ea9e42f0e99d42f0e89c45f067 +:010ef10022de +:100ef200d083d082f8e4937012740193700da3a38f +:100f020093f8740193f5828883e4737402936860a2 +:060f1200efa3a3a380dfa2 +:100d5e00020773e493a3f8e493a34003f68001f231 +:100d6e0008dff48029e493a3f85407240cc8c33396 +:100d7e00c4540f4420c8834004f456800146f6df65 +:100d8e00e4800b010204081020408090095ee47e8e +:100d9e00019360bca3ff543f30e509541ffee4935a +:100dae00a360010ecf54c025e060a840b8e493a321 +:100dbe00fae493a3f8e493a3c8c582c8cac583ca4c +:100dce00f0a3c8c582c8cac583cadfe9dee780be04 +:010a72000083 +:03009b0002038cd1 +:1002f50003580103500203480403400803700a032e +:10030500380c03301003681403281803211e031d3d +:0e03150030036032000003d374ea800274aa41 +:0f032300751a01805e79017a017b0980467901a4 +:100332007a017b01803e79017a027b018036790263 +:100342007a037b01802e79057a067b018026790b60 +:100352007a0c7b01801e79177a187b018016792f1f +:100362007a307b01800e79777a787b01800679ef8b +:100372007af07b0190e040e9f0a3eaf0a3ebf0e42d +:0f038200f51a74ca90e601f08047e490e68af01d +:0f03910090e68bf090e6a0e020e1f990e740e0e5 +:0f03a000600a94035006240a90e61af00204d76c +:010b940082de +:010b9a0086d4 +:010cf0008281 +:010cf6008677 +:00000001ff diff --git a/firmware/dso6022be-loader.hex b/firmware/dso6022be-loader.hex new file mode 100644 index 0000000..d7758b6 --- /dev/null +++ b/firmware/dso6022be-loader.hex @@ -0,0 +1,60 @@ +:1003680090E668E0FF74FFF0E0B40B04EFF0D322EE +:0603780090E668EFF0C3FF +:01037E00225C +:1001B500907FE9E064A360030202C5A3E07508002F +:1001C500F509A3E0FEE4EE4208907FEEE0750A0033 +:1001D500F50BA3E0FEE4EE420A907FE8E064407090 +:1001E50064E50B450A70030202D6E4907FC5F090E2 +:1001F5007FB4E020E3F9907FC5E0750C00F50DE4D0 +:10020500FCFDC3ED950DEC950C501F74C02DF582CA +:10021500E4347EF583E0FFE5092DF582E5083CF53C +:1002250083EFF00DBD00010C80D8E50D2509F5091A +:10023500E50C3508F508C3E50B950DF50BE50A95B5 +:100245000CF50A809C907FE8E064C060030202D64A +:10025500E50B450A607BC3E50B9440E50A94005025 +:1002650008850A0C850B0D8006750C00750D40E49C +:10027500FCFDC3ED950DEC950C501FE5092DF582A0 +:10028500E5083CF583E0FF74002DF582E4347FF545 +:1002950083EFF00DBD00010C80D8907FB5E50DF022 +:1002A5002509F509E50C3508F508C3E50B950DF5A8 +:1002B5000BE50A950CF50A907FB4E030E29280F7E1 +:1002C500907FE9E0B4AC0AE4907F00F0907FB5043C +:0802D500F0907FB4E04402F058 +:0102DD0022FE +:1000800090E6B9E064A36003020198A3E07508005C +:10009000F509A3E0FEE4EE420890E6BEE0750A0032 +:1000A000F50BA3E0FEE4EE420A90E6B8E06440708F +:1000B00066E50B450A70030201ADE490E68AF0A301 +:1000C000F090E6A0E020E1F990E68BE0750C00F5F9 +:1000D0000DE4FCFDC3ED950DEC950C501F74402D07 +:1000E000F582E434E7F583E0FFE5092DF582E508C4 +:1000F0003CF583EFF00DBD00010C80D8E50D25091E +:10010000F509E50C3508F508C3E50B950DF50BE58C +:100110000A950CF50A809A90E6B8E064C060030284 +:1001200001ADE50B450A70030201ADC3E50B944038 +:10013000E50A94005008850A0C850B0D8006750CA5 +:1001400000750D40E4FCFDC3ED950DEC950C501FC2 +:10015000E5092DF582E5083CF583E0FF74402DF5B7 +:1001600082E434E7F583EFF00DBD00010C80D8E4A4 +:1001700090E68AF0A3E50DF02509F509E50C3508B0 +:10018000F508C3E50B950DF50BE50A950CF50A90FE +:10019000E6A0E030E18C80F790E6B9E0B4AC0E90D8 +:1001A000E7407401F0E490E68AF0A304F090E6A042 +:0401B000E04480F0B7 +:0101B4002228 +:1002DE00C2011203689200907F95E044C0F0D2E80C +:1002EE0030000890E65D74FFF08006907FAB74FFDF +:1002FE00F030000890E6687408F08007907FAFE059 +:10030E004401F030000890E65C7401F08006907FA6 +:10031E00AE7401F0D2AF3001FD30000512008080C6 +:08032E00031201B5C20180EECB +:03000300020336BF +:10033600C0E0C083C082C085C084C086758600D2F6 +:10034600015391EF30000890E65D7401F08006904D +:100356007FAB7401F0D086D084D085D082D083D094 +:02036600E03283 +:03004300020400B4 +:0404000002033600BD +:0300000002037F79 +:0C037F00787FE4F6D8FD7581200202DED4 +:00000001FF diff --git a/openhantek/src/configpages.cpp b/openhantek/src/configpages.cpp index bdbe6c8..505eb41 100644 --- a/openhantek/src/configpages.cpp +++ b/openhantek/src/configpages.cpp @@ -165,6 +165,39 @@ DsoConfigColorsPage::DsoConfigColorsPage(DsoSettings *settings, QWidget *parent) this->screenGroup = new QGroupBox(tr("Screen")); this->screenGroup->setLayout(this->screenLayout); + // Print category + this->printAxesLabel = new QLabel(tr("Axes")); + this->printAxesColorBox = new ColorBox(this->settings->view.color.print.axes); + this->printBackgroundLabel = new QLabel(tr("Background")); + this->printBackgroundColorBox = new ColorBox(this->settings->view.color.print.background); + this->printBorderLabel = new QLabel(tr("Border")); + this->printBorderColorBox = new ColorBox(this->settings->view.color.print.border); + this->printGridLabel = new QLabel(tr("Grid")); + this->printGridColorBox = new ColorBox(this->settings->view.color.print.grid); + this->printMarkersLabel = new QLabel(tr("Markers")); + this->printMarkersColorBox = new ColorBox(this->settings->view.color.print.markers); + this->printTextLabel = new QLabel(tr("Text")); + this->printTextColorBox = new ColorBox(this->settings->view.color.print.text); + + this->printLayout = new QGridLayout(); + this->printLayout->setColumnStretch(0, 1); + this->printLayout->setColumnMinimumWidth(1, 80); + this->printLayout->addWidget(this->printBackgroundLabel, 0, 0); + this->printLayout->addWidget(this->printBackgroundColorBox, 0, 1); + this->printLayout->addWidget(this->printGridLabel, 1, 0); + this->printLayout->addWidget(this->printGridColorBox, 1, 1); + this->printLayout->addWidget(this->printAxesLabel, 2, 0); + this->printLayout->addWidget(this->printAxesColorBox, 2, 1); + this->printLayout->addWidget(this->printBorderLabel, 3, 0); + this->printLayout->addWidget(this->printBorderColorBox, 3, 1); + this->printLayout->addWidget(this->printMarkersLabel, 4, 0); + this->printLayout->addWidget(this->printMarkersColorBox, 4, 1); + this->printLayout->addWidget(this->printTextLabel, 5, 0); + this->printLayout->addWidget(this->printTextColorBox, 5, 1); + + this->printGroup = new QGroupBox(tr("Print")); + this->printGroup->setLayout(this->printLayout); + // Graph category this->channelLabel = new QLabel(tr("Channel")); this->channelLabel->setAlignment(Qt::AlignHCenter); @@ -194,6 +227,7 @@ DsoConfigColorsPage::DsoConfigColorsPage(DsoSettings *settings, QWidget *parent) // Main layout this->mainLayout = new QVBoxLayout(); this->mainLayout->addWidget(this->screenGroup); + this->mainLayout->addWidget(this->printGroup); this->mainLayout->addWidget(this->graphGroup); this->mainLayout->addStretch(1); @@ -214,6 +248,14 @@ void DsoConfigColorsPage::saveSettings() { this->settings->view.color.screen.markers = this->markersColorBox->getColor(); this->settings->view.color.screen.text = this->textColorBox->getColor(); + // Print category + this->settings->view.color.print.axes = this->printAxesColorBox->getColor(); + this->settings->view.color.print.background = this->printBackgroundColorBox->getColor(); + this->settings->view.color.print.border = this->printBorderColorBox->getColor(); + this->settings->view.color.print.grid = this->printGridColorBox->getColor(); + this->settings->view.color.print.markers = this->printMarkersColorBox->getColor(); + this->settings->view.color.print.text = this->printTextColorBox->getColor(); + // Graph category for(int channel = 0; channel < this->settings->scope.voltage.count(); ++channel) { this->settings->view.color.screen.voltage[channel] = this->channelColorBox[channel]->getColor(); diff --git a/openhantek/src/configpages.h b/openhantek/src/configpages.h index c829f57..43da80a 100644 --- a/openhantek/src/configpages.h +++ b/openhantek/src/configpages.h @@ -102,6 +102,11 @@ class DsoConfigColorsPage : public QWidget { QGridLayout *screenLayout; QLabel *axesLabel, *backgroundLabel, *borderLabel, *gridLabel, *markersLabel, *textLabel; ColorBox *axesColorBox, *backgroundColorBox, *borderColorBox, *gridColorBox, *markersColorBox, *textColorBox; + + QGroupBox *printGroup; + QGridLayout *printLayout; + QLabel *printAxesLabel, *printBackgroundLabel, *printBorderLabel, *printGridLabel, *printMarkersLabel, *printTextLabel; + ColorBox *printAxesColorBox, *printBackgroundColorBox, *printBorderColorBox, *printGridColorBox, *printMarkersColorBox, *printTextColorBox; QGroupBox *graphGroup; QGridLayout *graphLayout; diff --git a/openhantek/src/dockwindows.cpp b/openhantek/src/dockwindows.cpp index 0a1e774..fbefab4 100644 --- a/openhantek/src/dockwindows.cpp +++ b/openhantek/src/dockwindows.cpp @@ -210,6 +210,16 @@ void HorizontalDock::samplerateLimitsChanged(double minimum, double maximum) { this->suppressSignals = false; } +/// \brief Updates the mode and steps of the samplerate spin box. +/// \param mode The mode value the spin box should accept. +/// \param steps The steps value the spin box should accept. +void HorizontalDock::samplerateSet(int mode, QList steps) { + this->suppressSignals = true; + this->samplerateSiSpinBox->setMode(mode); + this->samplerateSiSpinBox->setSteps(steps); + this->suppressSignals = false; +} + /// \brief Called when the frequencybase spinbox changes its value. /// \param frequencybase The frequencybase in hertz. void HorizontalDock::frequencybaseSelected(double frequencybase) { @@ -329,7 +339,7 @@ void TriggerDock::closeEvent(QCloseEvent *event) { /// \param mode The trigger mode. /// \return Index of mode-value, -1 on error. int TriggerDock::setMode(Dso::TriggerMode mode) { - if(mode >= Dso::TRIGGERMODE_AUTO && mode <=Dso:: TRIGGERMODE_SINGLE) { + if(mode >= Dso::TRIGGERMODE_AUTO && mode < Dso::TRIGGERMODE_COUNT) { this->modeComboBox->setCurrentIndex(mode); return mode; } diff --git a/openhantek/src/dockwindows.h b/openhantek/src/dockwindows.h index dbf6b1b..a06a9a2 100644 --- a/openhantek/src/dockwindows.h +++ b/openhantek/src/dockwindows.h @@ -84,6 +84,7 @@ class HorizontalDock : public QDockWidget { public slots: void availableRecordLengthsChanged(const QList &recordLengths); void samplerateLimitsChanged(double minimum, double maximum); + void samplerateSet(int mode, QList sampleSteps); protected slots: void frequencybaseSelected(double frequencybase); diff --git a/openhantek/src/dso.cpp b/openhantek/src/dso.cpp index 9991513..5384fe9 100644 --- a/openhantek/src/dso.cpp +++ b/openhantek/src/dso.cpp @@ -100,6 +100,8 @@ namespace Dso { return QApplication::tr("Normal"); case TRIGGERMODE_SINGLE: return QApplication::tr("Single"); + case TRIGGERMODE_SOFTWARE: + return QApplication::tr("Software"); default: return QString(); } diff --git a/openhantek/src/dso.h b/openhantek/src/dso.h index 3de5bc5..b1fb023 100644 --- a/openhantek/src/dso.h +++ b/openhantek/src/dso.h @@ -92,6 +92,7 @@ namespace Dso { TRIGGERMODE_AUTO, ///< Automatic without trigger event TRIGGERMODE_NORMAL, ///< Normal mode TRIGGERMODE_SINGLE, ///< Stop after the first trigger event + TRIGGERMODE_SOFTWARE, ///< Software trigger mode TRIGGERMODE_COUNT ///< The total number of modes }; diff --git a/openhantek/src/dsocontrol.h b/openhantek/src/dsocontrol.h index 3ee5483..865d714 100644 --- a/openhantek/src/dsocontrol.h +++ b/openhantek/src/dsocontrol.h @@ -73,6 +73,7 @@ class DsoControl : public QThread { void recordLengthChanged(unsigned long duration); ///< The record length has changed void recordTimeChanged(double duration); ///< The record time duration has changed void samplerateChanged(double samplerate); ///< The samplerate has changed + void samplerateSet(int mode, QList sampleSteps); ///< The samplerate has changed public slots: virtual void connectDevice(); diff --git a/openhantek/src/exporter.cpp b/openhantek/src/exporter.cpp index a0f8b60..74c5f15 100644 --- a/openhantek/src/exporter.cpp +++ b/openhantek/src/exporter.cpp @@ -216,7 +216,7 @@ bool Exporter::doExport() { // Add graphs for channels for(int channel = 0 ; channel < this->settings->scope.voltage.count(); ++channel) { if(this->settings->scope.voltage[channel].used && this->dataAnalyzer->data(channel)) { - painter.setPen(colorValues->voltage[channel]); + painter.setPen(QPen(colorValues->voltage[channel], 0)); // What's the horizontal distance between sampling points? double horizontalFactor = this->dataAnalyzer->data(channel)->samples.voltage.interval / this->settings->scope.horizontal.timebase; @@ -247,7 +247,7 @@ bool Exporter::doExport() { // Add spectrum graphs for (int channel = 0; channel < this->settings->scope.spectrum.count(); ++channel) { if(this->settings->scope.spectrum[channel].used && this->dataAnalyzer->data(channel)) { - painter.setPen(colorValues->spectrum[channel]); + painter.setPen(QPen(colorValues->spectrum[channel], 0)); // What's the horizontal distance between sampling points? double horizontalFactor = this->dataAnalyzer->data(channel)->samples.spectrum.interval / this->settings->scope.horizontal.frequencybase; @@ -296,7 +296,7 @@ bool Exporter::doExport() { painter.setMatrix(QMatrix((paintDevice->width() - 1) / DIVS_TIME, 0, 0, -(scopeHeight - 1) / DIVS_VOLTAGE, (double) (paintDevice->width() - 1) / 2, (scopeHeight - 1) * (zoomed + 0.5) + lineHeight * 1.5 + lineHeight * 2.5 * zoomed), false); // Grid lines - painter.setPen(colorValues->grid); + painter.setPen(QPen(colorValues->grid, 0)); if(this->format < EXPORT_FORMAT_IMAGE) { // Draw vertical lines @@ -342,7 +342,7 @@ bool Exporter::doExport() { } // Axes - painter.setPen(colorValues->axes); + painter.setPen(QPen(colorValues->axes, 0)); painter.drawLine(QPointF(-DIVS_TIME / 2, 0), QPointF(DIVS_TIME / 2, 0)); painter.drawLine(QPointF(0, -DIVS_VOLTAGE / 2), QPointF(0, DIVS_VOLTAGE / 2)); for(double div = 0.2; div <= DIVS_TIME / 2; div += 0.2) { @@ -355,7 +355,7 @@ bool Exporter::doExport() { } // Borders - painter.setPen(colorValues->border); + painter.setPen(QPen(colorValues->border, 0)); painter.drawRect(QRectF(-DIVS_TIME / 2, -DIVS_VOLTAGE / 2, DIVS_TIME, DIVS_VOLTAGE)); } diff --git a/openhantek/src/glgenerator.cpp b/openhantek/src/glgenerator.cpp index 980b001..e60222f 100644 --- a/openhantek/src/glgenerator.cpp +++ b/openhantek/src/glgenerator.cpp @@ -87,9 +87,87 @@ void GlGenerator::generateGraphs() { } this->dataAnalyzer->mutex()->lock(); - + + unsigned int preTrigSamples = 0; + unsigned int postTrigSamples = 0; switch(this->settings->scope.horizontal.format) { case Dso::GRAPHFORMAT_TY: + { + unsigned int swTriggerStart = 0; + // check trigger point for software trigger + if (this->settings->scope.trigger.mode == Dso::TRIGGERMODE_SOFTWARE && this->settings->scope.trigger.source <= 1) { + int channel = this->settings->scope.trigger.source; + if(this->settings->scope.voltage[channel].used && this->dataAnalyzer->data(channel) && !this->dataAnalyzer->data(channel)->samples.voltage.sample.empty()) { + double value; + double level = this->settings->scope.voltage[channel].trigger; + unsigned int sampleCount = this->dataAnalyzer->data(channel)->samples.voltage.sample.size(); + double timeDisplay = this->settings->scope.horizontal.timebase*10; + double samplesDisplay = timeDisplay * this->settings->scope.horizontal.samplerate; + if (samplesDisplay >= sampleCount) { + // For sure not enough samples to adjust for jitter. + // Following options exist: + // 1: Decrease sample rate + // 2: Change trigger mode to auto + // 3: Ignore samples + // For now #3 is chosen +#ifdef DEBUG + Helper::timestampDebug(QString("Too few samples to make a steady picture. Decrease sample rate")); +#endif + this->dataAnalyzer->mutex()->unlock(); + return; + } + preTrigSamples = (this->settings->scope.trigger.position * samplesDisplay); + postTrigSamples = sampleCount - (samplesDisplay - preTrigSamples); + //std::vector::const_iterator dataIterator = this->dataAnalyzer->data(channel)->samples.voltage.sample.begin(); + + if (this->settings->scope.trigger.slope == Dso::SLOPE_POSITIVE) { + double prev = INT_MAX; + for (unsigned int i = preTrigSamples; i < postTrigSamples; i++) { + value = this->dataAnalyzer->data(channel)->samples.voltage.sample[i]; + if (value > level && prev <= level) { + int rising = 0; + for (unsigned int k = i + 1; k < i + 11 && k < sampleCount; k++) { + if (this->dataAnalyzer->data(channel)->samples.voltage.sample[k] >= value) { + rising++; + } + } + if (rising > 7) { + swTriggerStart = i; + break; + } + } + prev = value; + } + } + else if (this->settings->scope.trigger.slope == Dso::SLOPE_NEGATIVE) { + double prev = INT_MIN; + for (unsigned int i = preTrigSamples; i < postTrigSamples; i++) { + value = this->dataAnalyzer->data(channel)->samples.voltage.sample[i]; + if (value < level && prev >= level) { + int falling = 0; + for (unsigned int k = i + 1; k < i + 11 && k < sampleCount; k++) { + if (this->dataAnalyzer->data(channel)->samples.voltage.sample[k] < value) { + falling++; + } + } + if (falling > 7) { + swTriggerStart = i; + break; + } + } + prev = value; + } + } + } + if (swTriggerStart == 0) { +#ifdef DEBUG + Helper::timestampDebug(QString("Trigger not asserted. Data ignored")); +#endif + this->dataAnalyzer->mutex()->unlock(); + return; + } + } + // Add graphs for channels for(int mode = Dso::CHANNELMODE_VOLTAGE; mode < Dso::CHANNELMODE_COUNT; ++mode) { for(int channel = 0; channel < this->settings->scope.voltage.size(); ++channel) { @@ -97,11 +175,16 @@ void GlGenerator::generateGraphs() { if(((mode == Dso::CHANNELMODE_VOLTAGE) ? this->settings->scope.voltage[channel].used : this->settings->scope.spectrum[channel].used) && this->dataAnalyzer->data(channel) && !this->dataAnalyzer->data(channel)->samples.voltage.sample.empty()) { // Check if the sample count has changed unsigned int sampleCount = (mode == Dso::CHANNELMODE_VOLTAGE) ? this->dataAnalyzer->data(channel)->samples.voltage.sample.size() : this->dataAnalyzer->data(channel)->samples.spectrum.sample.size(); + if(mode == Dso::CHANNELMODE_VOLTAGE) + sampleCount -= (swTriggerStart - preTrigSamples); unsigned int neededSize = sampleCount * 2; + +#if 0 for(unsigned int index = 0; index < this->digitalPhosphorDepth; ++index) { if(this->vaChannel[mode][channel][index].size() != neededSize) this->vaChannel[mode][channel][index].clear(); // Something was changed, drop old traces } +#endif // Set size directly to avoid reallocations this->vaChannel[mode][channel].front().resize(neededSize); @@ -122,6 +205,8 @@ void GlGenerator::generateGraphs() { const double gain = this->settings->scope.voltage[channel].gain; const double offset = this->settings->scope.voltage[channel].offset; + std::advance(dataIterator, swTriggerStart-preTrigSamples); + for(unsigned int position = 0; position < sampleCount; ++position) { *(glIterator++) = position * horizontalFactor - DIVS_TIME / 2; *(glIterator++) = *(dataIterator++) / gain + offset; @@ -145,6 +230,7 @@ void GlGenerator::generateGraphs() { } } } + } break; case Dso::GRAPHFORMAT_XY: diff --git a/openhantek/src/hantek/control.cpp b/openhantek/src/hantek/control.cpp index 3edb816..bd2d12b 100644 --- a/openhantek/src/hantek/control.cpp +++ b/openhantek/src/hantek/control.cpp @@ -351,6 +351,9 @@ namespace Hantek { else { // Normal mode, channels are using their separate buffers sampleCount = totalSampleCount / HANTEK_CHANNELS; + // if device is 6022BE, drop first 1000 samples + if (this->device->getModel() == MODEL_DSO6022BE) + sampleCount -= 1000; for(int channel = 0; channel < HANTEK_CHANNELS; ++channel) { if(this->settings.voltage[channel].used) { // Resize sample vector @@ -372,8 +375,11 @@ namespace Hantek { } } else { - if (this->device->getModel() == MODEL_DSO6022BE) + if (this->device->getModel() == MODEL_DSO6022BE) { bufferPosition += channel; + // if device is 6022BE, offset 1000 incrementally + bufferPosition += 1000 * 2; + } else bufferPosition += HANTEK_CHANNELS - 1 - channel; @@ -857,12 +863,12 @@ namespace Hantek { for(int control = 0; control <= lastControlIndex; ++control) this->controlPending[control] = true; - // Disable controls not supported by 6022BE - if (this->device->getModel() == MODEL_DSO6022BE) { - this->controlPending[CONTROLINDEX_SETOFFSET] = false; - this->controlPending[CONTROLINDEX_SETRELAYS] = false; - } - + // Disable controls not supported by 6022BE + if (this->device->getModel() == MODEL_DSO6022BE) { + this->controlPending[CONTROLINDEX_SETOFFSET] = false; + this->controlPending[CONTROLINDEX_SETRELAYS] = false; + } + // Maximum possible samplerate for a single channel and dividers for record lengths this->specification.bufferDividers.clear(); this->specification.samplerate.single.recordLengths.clear(); @@ -935,13 +941,13 @@ namespace Hantek { break; case MODEL_DSO6022BE: - this->specification.samplerate.single.base = 48e6; + this->specification.samplerate.single.base = 1e6; this->specification.samplerate.single.max = 48e6; - this->specification.samplerate.single.maxDownsampler = 1; + this->specification.samplerate.single.maxDownsampler = 10; this->specification.samplerate.single.recordLengths << UINT_MAX << 10240 << 32768; - this->specification.samplerate.multi.base = 48e6; + this->specification.samplerate.multi.base = 1e6; this->specification.samplerate.multi.max = 48e6; - this->specification.samplerate.multi.maxDownsampler = 1; + this->specification.samplerate.multi.maxDownsampler = 10; this->specification.samplerate.multi.recordLengths << UINT_MAX << 20480 << 65536; this->specification.bufferDividers << 1000 << 1 << 1; this->specification.gainSteps @@ -951,8 +957,12 @@ namespace Hantek { this->specification.voltageLimit[channel] << 25 << 51 << 103 << 206 << 412 << 196 << 392 << 784 << 1000; // Divider. Tested and calculated results are different! - //this->specification.gainDiv - // << 10 << 10 << 10 << 10 << 10 << 2 << 2 << 2 << 1; + this->specification.gainDiv + << 10 << 10 << 10 << 10 << 10 << 2 << 2 << 2 << 1; + this->specification.sampleSteps + << 1e5 << 2e5 << 5e5 << 1e6 << 2e6 << 4e6 << 8e6 << 16e6 << 24e6 << 48e6; + this->specification.sampleDiv + << 10 << 20 << 50 << 1 << 2 << 4 << 8 << 16 << 24 << 48; this->specification.sampleSize = 8; break; @@ -996,6 +1006,12 @@ namespace Hantek { if(this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] != UINT_MAX) emit recordTimeChanged((double) this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] / this->settings.samplerate.current); emit samplerateChanged(this->settings.samplerate.current); + + if(this->device->getModel() == MODEL_DSO6022BE) { + QList sampleSteps; + sampleSteps << 1.0 << 2.0 << 5.0 << 10.0 << 20.0 << 40.0 << 80.0 << 160.0 << 240.0 << 480.0; + emit samplerateSet(1, sampleSteps); + } DsoControl::connectDevice(); } @@ -1032,18 +1048,36 @@ namespace Hantek { this->settings.samplerate.target.samplerateSet = true; } - // When possible, enable fast rate if it is required to reach the requested samplerate - bool fastRate = (this->settings.usedChannels <= 1) && (samplerate > this->specification.samplerate.single.max / this->specification.bufferDividers[this->settings.recordLengthId]); - - // What is the nearest, at least as high samplerate the scope can provide? - unsigned int downsampler = 0; - double bestSamplerate = getBestSamplerate(samplerate, fastRate, false, &(downsampler)); - - // Set the calculated samplerate - if(this->updateSamplerate(downsampler, fastRate) == UINT_MAX) - return 0.0; - else { - return bestSamplerate; + if (this->device->getModel() != MODEL_DSO6022BE) { + // When possible, enable fast rate if it is required to reach the requested samplerate + bool fastRate = (this->settings.usedChannels <= 1) && (samplerate > this->specification.samplerate.single.max / this->specification.bufferDividers[this->settings.recordLengthId]); + + // What is the nearest, at least as high samplerate the scope can provide? + unsigned int downsampler = 0; + double bestSamplerate = getBestSamplerate(samplerate, fastRate, false, &(downsampler)); + + // Set the calculated samplerate + if(this->updateSamplerate(downsampler, fastRate) == UINT_MAX) + return 0.0; + else { + return bestSamplerate; + } + } else { + int sampleId; + for(sampleId = 0; sampleId < this->specification.sampleSteps.count() - 1; ++sampleId) + if(this->specification.sampleSteps[sampleId] == samplerate) + break; + this->controlCode[CONTROLINDEX_SETTIMEDIV] = CONTROL_SETTIMEDIV; + static_cast(this->control[CONTROLINDEX_SETTIMEDIV])->setDiv(this->specification.sampleDiv[sampleId]); + this->controlPending[CONTROLINDEX_SETTIMEDIV] = true; + this->settings.samplerate.current = samplerate; + + // Check for Roll mode + if(this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] != UINT_MAX) + emit recordTimeChanged((double) this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] / this->settings.samplerate.current); + emit samplerateChanged(this->settings.samplerate.current); + + return samplerate; } } @@ -1062,21 +1096,44 @@ namespace Hantek { this->settings.samplerate.target.samplerateSet = false; } - // Calculate the maximum samplerate that would still provide the requested duration - double maxSamplerate = (double) this->specification.samplerate.single.recordLengths[this->settings.recordLengthId] / duration; - - // When possible, enable fast rate if the record time can't be set that low to improve resolution - bool fastRate = (this->settings.usedChannels <= 1) && (maxSamplerate >= this->specification.samplerate.multi.base / this->specification.bufferDividers[this->settings.recordLengthId]); - - // What is the nearest, at most as high samplerate the scope can provide? - unsigned int downsampler = 0; - double bestSamplerate = getBestSamplerate(maxSamplerate, fastRate, true, &(downsampler)); - - // Set the calculated samplerate - if(this->updateSamplerate(downsampler, fastRate) == UINT_MAX) - return 0.0; - else { - return (double) this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] / bestSamplerate; + if (this->device->getModel() != MODEL_DSO6022BE) { + // Calculate the maximum samplerate that would still provide the requested duration + double maxSamplerate = (double) this->specification.samplerate.single.recordLengths[this->settings.recordLengthId] / duration; + + // When possible, enable fast rate if the record time can't be set that low to improve resolution + bool fastRate = (this->settings.usedChannels <= 1) && (maxSamplerate >= this->specification.samplerate.multi.base / this->specification.bufferDividers[this->settings.recordLengthId]); + + // What is the nearest, at most as high samplerate the scope can provide? + unsigned int downsampler = 0; + double bestSamplerate = getBestSamplerate(maxSamplerate, fastRate, true, &(downsampler)); + + // Set the calculated samplerate + if(this->updateSamplerate(downsampler, fastRate) == UINT_MAX) + return 0.0; + else { + return (double) this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] / bestSamplerate; + } + } else { + // For now - we go for the 10240 size sampling - the other seems not to be supported + // Find highest samplerate using less than 10240 samples to obtain our duration. + // Better add some margin for our SW trigger + unsigned int sampleMargin = 2000; + unsigned int sampleCount = 10240; + int bestId = 0; + int sampleId; + for(sampleId = 0; sampleId < this->specification.sampleSteps.count(); ++sampleId) { + if (this->specification.sampleSteps[sampleId] * duration < (sampleCount - sampleMargin)) + bestId = sampleId; + } + sampleId = bestId; + // Usable sample value + this->controlCode[CONTROLINDEX_SETTIMEDIV] = CONTROL_SETTIMEDIV; + static_cast(this->control[CONTROLINDEX_SETTIMEDIV])->setDiv(this->specification.sampleDiv[sampleId]); + this->controlPending[CONTROLINDEX_SETTIMEDIV] = true; + this->settings.samplerate.current = this->specification.sampleSteps[sampleId]; + + emit samplerateChanged(this->settings.samplerate.current); + return this->settings.samplerate.current; } } @@ -1164,8 +1221,10 @@ namespace Hantek { // Dso::ERROR_NONE; // SetRelays control command for coupling relays - static_cast(this->control[CONTROLINDEX_SETRELAYS])->setCoupling(channel, coupling != Dso::COUPLING_AC); - this->controlPending[CONTROLINDEX_SETRELAYS] = true; + if (this->device->getModel() != MODEL_DSO6022BE) { + static_cast(this->control[CONTROLINDEX_SETRELAYS])->setCoupling(channel, coupling != Dso::COUPLING_AC); + this->controlPending[CONTROLINDEX_SETRELAYS] = true; + } return Dso::ERROR_NONE; } @@ -1186,17 +1245,29 @@ namespace Hantek { for(gainId = 0; gainId < this->specification.gainSteps.count() - 1; ++gainId) if(this->specification.gainSteps[gainId] >= gain) break; - - // SetGain bulk command for gain - static_cast(this->command[BULK_SETGAIN])->setGain(channel, this->specification.gainIndex[gainId]); - this->commandPending[BULK_SETGAIN] = true; - - // SetRelays control command for gain relays - ControlSetRelays *controlSetRelays = static_cast(this->control[CONTROLINDEX_SETRELAYS]); - controlSetRelays->setBelow1V(channel, gainId < 3); - controlSetRelays->setBelow100mV(channel, gainId < 6); - this->controlPending[CONTROLINDEX_SETRELAYS] = true; - + + // Fixme, shoulb be some kind of protocol check instead of model check. + if (this->device->getModel() == MODEL_DSO6022BE) { + if (channel == 0) { + static_cast(this->control[CONTROLINDEX_SETVOLTDIV_CH1])->setDiv(this->specification.gainDiv[gainId]); + this->controlPending[CONTROLINDEX_SETVOLTDIV_CH1] = true; + } else if (channel == 1) { + static_cast(this->control[CONTROLINDEX_SETVOLTDIV_CH2])->setDiv(this->specification.gainDiv[gainId]); + this->controlPending[CONTROLINDEX_SETVOLTDIV_CH2] = true; + } else + qDebug("%s: Unsuported channel: %i\n", __func__, channel); + } else { + // SetGain bulk command for gain + static_cast(this->command[BULK_SETGAIN])->setGain(channel, this->specification.gainIndex[gainId]); + this->commandPending[BULK_SETGAIN] = true; + + // SetRelays control command for gain relays + ControlSetRelays *controlSetRelays = static_cast(this->control[CONTROLINDEX_SETRELAYS]); + controlSetRelays->setBelow1V(channel, gainId < 3); + controlSetRelays->setBelow100mV(channel, gainId < 6); + this->controlPending[CONTROLINDEX_SETRELAYS] = true; + } + this->settings.voltage[channel].gain = gainId; this->setOffset(channel, this->settings.voltage[channel].offset); @@ -1223,8 +1294,12 @@ namespace Hantek { double offsetReal = (double) (offsetValue - minimum) / (maximum - minimum); // SetOffset control command for channel offset - static_cast(this->control[CONTROLINDEX_SETOFFSET])->setChannel(channel, offsetValue); - this->controlPending[CONTROLINDEX_SETOFFSET] = true; + // Don't set control command if 6022be. + // Otherwise, pipe error messages will be appeared. + if (this->device->getModel() != MODEL_DSO6022BE) { + static_cast(this->control[CONTROLINDEX_SETOFFSET])->setChannel(channel, offsetValue); + this->controlPending[CONTROLINDEX_SETOFFSET] = true; + } this->settings.voltage[channel].offset = offset; this->settings.voltage[channel].offsetReal = offsetReal; @@ -1240,7 +1315,7 @@ namespace Hantek { if(!this->device->isConnected()) return Dso::ERROR_CONNECTION; - if(mode < Dso::TRIGGERMODE_AUTO || mode > Dso::TRIGGERMODE_SINGLE) + if(mode < Dso::TRIGGERMODE_AUTO || mode >= Dso::TRIGGERMODE_COUNT) return Dso::ERROR_PARAMETER; this->settings.trigger.mode = mode; @@ -1335,7 +1410,8 @@ namespace Hantek { unsigned short int levelValue = qBound((long int) minimum, (long int) ((this->settings.voltage[channel].offsetReal + level / this->specification.gainSteps[this->settings.voltage[channel].gain]) * (maximum - minimum) + 0.5) + minimum, (long int) maximum); // Check if the set channel is the trigger source - if(!this->settings.trigger.special && channel == this->settings.trigger.source) { + if(!this->settings.trigger.special && channel == this->settings.trigger.source + && this->device->getModel() != MODEL_DSO6022BE) { // SetOffset control command for trigger level static_cast(this->control[CONTROLINDEX_SETOFFSET])->setTrigger(levelValue); this->controlPending[CONTROLINDEX_SETOFFSET] = true; diff --git a/openhantek/src/hantek/control.h b/openhantek/src/hantek/control.h index b4df9c4..80e38a4 100644 --- a/openhantek/src/hantek/control.h +++ b/openhantek/src/hantek/control.h @@ -143,6 +143,9 @@ namespace Hantek { QList voltageLimit[HANTEK_CHANNELS]; /// The index of the selected gain on the hardware QList gainIndex; + QList gainDiv; + QList sampleSteps; ///< Available samplerate steps in s + QList sampleDiv; /// Calibration data for the channel offsets \todo Should probably be a QList too unsigned short int offsetLimit[HANTEK_CHANNELS][9][OFFSET_COUNT]; }; diff --git a/openhantek/src/hantek/device.cpp b/openhantek/src/hantek/device.cpp index c0b1733..2626f76 100644 --- a/openhantek/src/hantek/device.cpp +++ b/openhantek/src/hantek/device.cpp @@ -249,7 +249,11 @@ namespace Hantek { int Device::bulkCommand(Helper::DataArray *command, int attempts) { if(!this->handle) return LIBUSB_ERROR_NO_DEVICE; - + + // don't send bulk command if dso6022be + if (this->getModel() == MODEL_DSO6022BE) + return 0; + // Send BeginCommand control command int errorCode = this->controlWrite(CONTROL_BEGINCOMMAND, this->beginCommandControl->data(), this->beginCommandControl->getSize()); if(errorCode < 0) diff --git a/openhantek/src/hantek/types.cpp b/openhantek/src/hantek/types.cpp index f681464..e4ad2c6 100644 --- a/openhantek/src/hantek/types.cpp +++ b/openhantek/src/hantek/types.cpp @@ -1057,11 +1057,11 @@ namespace Hantek { // class ControlSetTimeDIV /// \brief Sets the data array to the default values. ControlSetTimeDIV::ControlSetTimeDIV() : Helper::DataArray(1) { - this->init(); + this->setDiv(1); } - void ControlSetTimeDIV::init() { - this->array[0] = 0x01; + void ControlSetTimeDIV::setDiv(uint8_t val) { + this->array[0] = val; } ////////////////////////////////////////////////////////////////////////////// diff --git a/openhantek/src/hantek/types.h b/openhantek/src/hantek/types.h index 282b035..470207e 100644 --- a/openhantek/src/hantek/types.h +++ b/openhantek/src/hantek/types.h @@ -39,7 +39,7 @@ #define HANTEK_EP_OUT 0x02 ///< OUT Endpoint for bulk transfers #define HANTEK_EP_IN 0x86 ///< IN Endpoint for bulk transfers #define HANTEK_TIMEOUT 500 ///< Timeout for USB transfers in ms -#define HANTEK_TIMEOUT_MULTI 10 ///< Timeout for multi packet USB transfers in ms +#define HANTEK_TIMEOUT_MULTI 100 ///< Timeout for multi packet USB transfers in ms #define HANTEK_ATTEMPTS 3 ///< The number of transfer attempts #define HANTEK_ATTEMPTS_MULTI 1 ///< The number of multi packet transfer attempts @@ -1186,8 +1186,7 @@ namespace Hantek { class ControlSetTimeDIV : public Helper::DataArray { public: ControlSetTimeDIV(); - private: - void init(); + void setDiv(uint8_t val); }; ////////////////////////////////////////////////////////////////////////////// diff --git a/openhantek/src/helper.cpp b/openhantek/src/helper.cpp index d75c583..5b09867 100644 --- a/openhantek/src/helper.cpp +++ b/openhantek/src/helper.cpp @@ -192,7 +192,7 @@ namespace Helper { switch(unit) { case UNIT_VOLTS: { // Voltage string decoding - if(unitString.startsWith('\265')) + if(unitString.startsWith("ยต")) return value * 1e-6; else if(unitString.startsWith('m')) return value * 1e-3; diff --git a/openhantek/src/openhantek.cpp b/openhantek/src/openhantek.cpp index b053d3d..2fe1ab6 100644 --- a/openhantek/src/openhantek.cpp +++ b/openhantek/src/openhantek.cpp @@ -317,6 +317,7 @@ void OpenHantekMainWindow::connectSignals() { connect(this->dsoControl, SIGNAL(availableRecordLengthsChanged(QList)), this->horizontalDock, SLOT(availableRecordLengthsChanged(QList))); connect(this->dsoControl, SIGNAL(samplerateLimitsChanged(double, double)), this->horizontalDock, SLOT(samplerateLimitsChanged(double, double))); + connect(this->dsoControl, SIGNAL(samplerateSet(int, QList)), this->horizontalDock, SLOT(samplerateSet(int, QList))); } /// \brief Initialize the device with the current settings. diff --git a/openhantek/src/sispinbox.cpp b/openhantek/src/sispinbox.cpp index 7bf14a4..b5ecb13 100644 --- a/openhantek/src/sispinbox.cpp +++ b/openhantek/src/sispinbox.cpp @@ -112,9 +112,9 @@ void SiSpinBox::stepBy(int steps) { if(!this->steppedTo) { // No step done directly before this one, so we need to check where we are // Get how often the steps have to be fully ran through - int stepsFully = (int) floor(log(this->value() / this->steps.first()) / log(stepsSpan)); + int stepsFully = (this->mode == 0) ? (int) floor(log(this->value() / this->steps.first()) / log(stepsSpan)) : 0; // And now the remaining multiple - double stepMultiple = this->value() / pow(stepsSpan, stepsFully); + double stepMultiple = (this->mode == 0) ? this->value() / pow(stepsSpan, stepsFully) : this->value() / this->minimum(); // Now get the neighbours of the current value from our steps list int remainingSteps = 0; for(; remainingSteps <= stepsCount; ++remainingSteps) { @@ -132,10 +132,14 @@ void SiSpinBox::stepBy(int steps) { int subStep = steps / abs(steps); for (int i = 0; i != steps; i += subStep) { this->stepId += subStep; + if (!this->mode) { int stepsId = this->stepId % stepsCount; if(stepsId < 0) stepsId += stepsCount; value = pow(stepsSpan, floor((double) this->stepId / stepsCount)) * this->steps[stepsId]; + } else { + value = this->minimum() * this->steps[stepId]; + } if (value <= this->minimum() || value >= this->maximum()) break; } @@ -167,6 +171,12 @@ void SiSpinBox::setSteps(const QList &steps) { this->steps = steps; } +/// \brief Set the mode. +/// \param mode The mode, the value 0 will have fixed interval, otherwise the value will have interval within steps itself. +void SiSpinBox::setMode(const int mode) { + this->mode = mode; +} + /// \brief Generic initializations. void SiSpinBox::init() { this->setMinimum(1e-12); @@ -178,6 +188,7 @@ void SiSpinBox::init() { this->steppedTo = false; this->stepId = 0; + this->mode = 0; connect(this, SIGNAL(valueChanged(double)), this, SLOT(resetSteppedTo())); } diff --git a/openhantek/src/sispinbox.h b/openhantek/src/sispinbox.h index 6f9f655..975c2d6 100644 --- a/openhantek/src/sispinbox.h +++ b/openhantek/src/sispinbox.h @@ -56,6 +56,7 @@ class SiSpinBox : public QDoubleSpinBox bool setUnit(Helper::Unit unit); void setUnitPostfix(const QString &postfix); void setSteps(const QList &steps); + void setMode(const int mode); private: void init(); @@ -63,6 +64,8 @@ class SiSpinBox : public QDoubleSpinBox Helper::Unit unit; ///< The SI unit used for this spin box QString unitPostfix; ///< Shown after the unit QList steps; ///< The steps, begins from start after last element + int mode; ///< The mode, fixed or constant + bool steppedTo; ///< true, if the current value was reached using stepBy int stepId; ///< The index of the last step reached using stepBy diff --git a/readme.md b/readme.md index bbd8088..49230ab 100644 --- a/readme.md +++ b/readme.md @@ -18,16 +18,16 @@ Navigate to the [Releases](https://github.com/OpenHantek/openhantek/releases) pa ## Building OpenHantek from source You need the following packages, to build OpenHantek from source: -* CMake 3.0+ +* CMake 3.5+ * Qt 5.3+ * FFTW 3+ (prebuild files will be downloaded on windows) -* libusb 1.x (prebuild files will be downloaded on windows) +* libusb 1.x (prebuild files will be used on windows) For debian based systems (Ubuntu, Mint) install named requirements like this: -> apt-get install cmake qttools5-dev qttools5-dev-tools libfftw3-dev binutils-dev libusb-1.0-0-dev +> apt-get install g++ cmake qttools5-dev qttools5-dev-tools libfftw3-dev binutils-dev libusb-1.0-0-dev For rpm based distributions (Fedora) use this command: -> dnf install cmake qt5-qtbase-gui qt5-qttools-devel qt5-qttranslations fftw-devel binutils-devel libusb-devel +> dnf install cmake gcc-c++ qt5-qtbase-gui qt5-qttools-devel qt5-qttranslations fftw-devel binutils-devel libusb-devel For MacOSX use homebrew > brew update
@@ -53,11 +53,28 @@ Your DSO does not store its firmware permanently -- the firmware has to be sent * You need binutils-dev autoconf automake fxload * Install the `firmware/*.hex` files into `/usr/local/share/hantek/`. + +> mkdir -p /usr/local/share/hantek
+> cp -r firmware/*.hex /usr/local/share/hantek/ + * Install the `firmware/90-hantek.rules` file into `/etc/udev/rules.d/`. -* install fxload (fxload is a program which downloads firmware to USB devices based on - AnchorChips EZ-USB, Cypress EZ-USB FX, or Cypress EZ-USB FX2 microcontrollers.) + +> cp firmware/90-hantek.rules /etc/udev/rules.d/ + +* install fxload (fxload is a program which downloads firmware to USB devices based on AnchorChips EZ-USB, Cypress EZ-USB FX, or Cypress EZ-USB FX2 microcontrollers.) + +> apt-get install fxload + * Add your current user to the **plugdev** group. +> usermod -a -G plugdev {user id} + +## For 6022BE +You can adjust samplerate and use software triggering for 6022BE. + - Support 48, 24, 16, 8, 4, 2, 1 M and 500, 200, 100 k Hz samplerates with modded firmware by [jhoenicke](https://github.com/rpcope1/Hantek6022API) + - Support software trigger by detecting rising or falling edge of signal. Use software trigger item on the trigger menu. For trigger level, adjust left arrow on the right-side of the graph. + - Note that I dropped first 1000 samples due to unstable/unusual reading. + ## Contribute Please use Github Issues to report any problems or enhancements or send us pull requests. Some random notes: - Read [how to properly contribute to open source projects on GitHub][10].