diff --git a/COPYING b/COPYING index 94a9ed024d3859793618152ea559a168bbcbb5e2..818433ecc0e094a4db1023c68b33f24344643ad8 100755 --- a/COPYING +++ b/COPYING @@ -1,674 +1,674 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - 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 3 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, see <http://www.gnu.org/licenses/>. - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - <program> Copyright (C) <year> <name of author> - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -<http://www.gnu.org/licenses/>. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -<http://www.gnu.org/philosophy/why-not-lgpl.html>. + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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 3 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, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>. diff --git a/README.md b/README.md index b28528e30c70508210fb47915bd493fddf5b1039..220ed6c58ec9977c8a9054b2098eecdf57b364b6 100644 --- a/README.md +++ b/README.md @@ -1,106 +1,106 @@ -# Introduction # - -Special Measure provides a simple frontend for MATLAB's instrument control toolbox, allowing users to quickly set up flexible scans through parameter space. - -# Installation # -Please see [Installation](doc/Installation.md) for install instructions. - -# Quick Reference # - -Please see the [Overview](doc/Overview.md) page for a list of Special Measure functions, -and [Error Messages](doc/ErrorMessages.md) for a list of common error messages and what to do. - -# Configuration Data # - * [scan](doc/Scans_new.md) (structure) - * [smdata](doc/smdata_new.md) (global structure) - - -# Structure of Special Measure # - -### Instruments and channels ### - -Each hardware device is represented by an instrument (not to be confused with -MATLAB instrument objects) that contains information about how to control it -and what channels (see below) it provides. This information roughly corresponds -to the hardcoded instrument drivers and channel array in Labview SM. - - -The channel concept is very similar to that of Labview SM - each channel -represents some parameter, input or output value of an instrument. -In most cases, it will be some physical quantity. -There is currently no distinction between write and read channels. -All channels should support a read operation, but it is -up to the user to make sure that channels that do not support write operations -(typically acqusition devices) are not used as set channels. -Writeable channels should always accept and return a single double, but -read-only channels can also return matrices of arbitrary dimension - e.g. -a vector representing a complete scan line. -Writeable channels can be self ramping, in which case its variable can be -ramped by the corresponding instrument. If available, this feature is always -used to set channel values (function smset), and can also be used for -measurements. - -Information about instruments, channels (i.e. the rack) and other -configuration is stored in the global struct smdata. Channels and -instruments are stored in the struct array smdata.channels and smdata.inst. -Major changes to smdata.inst are only required when adding new instruments -or updating drivers, but it may occasionally be necessary to change certain -instrument parameters, such as the data dimension for read channels. - - - -### Specifying instruments and channels ### - ---- - -Internally, channels and instruments are identified by their indices -to the struct arrays smdata.inst and smdata.channels. These indices -(printed at the beginning of each line by smprintchannels and -smprintinst can also be used to specify channels and instruments in -function arguments, including scan definition. Alternatively, channel -and instruments names can be used. Lists of names can be given as a -char arrays or cell vectors of strings. The conversion from names to -indices is typically done with smchanlookup and sminstlookup. -Channel names should always be unique. Instruments can be called by their -instrument type identifier (smdata.inst().device, e.g. SR830) if there is only -one such instrument in the rack, or an optional name, which should be unique -amongst instrument types and names. Instruments with a name should generally -be called by that name. - -### Adding and removing channels ### - ---- - -To add a channel, use the [smaddchannel](doc/smaddchannel.md) function. Note that depending -on the instrument, further configuration may be necessary. -(Particularly for channels to be ramped for data taking, or matrix-valued -channels). - -To remove one or several channels ch, just type "[smdata](doc/smdata#channels.md).channels(ch) = `[]`;" -Note that this will change the indices of all subsequent channels. - - -### Displaying configuration ### - ---- - -Use the smprintfunctions to display the most important configuration -information. - - -### Displaying the current channel values ### - ---- - -The current values of all scalar channels can be displayed in figure 1001 -if this figure is initialized by calling "sminitdisp". The displayed values -will be updated by every call of smget and smset for each channel. -To disable this feature, close figure 1001. - - -### Specifying a scan ### - ---- - -The measurement task to be excecuted by [smrun](doc/smrun.md) is defined by a [scan](doc/Scans_new.md) struct passed to [smrun](doc/smrun.md). For explanations of its fields, see [scan](doc/Scans_new.md). -Note that some of the parameters are optional. +# Introduction # + +Special Measure provides a simple frontend for MATLAB's instrument control toolbox, allowing users to quickly set up flexible scans through parameter space. + +# Installation # +Please see [Installation](doc/Installation.md) for install instructions. + +# Quick Reference # + +Please see the [Overview](doc/Overview.md) page for a list of Special Measure functions, +and [Error Messages](doc/ErrorMessages.md) for a list of common error messages and what to do. + +# Configuration Data # + * [scan](doc/Scans_new.md) (structure) + * [smdata](doc/smdata_new.md) (global structure) + + +# Structure of Special Measure # + +### Instruments and channels ### + +Each hardware device is represented by an instrument (not to be confused with +MATLAB instrument objects) that contains information about how to control it +and what channels (see below) it provides. This information roughly corresponds +to the hardcoded instrument drivers and channel array in Labview SM. + + +The channel concept is very similar to that of Labview SM - each channel +represents some parameter, input or output value of an instrument. +In most cases, it will be some physical quantity. +There is currently no distinction between write and read channels. +All channels should support a read operation, but it is +up to the user to make sure that channels that do not support write operations +(typically acqusition devices) are not used as set channels. +Writeable channels should always accept and return a single double, but +read-only channels can also return matrices of arbitrary dimension - e.g. +a vector representing a complete scan line. +Writeable channels can be self ramping, in which case its variable can be +ramped by the corresponding instrument. If available, this feature is always +used to set channel values (function smset), and can also be used for +measurements. + +Information about instruments, channels (i.e. the rack) and other +configuration is stored in the global struct smdata. Channels and +instruments are stored in the struct array smdata.channels and smdata.inst. +Major changes to smdata.inst are only required when adding new instruments +or updating drivers, but it may occasionally be necessary to change certain +instrument parameters, such as the data dimension for read channels. + + + +### Specifying instruments and channels ### + +--- + +Internally, channels and instruments are identified by their indices +to the struct arrays smdata.inst and smdata.channels. These indices +(printed at the beginning of each line by smprintchannels and +smprintinst can also be used to specify channels and instruments in +function arguments, including scan definition. Alternatively, channel +and instruments names can be used. Lists of names can be given as a +char arrays or cell vectors of strings. The conversion from names to +indices is typically done with smchanlookup and sminstlookup. +Channel names should always be unique. Instruments can be called by their +instrument type identifier (smdata.inst().device, e.g. SR830) if there is only +one such instrument in the rack, or an optional name, which should be unique +amongst instrument types and names. Instruments with a name should generally +be called by that name. + +### Adding and removing channels ### + +--- + +To add a channel, use the [smaddchannel](doc/smaddchannel.md) function. Note that depending +on the instrument, further configuration may be necessary. +(Particularly for channels to be ramped for data taking, or matrix-valued +channels). + +To remove one or several channels ch, just type "[smdata](doc/smdata#channels.md).channels(ch) = `[]`;" +Note that this will change the indices of all subsequent channels. + + +### Displaying configuration ### + +--- + +Use the smprintfunctions to display the most important configuration +information. + + +### Displaying the current channel values ### + +--- + +The current values of all scalar channels can be displayed in figure 1001 +if this figure is initialized by calling "sminitdisp". The displayed values +will be updated by every call of smget and smset for each channel. +To disable this feature, close figure 1001. + + +### Specifying a scan ### + +--- + +The measurement task to be excecuted by [smrun](doc/smrun.md) is defined by a [scan](doc/Scans_new.md) struct passed to [smrun](doc/smrun.md). For explanations of its fields, see [scan](doc/Scans_new.md). +Note that some of the parameters are optional. diff --git a/doc/ErrorMessages.md b/doc/ErrorMessages.md index e9ea4a7f4578aea1b1321f942d5eb0af2948b247..89159ec9d5cc8a74e814089750c565652c5d6449 100644 --- a/doc/ErrorMessages.md +++ b/doc/ErrorMessages.md @@ -1,25 +1,25 @@ - - - -# VISA Errors # -These are errors common to all VISA (most USB and ethernet devices) -connected devices. - -``` -??? Error using ==> icinterface.fprintf at 147 -VISA: The connection for the given session has been lost. -``` - -USB and Ethernet VISA connections will be closed if the device is disconnected or rebooted. **[smclose](smclose.md)** and **[smopen](smopen.md)** the device. - -# AWG Errors # -``` --500,"Power On" -``` - -The AWG was just turned on. Harmless, ignore. - -``` -"Sequence/Waveform loading error; E11203 - AWGC:RUN" -``` + + + +# VISA Errors # +These are errors common to all VISA (most USB and ethernet devices) +connected devices. + +``` +??? Error using ==> icinterface.fprintf at 147 +VISA: The connection for the given session has been lost. +``` + +USB and Ethernet VISA connections will be closed if the device is disconnected or rebooted. **[smclose](smclose.md)** and **[smopen](smopen.md)** the device. + +# AWG Errors # +``` +-500,"Power On" +``` + +The AWG was just turned on. Harmless, ignore. + +``` +"Sequence/Waveform loading error; E11203 - AWGC:RUN" +``` No waveform defined for one of the channels. Probably the AWG is not in sequence mode. \ No newline at end of file diff --git a/doc/Installation.md b/doc/Installation.md index bbae8d946a682b4a66290cff363ae09361fb9b4b..13024ad9f0174ecf2fe697aaef18e0eb423dc44b 100644 --- a/doc/Installation.md +++ b/doc/Installation.md @@ -1,34 +1,34 @@ -# Installation # -Special Measure is best installed using the Mercurial version control system. For windows users, we recommend the GUI available at -http://tortoisehg.bitbucket.org/. See the Source page for further download instructions. - -After creating a local clone, (http://code.google.com/p/special-measure/source/checkout) add the following directories to the MATLAB search path, where "install-dir" needs to be replaced by the complete installation directory: - -``` -install-dir\sm -install-dir\sm\procfn -install-dir\sm\channels -install-dir\sm GUI -``` - -# Startup # - -To set up a MATLAB session for running SM, proceed as follows: - * You need an instrument control toolbox. (ie., the National Instruments or Tektronix drivers) - * Make sure the sm and sm/channels directories are in the path. - * Make smdata accessible from the workspace by typing `global smdata;` This is necessary only once per Matlab session, or after a `clear global` command. - * Load a rack from a MATLAB (.mat) file, e.g. -> > "load install-dir/sm/sm\_config/smdata\_base". - * Open instruments with smopen. (Assuming they follow the standard convention discussed in section "Writing instrument drivers".) - -The following examples for getting started can be found in the `install-dir\config` directory: - -`smsetup.m`: Create a rack (i.e. system configuration)<br> -<code>smsetup.m</code>: Reload a previosly created rack after restarting matlab<br> -<code>smscanconf.m</code>: Configure a simple scan<br> -<br> -Occasionally, it may be necessary to close and reopen instruments, for example to change certain properties such as the buffer size, or if the instrument crashes. For instruments following the standard convention, this can be done with <a href='smclose.md'>smclose</a> and <a href='smopen.md'>smopen</a>.<br> -<br> -<h3>See Also</h3> -<ul><li><a href='smdata.md'>smdata</a> +# Installation # +Special Measure is best installed using the Mercurial version control system. For windows users, we recommend the GUI available at +http://tortoisehg.bitbucket.org/. See the Source page for further download instructions. + +After creating a local clone, (http://code.google.com/p/special-measure/source/checkout) add the following directories to the MATLAB search path, where "install-dir" needs to be replaced by the complete installation directory: + +``` +install-dir\sm +install-dir\sm\procfn +install-dir\sm\channels +install-dir\sm GUI +``` + +# Startup # + +To set up a MATLAB session for running SM, proceed as follows: + * You need an instrument control toolbox. (ie., the National Instruments or Tektronix drivers) + * Make sure the sm and sm/channels directories are in the path. + * Make smdata accessible from the workspace by typing `global smdata;` This is necessary only once per Matlab session, or after a `clear global` command. + * Load a rack from a MATLAB (.mat) file, e.g. +> > "load install-dir/sm/sm\_config/smdata\_base". + * Open instruments with smopen. (Assuming they follow the standard convention discussed in section "Writing instrument drivers".) + +The following examples for getting started can be found in the `install-dir\config` directory: + +`smsetup.m`: Create a rack (i.e. system configuration)<br> +<code>smsetup.m</code>: Reload a previosly created rack after restarting matlab<br> +<code>smscanconf.m</code>: Configure a simple scan<br> +<br> +Occasionally, it may be necessary to close and reopen instruments, for example to change certain properties such as the buffer size, or if the instrument crashes. For instruments following the standard convention, this can be done with <a href='smclose.md'>smclose</a> and <a href='smopen.md'>smopen</a>.<br> +<br> +<h3>See Also</h3> +<ul><li><a href='smdata.md'>smdata</a> </li><li><a href='SpecialMeasure.md'>SpecialMeasure</a> \ No newline at end of file diff --git a/doc/OOSM.md b/doc/OOSM.md index 5089178960240ca4e00b27cd2574e81e79787e72..cab521bcab0b1bd9448e9c36a56b73e450c89e70 100644 --- a/doc/OOSM.md +++ b/doc/OOSM.md @@ -1,25 +1,25 @@ -# Introduction # - -Mikey's ideas. Please add/comment/criticize, etc. - -## Summary ## -The goal is to use OO programming to improve special measure. In particular, this aims to make reading and writing instrument drivers and creating instruments easier. -each instrument is a class that inherits from a superclass sminst. Each inst has an array of sminstchans, which are the channels. The instrument overloads the functions set, get, trigger, arm, etc. The superclass sminst defaults to calling the cntlfn for the instruments to keep things backward compatible. - -## Classes ## -### sminst ### -superclass of instruments. each instrument will inherit and overload methods. It has properties: matlabobject, cntlfn, channels (see sminstchan), name. -Objects that inherit from this will overload useful methods, including a constructor, which will make defining instruments **much** more straight forward. - -### sminstchan ### -channels that are part of an instrument. these are incredibly simple object, but allow for some specialize functionality if you want. It has properties: setable (boolean), name, HWramp, lims, datadim, datatype -It is unclear how much of this should be party of smdata.inst.channels and how much should be part of smdata.channels. - -# Implementation and Changes # -smdata.inst is now a **cell** array because matlab does not allow arrays of different objects, even if they inherit from the same class. This means that lots of smdata.inst(x) need to change to smdata.inst{x} which will be annoying to find. -smset and smget would change reasonably trivially to call get(inst,chan) or set(instr,chan,val) etc instead of calling a cntlfn. - -# Pros and Cons # - * Much easier to write new drivers and create new instruments. - * Code is much easier to read +# Introduction # + +Mikey's ideas. Please add/comment/criticize, etc. + +## Summary ## +The goal is to use OO programming to improve special measure. In particular, this aims to make reading and writing instrument drivers and creating instruments easier. +each instrument is a class that inherits from a superclass sminst. Each inst has an array of sminstchans, which are the channels. The instrument overloads the functions set, get, trigger, arm, etc. The superclass sminst defaults to calling the cntlfn for the instruments to keep things backward compatible. + +## Classes ## +### sminst ### +superclass of instruments. each instrument will inherit and overload methods. It has properties: matlabobject, cntlfn, channels (see sminstchan), name. +Objects that inherit from this will overload useful methods, including a constructor, which will make defining instruments **much** more straight forward. + +### sminstchan ### +channels that are part of an instrument. these are incredibly simple object, but allow for some specialize functionality if you want. It has properties: setable (boolean), name, HWramp, lims, datadim, datatype +It is unclear how much of this should be party of smdata.inst.channels and how much should be part of smdata.channels. + +# Implementation and Changes # +smdata.inst is now a **cell** array because matlab does not allow arrays of different objects, even if they inherit from the same class. This means that lots of smdata.inst(x) need to change to smdata.inst{x} which will be annoying to find. +smset and smget would change reasonably trivially to call get(inst,chan) or set(instr,chan,val) etc instead of calling a cntlfn. + +# Pros and Cons # + * Much easier to write new drivers and create new instruments. + * Code is much easier to read * development is tricky: matlab does not deal with having two versions of the same class in memory. there are also other object oriented oddities in matlab. this means you need to have a clear idea of what you want. \ No newline at end of file diff --git a/doc/Overview.md b/doc/Overview.md index 6352aa03c1a03652f23d7ef69a6a8677d63001bd..e827f0cb3c7730fe3f410e1061d0ab771ad2bbaa 100644 --- a/doc/Overview.md +++ b/doc/Overview.md @@ -1,78 +1,78 @@ -# Introduction # - -Special Measure provides a simple frontend for MATLAB's instrument control toolbox, allowing users to quickly set up flexible scans through parameter space. - - - ---- - -# Quick Reference # -## Structures ## - * [Scans\_new](Scans_new.md) - * [smdata\_new](smdata_new.md) - -## Functions ## -### Main measurement routine ### -| **[smrun](smrun.md)** | Run a scan. | -|:----------------------|:------------| - -### Channel Control ### -| **[smset](smset.md)** | Set channel values. | -|:----------------------|:----------------------| -| **[smget](smget.md)** | Read channel values. | -| **[smprintchannels](smprintchannels.md)** | Print channel information | -| **[smprintrange](smprintrange.md)** | Print range and rate information | - -### Scan configuration ### -| **[smdiagpar](smdiagpar.md)** | Configure scan rotation. | -|:--------------------------------|:-------------------------| -| **[smscanpar](smscanpar.md)** | Set scan range and resolution. | -| **[smalintrafo](smalintrafo.md)** | Set up a rotated scan. | -| **[smprintscan](smprintscan.md)** | Print scan parameters. | - -### Setup ### -| **[smaddchannel](smaddchannel.md)** | Create a new channel | -|:------------------------------------|:---------------------| -| **[sminitdisp](sminitdisp.md)** | Configure figure 1001 to display current channel values. To disable this feature, close figure 1001. | - -### Instrument Control ### -| **[smopen](smopen.md)** | Open instruments. | -|:-------------------------|:--------------------| -| **[smclose](smclose.md)** | Close instruments. | -| **[smprintinst](smprintinst.md)** | Print instrument information | - -### Low-level Instrument I/O ### -| **[smprintf](smprintf.md)** | Wrapper for fprintf. | -|:----------------------------|:---------------------| -| **[smscanf](smscanf.md)** | Wrapper for fscanf. | -| **[smquery](smquery.md)** | Wrapper for query. | - - ---- - -## Auxiliary functions ## -### Configuration and control of specific instruments ### - -| **smarampYokoSR830dmm** | Set up linewise acquisition with dmm and/or lockin | -|:------------------------|:---------------------------------------------------| -| **smarampYokoSR830** | Subset of above, no dmm support | -| **smarampYokoTDS** | Set up linewise acquisition with TDS5104. | -| **smaDMMsnglmode** | Restore default sample parameters for DMM(s). | -| **smastopYokos** | Stop ramps on Yokos. | - -### Trigger routines (used as trigfn's) ### -| **smatrigYokoSR830dmm** | | -|:------------------------|:| -| **smatrigYokoTDS** | | -| **smatrigYokoSR830** | (Obsolete, no longer maintained) | -| **smatrig** | | - - ---- - -### Other routines, mainly used internally ### -| **smdispchan** | Update display of current values | -|:-----------------|:---------------------------------| -| **smchanlookup** | Translation from channel name to index | -| **sminstlookup** | Translation form device name to index | +# Introduction # + +Special Measure provides a simple frontend for MATLAB's instrument control toolbox, allowing users to quickly set up flexible scans through parameter space. + + + +--- + +# Quick Reference # +## Structures ## + * [Scans\_new](Scans_new.md) + * [smdata\_new](smdata_new.md) + +## Functions ## +### Main measurement routine ### +| **[smrun](smrun.md)** | Run a scan. | +|:----------------------|:------------| + +### Channel Control ### +| **[smset](smset.md)** | Set channel values. | +|:----------------------|:----------------------| +| **[smget](smget.md)** | Read channel values. | +| **[smprintchannels](smprintchannels.md)** | Print channel information | +| **[smprintrange](smprintrange.md)** | Print range and rate information | + +### Scan configuration ### +| **[smdiagpar](smdiagpar.md)** | Configure scan rotation. | +|:--------------------------------|:-------------------------| +| **[smscanpar](smscanpar.md)** | Set scan range and resolution. | +| **[smalintrafo](smalintrafo.md)** | Set up a rotated scan. | +| **[smprintscan](smprintscan.md)** | Print scan parameters. | + +### Setup ### +| **[smaddchannel](smaddchannel.md)** | Create a new channel | +|:------------------------------------|:---------------------| +| **[sminitdisp](sminitdisp.md)** | Configure figure 1001 to display current channel values. To disable this feature, close figure 1001. | + +### Instrument Control ### +| **[smopen](smopen.md)** | Open instruments. | +|:-------------------------|:--------------------| +| **[smclose](smclose.md)** | Close instruments. | +| **[smprintinst](smprintinst.md)** | Print instrument information | + +### Low-level Instrument I/O ### +| **[smprintf](smprintf.md)** | Wrapper for fprintf. | +|:----------------------------|:---------------------| +| **[smscanf](smscanf.md)** | Wrapper for fscanf. | +| **[smquery](smquery.md)** | Wrapper for query. | + + +--- + +## Auxiliary functions ## +### Configuration and control of specific instruments ### + +| **smarampYokoSR830dmm** | Set up linewise acquisition with dmm and/or lockin | +|:------------------------|:---------------------------------------------------| +| **smarampYokoSR830** | Subset of above, no dmm support | +| **smarampYokoTDS** | Set up linewise acquisition with TDS5104. | +| **smaDMMsnglmode** | Restore default sample parameters for DMM(s). | +| **smastopYokos** | Stop ramps on Yokos. | + +### Trigger routines (used as trigfn's) ### +| **smatrigYokoSR830dmm** | | +|:------------------------|:| +| **smatrigYokoTDS** | | +| **smatrigYokoSR830** | (Obsolete, no longer maintained) | +| **smatrig** | | + + +--- + +### Other routines, mainly used internally ### +| **smdispchan** | Update display of current values | +|:-----------------|:---------------------------------| +| **smchanlookup** | Translation from channel name to index | +| **sminstlookup** | Translation form device name to index | | **smchaninst** | get instrument associated with a channel | \ No newline at end of file diff --git a/doc/Procfn.md b/doc/Procfn.md index dc3465fcdeadb0e764d7046f9711982b58b548cf..f30e3fbfcf5baa1442388fc75d8d4abb7619349e 100644 --- a/doc/Procfn.md +++ b/doc/Procfn.md @@ -1,86 +1,86 @@ -## procfn ## -`procfns` are used to process incoming data during a scan (see [Scans\_new](Scans_new.md) for info on scans). They are more complicated than most of the other functions embedded in scans because they determine how data is allocated and gathered. - -If a loop has `n` getchans and stores an additional `m` cells of processed data, its procfn will be a struct of length `m+n`. If data from a getchan does not need processing, you can leave its procfn empty. Each `procfn` has fields `fn` and `dim`. - -`fn` is a struct that determines what processing to do. Its length is the number of processing functions for that channel. These are run in order, so data can be processed serially across fns. - -`fn` has fields (terms defined below): - * fn, args, which have the same format as for prefns, etc. - * inchan, outchan: These are used to send new data from one channel to another. The data to be processed is taken from loop index inchan and placed in loop index outchan. - * indata, outdata. Procfns with indata and outdata let you process both `newdata` and stored `data` (so data from different loops can be processed together). They also directly store the processed data as a data cell, rewriting it at each loop iteration. - -`dim` gives the size of the processed data. If the dimension of processed data is different than defined for that channel in the inst's datadim, smrun has no way of knowing the size of data when creating cells to store data. Instead it is specified here. See Examples section for more info. - -A few useful smrun concepts for understanding procfns - * channel / data indices : Each getchan has two indices. One corresponds to the overall index (data index) within the scan, which counts from 1 for the first loop's first getchan across getchans and then loops. The other is the index within the loop (loop index), which counts up from 1 for the first getchan in each loop. The data index counts channels created by procfns: if there are 2 getchans in the first loop, plus an additional channel for processed data, and 1 getchan in the 2nd loop, the data index of the channel in the second loop is 4. Data index is used for indata / outdata, loop index for inchan / outchan. - * `newdata` vs. `data`: At each iteration in a scan, `smget` gathers data from all the `getchans` in the current loop and stores it in the cell array `newdata`. Procfns with `inchans/outchans` only will process the `newdata` only. The indices of the `inchans/outchans` refer to loop indices. fns with `indata/outdata` fields and `inchan/outchan` fields can process stored data and `newdata` and assign the final data to both `newdata` with loop index `outchan` and `data` with the `outdata` index. However, the index for `indata/outdata` is not the overall data index, but the overall data index subtracting the overall data index at the for the last channel of the last loop. This means it can be negative if you want indata from an inner loop. Procfns with outdata also bypass storing the newdata in data, so you will have to send newdata to an additional channel to store it. See the final example for more info. - -There are some useful rules to know for defining procfns: - 1. If there is an outdata but no indata, indata gets the value of outdata. - 1. If there is no inchan it gets the loop index. - 1. If there is a procfn.fn, but no outchan, it gets the value of inchan. - 1. If there is a dim in the procfn corresponding to the get chan, that sets the dim. Otherwise, it is taken from smdata.inst.datadim for the channel. - 1. Since data channels created via a procfn have no channel in smdata, they need to have dim defined. - 1. Data from multiple inchans will look like separate inputs to the procfn, so those functions should have inputs in form `function procfn(inchan1, inchan2)` - 1. If fn has a fn and an outchan not equal to its loop index, the output of fn will be stored in both the current loop index and the outchan index. - -## Examples ## -**Example 1** - -Send data from channel 1 to channel 3. dim always needs to be set for channels created by procfns. -``` -scan.loops(1).procfn(1).fn - inchan: 1 - outchan: 3 -scan.loops(1).procfn(3).dim: 100 -``` - -**Example 2** - -Perform function to change the size of data in channel 1, by first reshaping 8000 datapoints into an 80 x 100 array, then averaging them to get a 1 x 100 array. dim needs to be set for channels where data changes size. - -``` -scan.loops(1).procfn(1).fn(1) - fn: @reshape - args: {[80,100]}; -scan.loops(1).procfn(1).fn(2) - fn: @mean - args: {}; -scan.loops(1).procfn(1).dim: 100 -``` - -**Example 3** - -Send data from channel 1 and 2 to channel 3, divide chan 1 data by chan 2 data. -``` - scan.loops(1).procfn(1).fn: [] - scan.loops(1).procfn(2).fn: []; - scan.loops(1).procfn(3).fn - fn: @rdivide - args: {}; - inchan: [1,2] - outchan: [3] - scan.loops(1).procfn(3).dim = 100 -``` - -**Example 4** - -For scan with 2 loops, where the Loop 1 has 2 getchans and Loop 2 has 1 getchan, analyze `data` from Loop 1 Channel 1 and the `newdata` from the Loop 2 Channel 1. -Note, your function will pull in all stored data from the 1st loop / 2nd chan, so you will need to write your function to ignore NaNs / other unimportant data. -``` -loops(2).procfn(1): [] -loops(2).procfn(2): - dim: 1 - fn: - fn: @samp_proc - args: {} - inchan: 1 - outchan: 3 - indata: -1 - outdata: 2 -loops(2).procfn(3): - dim: 1 - fn: [] -``` +## procfn ## +`procfns` are used to process incoming data during a scan (see [Scans\_new](Scans_new.md) for info on scans). They are more complicated than most of the other functions embedded in scans because they determine how data is allocated and gathered. + +If a loop has `n` getchans and stores an additional `m` cells of processed data, its procfn will be a struct of length `m+n`. If data from a getchan does not need processing, you can leave its procfn empty. Each `procfn` has fields `fn` and `dim`. + +`fn` is a struct that determines what processing to do. Its length is the number of processing functions for that channel. These are run in order, so data can be processed serially across fns. + +`fn` has fields (terms defined below): + * fn, args, which have the same format as for prefns, etc. + * inchan, outchan: These are used to send new data from one channel to another. The data to be processed is taken from loop index inchan and placed in loop index outchan. + * indata, outdata. Procfns with indata and outdata let you process both `newdata` and stored `data` (so data from different loops can be processed together). They also directly store the processed data as a data cell, rewriting it at each loop iteration. + +`dim` gives the size of the processed data. If the dimension of processed data is different than defined for that channel in the inst's datadim, smrun has no way of knowing the size of data when creating cells to store data. Instead it is specified here. See Examples section for more info. + +A few useful smrun concepts for understanding procfns + * channel / data indices : Each getchan has two indices. One corresponds to the overall index (data index) within the scan, which counts from 1 for the first loop's first getchan across getchans and then loops. The other is the index within the loop (loop index), which counts up from 1 for the first getchan in each loop. The data index counts channels created by procfns: if there are 2 getchans in the first loop, plus an additional channel for processed data, and 1 getchan in the 2nd loop, the data index of the channel in the second loop is 4. Data index is used for indata / outdata, loop index for inchan / outchan. + * `newdata` vs. `data`: At each iteration in a scan, `smget` gathers data from all the `getchans` in the current loop and stores it in the cell array `newdata`. Procfns with `inchans/outchans` only will process the `newdata` only. The indices of the `inchans/outchans` refer to loop indices. fns with `indata/outdata` fields and `inchan/outchan` fields can process stored data and `newdata` and assign the final data to both `newdata` with loop index `outchan` and `data` with the `outdata` index. However, the index for `indata/outdata` is not the overall data index, but the overall data index subtracting the overall data index at the for the last channel of the last loop. This means it can be negative if you want indata from an inner loop. Procfns with outdata also bypass storing the newdata in data, so you will have to send newdata to an additional channel to store it. See the final example for more info. + +There are some useful rules to know for defining procfns: + 1. If there is an outdata but no indata, indata gets the value of outdata. + 1. If there is no inchan it gets the loop index. + 1. If there is a procfn.fn, but no outchan, it gets the value of inchan. + 1. If there is a dim in the procfn corresponding to the get chan, that sets the dim. Otherwise, it is taken from smdata.inst.datadim for the channel. + 1. Since data channels created via a procfn have no channel in smdata, they need to have dim defined. + 1. Data from multiple inchans will look like separate inputs to the procfn, so those functions should have inputs in form `function procfn(inchan1, inchan2)` + 1. If fn has a fn and an outchan not equal to its loop index, the output of fn will be stored in both the current loop index and the outchan index. + +## Examples ## +**Example 1** + +Send data from channel 1 to channel 3. dim always needs to be set for channels created by procfns. +``` +scan.loops(1).procfn(1).fn + inchan: 1 + outchan: 3 +scan.loops(1).procfn(3).dim: 100 +``` + +**Example 2** + +Perform function to change the size of data in channel 1, by first reshaping 8000 datapoints into an 80 x 100 array, then averaging them to get a 1 x 100 array. dim needs to be set for channels where data changes size. + +``` +scan.loops(1).procfn(1).fn(1) + fn: @reshape + args: {[80,100]}; +scan.loops(1).procfn(1).fn(2) + fn: @mean + args: {}; +scan.loops(1).procfn(1).dim: 100 +``` + +**Example 3** + +Send data from channel 1 and 2 to channel 3, divide chan 1 data by chan 2 data. +``` + scan.loops(1).procfn(1).fn: [] + scan.loops(1).procfn(2).fn: []; + scan.loops(1).procfn(3).fn + fn: @rdivide + args: {}; + inchan: [1,2] + outchan: [3] + scan.loops(1).procfn(3).dim = 100 +``` + +**Example 4** + +For scan with 2 loops, where the Loop 1 has 2 getchans and Loop 2 has 1 getchan, analyze `data` from Loop 1 Channel 1 and the `newdata` from the Loop 2 Channel 1. +Note, your function will pull in all stored data from the 1st loop / 2nd chan, so you will need to write your function to ignore NaNs / other unimportant data. +``` +loops(2).procfn(1): [] +loops(2).procfn(2): + dim: 1 + fn: + fn: @samp_proc + args: {} + inchan: 1 + outchan: 3 + indata: -1 + outdata: 2 +loops(2).procfn(3): + dim: 1 + fn: [] +``` This stores the processed data in the 5th cell. The processed data from the most recent smget is stored in cell 4. \ No newline at end of file diff --git a/doc/ProjectHome.md b/doc/ProjectHome.md index 918ad40d35c1c4c22ec4ce8c27b6c0c55cefd334..9d6c21d6df062f391044a91312113d07f7d7ebf1 100644 --- a/doc/ProjectHome.md +++ b/doc/ProjectHome.md @@ -1,3 +1,3 @@ -Special Measure is measurement control software designed to provide a simple interface to control instruments and acquire data using MATLAB. - +Special Measure is measurement control software designed to provide a simple interface to control instruments and acquire data using MATLAB. + Please see [the documentation](SpecialMeasure.md) or [install instructions](Installation.md) for more information. \ No newline at end of file diff --git a/doc/PulseControl.md b/doc/PulseControl.md index 7d721e7d544baed33b53a2aad5c68aa47401eaa1..01ed96ed1dfe2d78767df4916b6ba77bf6b50220 100644 --- a/doc/PulseControl.md +++ b/doc/PulseControl.md @@ -1,24 +1,24 @@ -# Introduction # - -This is not real documentation. These are notes on the changes enacted to allow multiple AWG's to be combined. - - 1. smdata.inst(x).data can have a field "chain". If chain is set to y and a jump is requested on smdata.inst(x), the jump is also executed on smdata.inst(y). Chains can be recursive. Please avoid loops. - 1. awgdata can be a struct array of awg's. each awg can have a clk (clock rate), bits (bit depth), awgdata.awg (pointer to visa object in awgdata), slave (if set to 1, pulse groups begin with wait for triger), chans ( map of which channels the awg outputs, may be non-unique). -ie, -``` - awgdata(1).chans=[1 2 3 4]; - awgdata(1).clk=1e9; - awgdata(1).bits=14; - awgdata(2).chans=[3 4]; - awgdata(2).clk=1e10; - awgdata(2).slave=1; - awgdata(2).bits=10; -``` -will set up awg2 (a 7k) to wait for awg1 to trigger it. They will both output channels 3 and 4, so the markers on the 5k can be used in lieu of the markers on the 7k. - -# Details # - -Add your content here. Format your content with: - * Text in **bold** or _italic_ - * Headings, paragraphs, and lists +# Introduction # + +This is not real documentation. These are notes on the changes enacted to allow multiple AWG's to be combined. + + 1. smdata.inst(x).data can have a field "chain". If chain is set to y and a jump is requested on smdata.inst(x), the jump is also executed on smdata.inst(y). Chains can be recursive. Please avoid loops. + 1. awgdata can be a struct array of awg's. each awg can have a clk (clock rate), bits (bit depth), awgdata.awg (pointer to visa object in awgdata), slave (if set to 1, pulse groups begin with wait for triger), chans ( map of which channels the awg outputs, may be non-unique). +ie, +``` + awgdata(1).chans=[1 2 3 4]; + awgdata(1).clk=1e9; + awgdata(1).bits=14; + awgdata(2).chans=[3 4]; + awgdata(2).clk=1e10; + awgdata(2).slave=1; + awgdata(2).bits=10; +``` +will set up awg2 (a 7k) to wait for awg1 to trigger it. They will both output channels 3 and 4, so the markers on the 5k can be used in lieu of the markers on the 7k. + +# Details # + +Add your content here. Format your content with: + * Text in **bold** or _italic_ + * Headings, paragraphs, and lists * Automatic links to other wiki pages \ No newline at end of file diff --git a/doc/Scans_new.md b/doc/Scans_new.md index c84f564e8b775a81a8bf42349ad71ca967a3021d..c24a7ea822031dd8f6d77d839dc24d1b69b10ed8 100644 --- a/doc/Scans_new.md +++ b/doc/Scans_new.md @@ -1,152 +1,152 @@ -# Introduction # -A scan is a struct with all the information to acquire data. It is executed by smrun. There are many fields in this struct (some of which may be left blank), and understanding each one will help you understand how smrun works. - -Here is what matlab outputs when you type smscan: -``` - loops: [1x2 struct] - saveloop: 2 - configfn: [1x1 struct] - disp: [1x2 struct] - cleanupfn: [] - consts: [1x2 struct] -``` - -Here we will go through all of these fields and some additional ones too. - -# Loops # -scan.loops is the meat of the scan. The loops contain all of the informations about which channels should be swept or ramped, which channels should be recorded, etc. The size of scan.loops dictates the dimension of the scan to be performed: a 1-D (line scan) will have one loop, a 2-D scan will have two loops, etc. In general, each iteration of a loop might sweep a channel and get another channel. scan.loop(1) is the inner-most loop (executed most often) and scan.loops(end) is the outter-most loop (executed least often). Let's take a look at what is inside each loop. - -## setchan ## -These are the channels to be swept in this loop. The setchan can either be a string (one channel) or a cell array of strings if more than one channel is to be swept. Alternatively, setchans can also be numbers, which are indexes into smdata.channels. - -## rng ## -The range over which the setchan should be swept. In each iteration of the loop the setchan starts at rng(1) and ends at rng(2). Alteratively, rng may be a vector of values to which the setchans are set. For example, scan.loops(l).rng = linspace(0,1,11). - -## npoints ## -The number of points in the ramp. Over the course of the loop the setchan will be set to linspace(rng(1),rng(2),npoints). If length(rng) is great than 2, this field is ignored. - -## getchan ## -This is the channel whose value is recorded at every point during the loop. Like the setchan, the getchan can be a string or a cell array of strings. The getchan can also be empty, if, for example, the instrument in question can store many values and return them all at once (buffered acquisition). In this case, the inner loop of a scan would have an empty getchan, and the outter loop would have a getchan that would return its values for an entire iteration of the inner loop. - -## ramptime ## -The time (in seconds) to spend per point of each loop. If a loop has npoints=100 and a ramptime = .01 then one iteration of this loop will take one second. A negative ramptime is used to note that an instrument is capable of generating a ramp by itself (i.e. spacial measure does not need to set the setchans to each point). An empty ramptime (often used in outter loops of scans) signifies that the setchan is simply set (at a rate given by smdata.channels(ch).rangeramp(3)) to the appropriate value and held there. - -## trigfn ## -This field, which may be left blank, is a function that triggers this loop to run. For example, this might be a function call to a timing generator that fires a TTL signal. -**example** -if we want to do an automatic ramp of a voltage channel on a decaDAC it needs to be triggered. This can be done with an AWG using -``` -scan.loops(1).trigfn.fn = @smatrigawg; -scan.loops(1).trigfn.args = {[16]} -``` -which will call smatrigawg([16](16.md)) to trigger each iteration of the first loop. Here we use 16 because smdata.inst(16) is the AWG that will generate the trigger. - -## trafofn ## -This is short hand for transformationfunction. The first argument (named x below, not be be confused with trafofn.args) to the trafofn is a vector of the loops variables, starting with the inner-most loop. The second argument (named y below) of the trafofn is the current value of all the channels, as store in smdata.chanvals. -scan.loops(l).trafofn(k) will transform the range over which scan.loops(l).setchan{k} is swept. Ordinarily, a setchan is swept from rng(1) to rng(end) in npoints. However, it is often necessary to transform this sweep range into another one. For example, imagine we have -``` - scan.loops(1).setchan = {'V1','V2'}; - scan.loops(1).rng = [-.001 .001]; -``` -> This means that both V1 and V2 will be simultaneously swept from -.001 to .001. However, imagine that we would like to sweep V1 from -.001 to .001, but we want V2 to be swept from .001 to -.001. The trafofn is a handy way to do this. If we set scan.loops(l).rng=[-.001 .001], which is the range we want for V1, then we want -``` -scan.loops(l).trafofn(1).fn = @(x,y) x(1); -``` -> which is the identity function. This is the trivial trafofn. A blank trafofn defaults to the identity. However, we want to transform the values of V2, which is scan.loops(l).setchan{2}. Therefore we set -``` -scan.loops(l).trafofn{2}.fn = @(x,y)-1*x(1); -scan.loops(l).trafofn{2}.args = {}; -``` -which will invert the range for the channel V2. -We can imagine a more complicated trafofn such as -``` -scan.loops(l).trafofn{2}.fn = @(x,y,p)-p(1)*x(1)+p(2); -scan.loops(l).trafofn{2}.args = {[4,23]}; -``` -which would pass the argument [4,23] to the trafofn to be used in place of p. - -**NB**: It is possible to use a variable in the workspace as part of a trafofn. -``` -scan.loops(l).trafofn{2}.fn = @(x,y,p)slope*x(1)+offset; -scan.loops(l).trafofn{2}.args = {}; -``` -assuming "slope" and "offset" exist. However, when trying to retrieve the scan, the values of slope and offset will not be easily accessed. It is often easier to store these in the trafofn.args field. - -## procfn ## -See [Procfn](Procfn.md) for details on how to use procfns. -This is an optional field. If populated the procfn is capable of processing or analyzing data during the scan. This is useful if, for example, the scan produces a lot of data but only certain quantities such as means or histograms are desired. - -## datafn ## -Like procfn, scan.loops(l).datafn is able to do simple processing on the data. Unlike the procfn, a datafn is only passed the data from the current loop iteration. This limits the datafn somewhat in functionality but makes it significantly faster. - - -# saveloop # -It is often useful to tell smrun when to save the data coming out of the scan to disk. For example, saving every iteration of every loop is very slow, but only saving the data one time at the end of the scan is not optimal since a crash would cause data loss. You can specify when do save data using scan.saveloop. saveloop is a numeric array; [_loop_, _interation_]. _iteration_ defaults to 1 if not specified. _loop_ defaults to 2 if not specified. -Data will get saved to disk every _iteration_'th iteration of the loop _loop_, where 1 is the fastest loop. For example: - -``` -scan.saveloop=[1 1]; % Save to disk with every data point. Slow. -scan.saveloop=[1 5]; % Save to disk with every 5th data point. -scan.saveloop=[3]; % Save every time the third loop is incremented. -``` - -# disp # -What data is displayed is defined in the disp field of the scan. scan.disp is a struct array with the fields listed below. Each element of scan.disp describes one subplot to be displayed in the data window (Figure 1000). If nothing is specified in scan.disp, then figure 1000 will be blank. - -fields of _disp_: - * _loop_: loop during which to update display - * _dim_: Dimension of data to be displayed, or 2 for plot or false-color image. - * _channel_: Data channel to be shown. This is an index to all channels stored (i.e. those listed in loops(l).getchan for any loop l), starting with the slowest loop(?). If all channels are read in the same loop l, channel is simply the index of loops(l).getchan; -For example, imagine we have a scan with two loops. Imagine that the inner loop (loop(1)) has two getchangs, out1 and out2. If we want to have a 1-D plot of out1 that updates every time second loop begins and a 2-D color plot of out2 that updates every time the second loops begins we would have -``` -scan.disp(1).loop = 2; -scan.disp(1).dim = 1; -scan.disp(1).channel = 1; - -scan.disp(2).loop = 2; -scan.disp(2).dim = 2; -scan.disp(2).channel = 1; -``` - -# consts # -It is often handy to have certain channels set to certain values at the beginning of a scan, for example, the sampling rate of a digitizing card. This is handled by scan.consts. scan.consts is a struct array with fields setchan and val. For each entry, i, of scan.consts, scan.consts(i).setchan is set to scan.consts(i).val before the scan executes. The setchans must be strings of channel names and the consts are numerical values. -**example** -imagine we want to set the sampling rate of a digitizing card to 1e5 and the pulseline of an AWG to 1 before a scan starts. We would use -``` -scan.consts(1).setchan = 'samprate'; -scan.consts(1).val = 100000; -scan.consts(2).setchan = 'Pulseline'; -scan.consts(2).val = 1; -``` - -# Configfn # -Just as it is handy to set certain variables to certain values before a scan, it is also handy to be able to execute certain function to configure a scan (i.e. arm a digitizing card). This is done with scan.configfn. The configfn is a struct array with two fields: configfn.fn, which is the function call, and configfn.args, which are the arguments past to the configfn. -**example** -if we want to use buffered acquisition on a scan, we need to configure the scan to do so. We use -``` -scan.confifn.fn = @smabufconfig2 -scan.configfn.args = {'arm',[1]} -``` -which will call smabufconfig2('arm',[1](1.md)) - -# Cleanupfn # -The scan.cleanupfn is similar to scan.configfn, except it is executed after the scan completes. Like the configfn, it is a struct array with the fields cleanupfn.fn and cleanupfn.args. -**example** -If we want to set the magnetic field back to zero at the end of a scan we might have -``` -scan.cleanupfn.fn = @smset -scan.cleanupfn.args = {'B',[0]}; -``` -which will call smset('B',0) when the scan completes. - -# A note on specifying user functions in scan # -Functions lists to be exectuted at various points -(prefn, postfn, datafn, procfn, trigfn) can be specified as -cell arrays of function handles or struct arrays with fields fn -(function handle) and args (cell array with user arguments to be passed). Any function handle can be repaced by a string, which will be interpreted by MATLAB's `str2func`. - -For more details, see the auxiliary function fncall at the end of `smrun.m`. - - -# Data # +# Introduction # +A scan is a struct with all the information to acquire data. It is executed by smrun. There are many fields in this struct (some of which may be left blank), and understanding each one will help you understand how smrun works. + +Here is what matlab outputs when you type smscan: +``` + loops: [1x2 struct] + saveloop: 2 + configfn: [1x1 struct] + disp: [1x2 struct] + cleanupfn: [] + consts: [1x2 struct] +``` + +Here we will go through all of these fields and some additional ones too. + +# Loops # +scan.loops is the meat of the scan. The loops contain all of the informations about which channels should be swept or ramped, which channels should be recorded, etc. The size of scan.loops dictates the dimension of the scan to be performed: a 1-D (line scan) will have one loop, a 2-D scan will have two loops, etc. In general, each iteration of a loop might sweep a channel and get another channel. scan.loop(1) is the inner-most loop (executed most often) and scan.loops(end) is the outter-most loop (executed least often). Let's take a look at what is inside each loop. + +## setchan ## +These are the channels to be swept in this loop. The setchan can either be a string (one channel) or a cell array of strings if more than one channel is to be swept. Alternatively, setchans can also be numbers, which are indexes into smdata.channels. + +## rng ## +The range over which the setchan should be swept. In each iteration of the loop the setchan starts at rng(1) and ends at rng(2). Alteratively, rng may be a vector of values to which the setchans are set. For example, scan.loops(l).rng = linspace(0,1,11). + +## npoints ## +The number of points in the ramp. Over the course of the loop the setchan will be set to linspace(rng(1),rng(2),npoints). If length(rng) is great than 2, this field is ignored. + +## getchan ## +This is the channel whose value is recorded at every point during the loop. Like the setchan, the getchan can be a string or a cell array of strings. The getchan can also be empty, if, for example, the instrument in question can store many values and return them all at once (buffered acquisition). In this case, the inner loop of a scan would have an empty getchan, and the outter loop would have a getchan that would return its values for an entire iteration of the inner loop. + +## ramptime ## +The time (in seconds) to spend per point of each loop. If a loop has npoints=100 and a ramptime = .01 then one iteration of this loop will take one second. A negative ramptime is used to note that an instrument is capable of generating a ramp by itself (i.e. spacial measure does not need to set the setchans to each point). An empty ramptime (often used in outter loops of scans) signifies that the setchan is simply set (at a rate given by smdata.channels(ch).rangeramp(3)) to the appropriate value and held there. + +## trigfn ## +This field, which may be left blank, is a function that triggers this loop to run. For example, this might be a function call to a timing generator that fires a TTL signal. +**example** +if we want to do an automatic ramp of a voltage channel on a decaDAC it needs to be triggered. This can be done with an AWG using +``` +scan.loops(1).trigfn.fn = @smatrigawg; +scan.loops(1).trigfn.args = {[16]} +``` +which will call smatrigawg([16](16.md)) to trigger each iteration of the first loop. Here we use 16 because smdata.inst(16) is the AWG that will generate the trigger. + +## trafofn ## +This is short hand for transformationfunction. The first argument (named x below, not be be confused with trafofn.args) to the trafofn is a vector of the loops variables, starting with the inner-most loop. The second argument (named y below) of the trafofn is the current value of all the channels, as store in smdata.chanvals. +scan.loops(l).trafofn(k) will transform the range over which scan.loops(l).setchan{k} is swept. Ordinarily, a setchan is swept from rng(1) to rng(end) in npoints. However, it is often necessary to transform this sweep range into another one. For example, imagine we have +``` + scan.loops(1).setchan = {'V1','V2'}; + scan.loops(1).rng = [-.001 .001]; +``` +> This means that both V1 and V2 will be simultaneously swept from -.001 to .001. However, imagine that we would like to sweep V1 from -.001 to .001, but we want V2 to be swept from .001 to -.001. The trafofn is a handy way to do this. If we set scan.loops(l).rng=[-.001 .001], which is the range we want for V1, then we want +``` +scan.loops(l).trafofn(1).fn = @(x,y) x(1); +``` +> which is the identity function. This is the trivial trafofn. A blank trafofn defaults to the identity. However, we want to transform the values of V2, which is scan.loops(l).setchan{2}. Therefore we set +``` +scan.loops(l).trafofn{2}.fn = @(x,y)-1*x(1); +scan.loops(l).trafofn{2}.args = {}; +``` +which will invert the range for the channel V2. +We can imagine a more complicated trafofn such as +``` +scan.loops(l).trafofn{2}.fn = @(x,y,p)-p(1)*x(1)+p(2); +scan.loops(l).trafofn{2}.args = {[4,23]}; +``` +which would pass the argument [4,23] to the trafofn to be used in place of p. + +**NB**: It is possible to use a variable in the workspace as part of a trafofn. +``` +scan.loops(l).trafofn{2}.fn = @(x,y,p)slope*x(1)+offset; +scan.loops(l).trafofn{2}.args = {}; +``` +assuming "slope" and "offset" exist. However, when trying to retrieve the scan, the values of slope and offset will not be easily accessed. It is often easier to store these in the trafofn.args field. + +## procfn ## +See [Procfn](Procfn.md) for details on how to use procfns. +This is an optional field. If populated the procfn is capable of processing or analyzing data during the scan. This is useful if, for example, the scan produces a lot of data but only certain quantities such as means or histograms are desired. + +## datafn ## +Like procfn, scan.loops(l).datafn is able to do simple processing on the data. Unlike the procfn, a datafn is only passed the data from the current loop iteration. This limits the datafn somewhat in functionality but makes it significantly faster. + + +# saveloop # +It is often useful to tell smrun when to save the data coming out of the scan to disk. For example, saving every iteration of every loop is very slow, but only saving the data one time at the end of the scan is not optimal since a crash would cause data loss. You can specify when do save data using scan.saveloop. saveloop is a numeric array; [_loop_, _interation_]. _iteration_ defaults to 1 if not specified. _loop_ defaults to 2 if not specified. +Data will get saved to disk every _iteration_'th iteration of the loop _loop_, where 1 is the fastest loop. For example: + +``` +scan.saveloop=[1 1]; % Save to disk with every data point. Slow. +scan.saveloop=[1 5]; % Save to disk with every 5th data point. +scan.saveloop=[3]; % Save every time the third loop is incremented. +``` + +# disp # +What data is displayed is defined in the disp field of the scan. scan.disp is a struct array with the fields listed below. Each element of scan.disp describes one subplot to be displayed in the data window (Figure 1000). If nothing is specified in scan.disp, then figure 1000 will be blank. + +fields of _disp_: + * _loop_: loop during which to update display + * _dim_: Dimension of data to be displayed, or 2 for plot or false-color image. + * _channel_: Data channel to be shown. This is an index to all channels stored (i.e. those listed in loops(l).getchan for any loop l), starting with the slowest loop(?). If all channels are read in the same loop l, channel is simply the index of loops(l).getchan; +For example, imagine we have a scan with two loops. Imagine that the inner loop (loop(1)) has two getchangs, out1 and out2. If we want to have a 1-D plot of out1 that updates every time second loop begins and a 2-D color plot of out2 that updates every time the second loops begins we would have +``` +scan.disp(1).loop = 2; +scan.disp(1).dim = 1; +scan.disp(1).channel = 1; + +scan.disp(2).loop = 2; +scan.disp(2).dim = 2; +scan.disp(2).channel = 1; +``` + +# consts # +It is often handy to have certain channels set to certain values at the beginning of a scan, for example, the sampling rate of a digitizing card. This is handled by scan.consts. scan.consts is a struct array with fields setchan and val. For each entry, i, of scan.consts, scan.consts(i).setchan is set to scan.consts(i).val before the scan executes. The setchans must be strings of channel names and the consts are numerical values. +**example** +imagine we want to set the sampling rate of a digitizing card to 1e5 and the pulseline of an AWG to 1 before a scan starts. We would use +``` +scan.consts(1).setchan = 'samprate'; +scan.consts(1).val = 100000; +scan.consts(2).setchan = 'Pulseline'; +scan.consts(2).val = 1; +``` + +# Configfn # +Just as it is handy to set certain variables to certain values before a scan, it is also handy to be able to execute certain function to configure a scan (i.e. arm a digitizing card). This is done with scan.configfn. The configfn is a struct array with two fields: configfn.fn, which is the function call, and configfn.args, which are the arguments past to the configfn. +**example** +if we want to use buffered acquisition on a scan, we need to configure the scan to do so. We use +``` +scan.confifn.fn = @smabufconfig2 +scan.configfn.args = {'arm',[1]} +``` +which will call smabufconfig2('arm',[1](1.md)) + +# Cleanupfn # +The scan.cleanupfn is similar to scan.configfn, except it is executed after the scan completes. Like the configfn, it is a struct array with the fields cleanupfn.fn and cleanupfn.args. +**example** +If we want to set the magnetic field back to zero at the end of a scan we might have +``` +scan.cleanupfn.fn = @smset +scan.cleanupfn.args = {'B',[0]}; +``` +which will call smset('B',0) when the scan completes. + +# A note on specifying user functions in scan # +Functions lists to be exectuted at various points +(prefn, postfn, datafn, procfn, trigfn) can be specified as +cell arrays of function handles or struct arrays with fields fn +(function handle) and args (cell array with user arguments to be passed). Any function handle can be repaced by a string, which will be interpreted by MATLAB's `str2func`. + +For more details, see the auxiliary function fncall at the end of `smrun.m`. + + +# Data # scan.data is another optional field. Here you can store essentially anything that matlab knows how to handle: doubles, structs, strings, etc. \ No newline at end of file diff --git a/doc/SpecialMeasure.md b/doc/SpecialMeasure.md index 54c8227024079c8a5bf3e6247b9260cbd3ae07a7..7c8437e8059465d1220d02ac1532f97dca6afd7e 100644 --- a/doc/SpecialMeasure.md +++ b/doc/SpecialMeasure.md @@ -1,106 +1,106 @@ -# Introduction # - -Special Measure provides a simple frontend for MATLAB's instrument control toolbox, allowing users to quickly set up flexible scans through parameter space. - -# Installation # -Please see [Installation](Installation.md) for install instructions. - -# Quick Reference # - -Please see the [Overview](Overview.md) page for a list of Special Measure functions, -and [Error Messages](ErrorMessages.md) for a list of common error messages and what to do. - -# Configuration Data # - * [scan](Scans_new.md) (structure) - * [smdata](smdata_new.md) (global structure) - - -# Structure of Special Measure # - -### Instruments and channels ### - -Each hardware device is represented by an instrument (not to be confused with -MATLAB instrument objects) that contains information about how to control it -and what channels (see below) it provides. This information roughly corresponds -to the hardcoded instrument drivers and channel array in Labview SM. - - -The channel concept is very similar to that of Labview SM - each channel -represents some parameter, input or output value of an instrument. -In most cases, it will be some physical quantity. -There is currently no distinction between write and read channels. -All channels should support a read operation, but it is -up to the user to make sure that channels that do not support write operations -(typically acqusition devices) are not used as set channels. -Writeable channels should always accept and return a single double, but -read-only channels can also return matrices of arbitrary dimension - e.g. -a vector representing a complete scan line. -Writeable channels can be self ramping, in which case its variable can be -ramped by the corresponding instrument. If available, this feature is always -used to set channel values (function smset), and can also be used for -measurements. - -Information about instruments, channels (i.e. the rack) and other -configuration is stored in the global struct smdata. Channels and -instruments are stored in the struct array smdata.channels and smdata.inst. -Major changes to smdata.inst are only required when adding new instruments -or updating drivers, but it may occasionally be necessary to change certain -instrument parameters, such as the data dimension for read channels. - - - -### Specifying instruments and channels ### - ---- - -Internally, channels and instruments are identified by their indices -to the struct arrays smdata.inst and smdata.channels. These indices -(printed at the beginning of each line by smprintchannels and -smprintinst can also be used to specify channels and instruments in -function arguments, including scan definition. Alternatively, channel -and instruments names can be used. Lists of names can be given as a -char arrays or cell vectors of strings. The conversion from names to -indices is typically done with smchanlookup and sminstlookup. -Channel names should always be unique. Instruments can be called by their -instrument type identifier (smdata.inst().device, e.g. SR830) if there is only -one such instrument in the rack, or an optional name, which should be unique -amongst instrument types and names. Instruments with a name should generally -be called by that name. - -### Adding and removing channels ### - ---- - -To add a channel, use the [smaddchannel](smaddchannel.md) function. Note that depending -on the instrument, further configuration may be necessary. -(Particularly for channels to be ramped for data taking, or matrix-valued -channels). - -To remove one or several channels ch, just type "[smdata](smdata#channels.md).channels(ch) = `[]`;" -Note that this will change the indices of all subsequent channels. - - -### Displaying configuration ### - ---- - -Use the smprint**function to display the most important configuration -information.** - - -### Displaying the current channel values ### - ---- - -The current values of all scalar channels can be displayed in figure 1001 -if this figure is initialized by calling "sminitdisp". The displayed values -will be updated by every call of smget and smset for each channel. -To disable this feature, close figure 1001. - - -### Specifying a scan ### - ---- - -The measurement task to be excecuted by [smrun](smrun.md) is defined by a [scan](Scans_new.md) struct passed to [smrun](smrun.md). For explanations of its fields, see [scan](Scans_new.md). +# Introduction # + +Special Measure provides a simple frontend for MATLAB's instrument control toolbox, allowing users to quickly set up flexible scans through parameter space. + +# Installation # +Please see [Installation](Installation.md) for install instructions. + +# Quick Reference # + +Please see the [Overview](Overview.md) page for a list of Special Measure functions, +and [Error Messages](ErrorMessages.md) for a list of common error messages and what to do. + +# Configuration Data # + * [scan](Scans_new.md) (structure) + * [smdata](smdata_new.md) (global structure) + + +# Structure of Special Measure # + +### Instruments and channels ### + +Each hardware device is represented by an instrument (not to be confused with +MATLAB instrument objects) that contains information about how to control it +and what channels (see below) it provides. This information roughly corresponds +to the hardcoded instrument drivers and channel array in Labview SM. + + +The channel concept is very similar to that of Labview SM - each channel +represents some parameter, input or output value of an instrument. +In most cases, it will be some physical quantity. +There is currently no distinction between write and read channels. +All channels should support a read operation, but it is +up to the user to make sure that channels that do not support write operations +(typically acqusition devices) are not used as set channels. +Writeable channels should always accept and return a single double, but +read-only channels can also return matrices of arbitrary dimension - e.g. +a vector representing a complete scan line. +Writeable channels can be self ramping, in which case its variable can be +ramped by the corresponding instrument. If available, this feature is always +used to set channel values (function smset), and can also be used for +measurements. + +Information about instruments, channels (i.e. the rack) and other +configuration is stored in the global struct smdata. Channels and +instruments are stored in the struct array smdata.channels and smdata.inst. +Major changes to smdata.inst are only required when adding new instruments +or updating drivers, but it may occasionally be necessary to change certain +instrument parameters, such as the data dimension for read channels. + + + +### Specifying instruments and channels ### + +--- + +Internally, channels and instruments are identified by their indices +to the struct arrays smdata.inst and smdata.channels. These indices +(printed at the beginning of each line by smprintchannels and +smprintinst can also be used to specify channels and instruments in +function arguments, including scan definition. Alternatively, channel +and instruments names can be used. Lists of names can be given as a +char arrays or cell vectors of strings. The conversion from names to +indices is typically done with smchanlookup and sminstlookup. +Channel names should always be unique. Instruments can be called by their +instrument type identifier (smdata.inst().device, e.g. SR830) if there is only +one such instrument in the rack, or an optional name, which should be unique +amongst instrument types and names. Instruments with a name should generally +be called by that name. + +### Adding and removing channels ### + +--- + +To add a channel, use the [smaddchannel](smaddchannel.md) function. Note that depending +on the instrument, further configuration may be necessary. +(Particularly for channels to be ramped for data taking, or matrix-valued +channels). + +To remove one or several channels ch, just type "[smdata](smdata#channels.md).channels(ch) = `[]`;" +Note that this will change the indices of all subsequent channels. + + +### Displaying configuration ### + +--- + +Use the smprint**function to display the most important configuration +information.** + + +### Displaying the current channel values ### + +--- + +The current values of all scalar channels can be displayed in figure 1001 +if this figure is initialized by calling "sminitdisp". The displayed values +will be updated by every call of smget and smset for each channel. +To disable this feature, close figure 1001. + + +### Specifying a scan ### + +--- + +The measurement task to be excecuted by [smrun](smrun.md) is defined by a [scan](Scans_new.md) struct passed to [smrun](smrun.md). For explanations of its fields, see [scan](Scans_new.md). Note that some of the parameters are optional. \ No newline at end of file diff --git a/doc/Standardized_Operation_Numbers.md b/doc/Standardized_Operation_Numbers.md index 711d587a47cd541915ba8df581b9585c9c8dddce..8202ccc8d6bb340d7c0071b56f6512e1ce1355ec 100644 --- a/doc/Standardized_Operation_Numbers.md +++ b/doc/Standardized_Operation_Numbers.md @@ -1,15 +1,15 @@ -Standard operations used by special measure (particularly control functions) and the numbers that correspond to them. - -# Introduction # - -Special measure used a syntax for ico = [istrument, channel, operation] in control functions and other places. Here is a list of what the third element (operation) can be. These might be instrument specific, i.e. they can sometimes change from instrument to instrument. 0 and 1 are very standard. - -0: read - -1: set - -2: - -3: trigger - +Standard operations used by special measure (particularly control functions) and the numbers that correspond to them. + +# Introduction # + +Special measure used a syntax for ico = [istrument, channel, operation] in control functions and other places. Here is a list of what the third element (operation) can be. These might be instrument specific, i.e. they can sometimes change from instrument to instrument. 0 and 1 are very standard. + +0: read + +1: set + +2: + +3: trigger + 4: arm \ No newline at end of file diff --git a/doc/WritingDrivers.md b/doc/WritingDrivers.md index 10ce929227420416a9862fda4717007ba6b90559..15396a1683079618a3eb7fb8550851dd2d7cbbe7 100644 --- a/doc/WritingDrivers.md +++ b/doc/WritingDrivers.md @@ -1,48 +1,48 @@ -# Writing Instrument Drivers # - -Adding new instruments consists of two parts: writing a [control function](#Control_Function.md) and specifying the instrument information in [\*smdata.inst\*](#smdata.inst.md), a struct array with the following fields: - -### smdata.inst ### - -| cntrlfn | Function handle of the control function | -|:---------|:----------------------------------------| -| data | instrument specific data. An open MATLAB instrument object representing the instrument should be stored in data.inst, if a applicable. | -| datadim | array with non-singleton data dimensions for each channel (no entry needed for singleton dimensions) | -| type | channel type, one element for each channel. Set to 1 if a channel uses programmed ramps. | -| channels | channel names (char array) | -| device | string with instrument indentifier. | -| name | optional name to distinguish different instruments of the same type. | - ---- -### Control functions ### - -All communications with an instrument occurs through calls of -`smdata.inst().cntrlfn`, which has the following calling convention: - -_val_ = **cntrlfn**(`[`_inst_, _channel_, _operation_`]`, _val_, _rate_) - -inst and channel are the instrument and channel indices. Operation -determines what the function should do. - - 1. read channel value. No further argument given. The return value can be matrix with the dimensions given in `smdata.inst(inst).datadim(channel, :)`. - 1. set channel value to val. Rate argument will be given for channels with ramp functionality. The return value val should be the expected time required to complete the ramp to the set point. - 1. query remaining ramp time. Ramp rate used to program the last ramp is given in rate. This functionality is not used by smset (or anywhere else) at the time of writing. - 1. trigger previously programmed ramp. - 1. Arm acquisition device (optional) - 1. Configure acquisition device (optional) See smcATS660v2.m for examples on usage of 4 and 5. - -If rate `<` 0 for ramped channels, a ramp is used in a measurement. In this case, the ramp should only be programmed and started later by a separate trigger function (see "Ramping channels"). - -How instruments are stored and addressed by the control function is -in principle arbitrary. However, I would recommend to follow the -convention that GPIB, serial, VISA, and similar instruments (i.e. those -controlled via the instrument control toolbox) be represented -by an instrument object stored in in smdata.inst().data.inst, which is -always kept open. smopen, smclose, smprintf, smscanf and smquery only -work for instruments following this convention. - -For simple examples that can be adapted see for example smcHP1000A.m -or smctemplate.m, which is intended to be a starting point for writing new drivers. - -### See Also ### +# Writing Instrument Drivers # + +Adding new instruments consists of two parts: writing a [control function](#Control_Function.md) and specifying the instrument information in [\*smdata.inst\*](#smdata.inst.md), a struct array with the following fields: + +### smdata.inst ### + +| cntrlfn | Function handle of the control function | +|:---------|:----------------------------------------| +| data | instrument specific data. An open MATLAB instrument object representing the instrument should be stored in data.inst, if a applicable. | +| datadim | array with non-singleton data dimensions for each channel (no entry needed for singleton dimensions) | +| type | channel type, one element for each channel. Set to 1 if a channel uses programmed ramps. | +| channels | channel names (char array) | +| device | string with instrument indentifier. | +| name | optional name to distinguish different instruments of the same type. | + +--- +### Control functions ### + +All communications with an instrument occurs through calls of +`smdata.inst().cntrlfn`, which has the following calling convention: + +_val_ = **cntrlfn**(`[`_inst_, _channel_, _operation_`]`, _val_, _rate_) + +inst and channel are the instrument and channel indices. Operation +determines what the function should do. + + 1. read channel value. No further argument given. The return value can be matrix with the dimensions given in `smdata.inst(inst).datadim(channel, :)`. + 1. set channel value to val. Rate argument will be given for channels with ramp functionality. The return value val should be the expected time required to complete the ramp to the set point. + 1. query remaining ramp time. Ramp rate used to program the last ramp is given in rate. This functionality is not used by smset (or anywhere else) at the time of writing. + 1. trigger previously programmed ramp. + 1. Arm acquisition device (optional) + 1. Configure acquisition device (optional) See smcATS660v2.m for examples on usage of 4 and 5. + +If rate `<` 0 for ramped channels, a ramp is used in a measurement. In this case, the ramp should only be programmed and started later by a separate trigger function (see "Ramping channels"). + +How instruments are stored and addressed by the control function is +in principle arbitrary. However, I would recommend to follow the +convention that GPIB, serial, VISA, and similar instruments (i.e. those +controlled via the instrument control toolbox) be represented +by an instrument object stored in in smdata.inst().data.inst, which is +always kept open. smopen, smclose, smprintf, smscanf and smquery only +work for instruments following this convention. + +For simple examples that can be adapted see for example smcHP1000A.m +or smctemplate.m, which is intended to be a starting point for writing new drivers. + +### See Also ### * [smdata\_new](smdata_new.md) \ No newline at end of file diff --git a/doc/scan.md b/doc/scan.md index f4d9dd55e26700f5b813cce9700a3175a1e5b20c..41ba2005ff54df00626dba537181631b68d42471 100644 --- a/doc/scan.md +++ b/doc/scan.md @@ -1,78 +1,78 @@ -# Overview # -See the help for smrun `help smrun` or scan\_new for worthwhile documentation. - -### Confguring the display ### -What data is displayed is defined in the disp field of the scan definition -struct. disp is a struct array with the fields listed below. Each element -of disp describes one subplot to be displayed in the data window (Figure 1000). - -fields of _disp_: - * _loop_: loop furing which to update display - * _dim_: Dimension of data to be displayed, or 2 for plot or false-color image. - * _channel_: Data channel to be shown. This is an index to all channels stored (i.e. those listed in loops(l).getchan for any loop l), starting with the slowest loop(?). If all channels are read in the same loop l, channel is simply the index of loops(l).getchan; - -### Configuring Saving to Disk ### -How frequently data is saved to disk is controlled by scan.saveloop -saveloop is a numeric array; [_loop_, _interation_]. _iteration_ defaults to 1 if not specified. _loop_ defaults to 2 if not specified. -Data will get saved to disk every _iteration_'th iteration of the loop _loop_, where 1 is the fastest loop. For example: - -``` -scan.saveloop=[1 1]; % Save to disk with every data point. Slow. -scan.saveloop=[1 5]; % Save to disk with every 5th data point. -scan.saveloop=[3]; % Save every time the third loop is incremented. -``` - -### Ramping channels ### -A writeable channel ch on instrument inst with -smdata.inst(inst).type(ch) set to 1 is considered as a ramping -channel, i.e. smset assumes that the device can autonomously generate -ramps. This feature is always used to change the value of the channel. -The maximum and default ramp rate is stored in smdata. - -Ramps are also be used for measurements if scan.loops(i).ramptime < 0 -In this latter case, smrun (the main measurement routine) only sets -the channel to the initial value and programs the endpoint of a ramp -and the ramp rate and then (optionally) -calls a trigger function to initiate a ramp. - -### Specifying user functions in scan ### -Functions lists to be exectuted at various points -(prefn, postfn, datafn, procfn, trigfn) can be specified as -cell arrays of function handles or struct arrays with fields fn -(function handle) and args (cell array with user arguments to be passed). Any function handle can be repaced by a string, which will be interpreted by MATLAB's `str2func`. - -For more details, see the auxiliary function fncall at the end of `smrun.m`. - - -### Transformation functions ### - -Channel transformation functions compute the channel value to be set -from the independent variables and other channel values. -Their first argument is a vector with the loop variables, -starting with the innermost loop. -the second one the current value of all channels, as stored in -smdata.chanvals. Those values are only updated by calls to -smset or smget. Channels returning arrays are not stored there. - -Transformation fucntions (trafofn's) can be specified as a cell array of functions, or as a struct array with fields .fn and .args as described above. - -**Example:** -``` -scan.loops(1).trafofn{2} = @(x,y) (x(1)-2) * .2 + y(3); -``` -or -``` -scan.loops(2).trafofn(1).fn = @(x,y,p) (x(1)-2) * .2 + p; -scan.loops(2).trafofn(1).args = {5} -``` - - -The global transformation functions are applied to the independent variables -before the channel specific transformations. Currently, their only argument -is the loop variable vector. - - -### prefn ### -> prefunction get (fn.args, loop vars) as aruments. INSERT EXAMPLE -### Known Bugs ### +# Overview # +See the help for smrun `help smrun` or scan\_new for worthwhile documentation. + +### Confguring the display ### +What data is displayed is defined in the disp field of the scan definition +struct. disp is a struct array with the fields listed below. Each element +of disp describes one subplot to be displayed in the data window (Figure 1000). + +fields of _disp_: + * _loop_: loop furing which to update display + * _dim_: Dimension of data to be displayed, or 2 for plot or false-color image. + * _channel_: Data channel to be shown. This is an index to all channels stored (i.e. those listed in loops(l).getchan for any loop l), starting with the slowest loop(?). If all channels are read in the same loop l, channel is simply the index of loops(l).getchan; + +### Configuring Saving to Disk ### +How frequently data is saved to disk is controlled by scan.saveloop +saveloop is a numeric array; [_loop_, _interation_]. _iteration_ defaults to 1 if not specified. _loop_ defaults to 2 if not specified. +Data will get saved to disk every _iteration_'th iteration of the loop _loop_, where 1 is the fastest loop. For example: + +``` +scan.saveloop=[1 1]; % Save to disk with every data point. Slow. +scan.saveloop=[1 5]; % Save to disk with every 5th data point. +scan.saveloop=[3]; % Save every time the third loop is incremented. +``` + +### Ramping channels ### +A writeable channel ch on instrument inst with +smdata.inst(inst).type(ch) set to 1 is considered as a ramping +channel, i.e. smset assumes that the device can autonomously generate +ramps. This feature is always used to change the value of the channel. +The maximum and default ramp rate is stored in smdata. + +Ramps are also be used for measurements if scan.loops(i).ramptime < 0 +In this latter case, smrun (the main measurement routine) only sets +the channel to the initial value and programs the endpoint of a ramp +and the ramp rate and then (optionally) +calls a trigger function to initiate a ramp. + +### Specifying user functions in scan ### +Functions lists to be exectuted at various points +(prefn, postfn, datafn, procfn, trigfn) can be specified as +cell arrays of function handles or struct arrays with fields fn +(function handle) and args (cell array with user arguments to be passed). Any function handle can be repaced by a string, which will be interpreted by MATLAB's `str2func`. + +For more details, see the auxiliary function fncall at the end of `smrun.m`. + + +### Transformation functions ### + +Channel transformation functions compute the channel value to be set +from the independent variables and other channel values. +Their first argument is a vector with the loop variables, +starting with the innermost loop. +the second one the current value of all channels, as stored in +smdata.chanvals. Those values are only updated by calls to +smset or smget. Channels returning arrays are not stored there. + +Transformation fucntions (trafofn's) can be specified as a cell array of functions, or as a struct array with fields .fn and .args as described above. + +**Example:** +``` +scan.loops(1).trafofn{2} = @(x,y) (x(1)-2) * .2 + y(3); +``` +or +``` +scan.loops(2).trafofn(1).fn = @(x,y,p) (x(1)-2) * .2 + p; +scan.loops(2).trafofn(1).args = {5} +``` + + +The global transformation functions are applied to the independent variables +before the channel specific transformations. Currently, their only argument +is the loop variable vector. + + +### prefn ### +> prefunction get (fn.args, loop vars) as aruments. INSERT EXAMPLE +### Known Bugs ### This page is worthless. \ No newline at end of file diff --git a/doc/smclose.md b/doc/smclose.md index 17ac9ce21dbee5b86c65471c4726bed0bc7b167d..17fd8716cf5216bc0534530f0f2f2a86a15a0366 100644 --- a/doc/smclose.md +++ b/doc/smclose.md @@ -1,19 +1,19 @@ -**smclose**(_`[`inst`]`)_ - -This closes a connection to a MATLAB instrument. **It is not in general necessary to ever call this function unless an instrument crashes or reboots**, in which case it can be useful to _[smclose](smclose.md)_ and then _[smopen](smopen.md)_ it. An example might be a VISA-USB instrument that was disconnected and reconnected, or a DecaDAC that has become desynchronized on communications. _inst_ can be: - - * Empty, in which case all instruments in ` smdata.inst ` will be opened. - * A vector of numbers, in which case instruments with those numbers will be opened. See _[smprintinst](smprintinst.md)_. - * A string, in which case the instrument with that name is opened. - -### Example ### -``` -smclose(2); smopen(2); % Close and re-open an instrument that crashed. -``` - - -### See Also ### - * _[smopen](smopen.md)_ - * _[smprintinst](smprintinst.md)_ - * The MATLAB manual on VISA/GPIB objects. +**smclose**(_`[`inst`]`)_ + +This closes a connection to a MATLAB instrument. **It is not in general necessary to ever call this function unless an instrument crashes or reboots**, in which case it can be useful to _[smclose](smclose.md)_ and then _[smopen](smopen.md)_ it. An example might be a VISA-USB instrument that was disconnected and reconnected, or a DecaDAC that has become desynchronized on communications. _inst_ can be: + + * Empty, in which case all instruments in ` smdata.inst ` will be opened. + * A vector of numbers, in which case instruments with those numbers will be opened. See _[smprintinst](smprintinst.md)_. + * A string, in which case the instrument with that name is opened. + +### Example ### +``` +smclose(2); smopen(2); % Close and re-open an instrument that crashed. +``` + + +### See Also ### + * _[smopen](smopen.md)_ + * _[smprintinst](smprintinst.md)_ + * The MATLAB manual on VISA/GPIB objects. * **[smdata](smdata.md)** \ No newline at end of file diff --git a/doc/smdata.md b/doc/smdata.md index c3f6f6dc9394841e74d9b44ad13102383c9265e2..e733933a5b597035c1cccfbf616c7703de8e9af0 100644 --- a/doc/smdata.md +++ b/doc/smdata.md @@ -1,37 +1,37 @@ -# smdata # -Structure elements - * **[inst](#smdata.inst.md)** A list of the defined instruments - * **[channels](#smdata.channels.md)** A list of the defined channels. - -| configch | blah. | -|:----------|:------| -| configfn | | -| chandisph | | -| chanvals | | - - -### smdata.inst ### - * data - * datadim - * ctrlfn - * type - * device - * name - * channels - -### smdata.channels ### -> instchan [instrument index, channel index w.r.t. instrument's -> > channels] - -> rangeramp: First two elements are lower and upper limit. -> > Third element determines ramp rate (in 1/s). -> > 4th element is the conversion factor; requested value -> > > is multiplied by this before sending to the -> > > instrument. -> > > name Channel name (string). - -### See Also ### - * [Special Measure](SpecialMeasure.md) - -### Bugs/Known Issues ### +# smdata # +Structure elements + * **[inst](#smdata.inst.md)** A list of the defined instruments + * **[channels](#smdata.channels.md)** A list of the defined channels. + +| configch | blah. | +|:----------|:------| +| configfn | | +| chandisph | | +| chanvals | | + + +### smdata.inst ### + * data + * datadim + * ctrlfn + * type + * device + * name + * channels + +### smdata.channels ### +> instchan [instrument index, channel index w.r.t. instrument's +> > channels] + +> rangeramp: First two elements are lower and upper limit. +> > Third element determines ramp rate (in 1/s). +> > 4th element is the conversion factor; requested value +> > > is multiplied by this before sending to the +> > > instrument. +> > > name Channel name (string). + +### See Also ### + * [Special Measure](SpecialMeasure.md) + +### Bugs/Known Issues ### This page is incomplete and possibly inaccurate. \ No newline at end of file diff --git a/doc/smdata_new.md b/doc/smdata_new.md index c2cd1fde407ea86981f1369d2e6dba574bcca171..1806ea8544990e82847daee3575577f74291d161 100644 --- a/doc/smdata_new.md +++ b/doc/smdata_new.md @@ -1,107 +1,107 @@ -# smdata # - -Let's look at what is inside smdata -``` -smdata= - inst: [1x23 struct] - channels: [1x67 struct] - chandisph: 1.0012 - chanvals: [1x69 double] - configch: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 37 38 39 56 29 52 53 54 55 30] - configfn: {} -``` - -Lets see what each field is: - -# smdata.inst # -smdata.inst is a struct array of all the instruments that special measure knows how to set, read, and control. It has -``` -smdata.inst = -1x23 struct array with fields: - data - datadim - cntrlfn - type - device - name - channels -``` -Let's discuss these out of order: - -**device**: describes the type of instruments, for example "Yoko7651." - -**name:** the name of the instrument, for example, "YOKO1." It is a user define field to help you keep track of the instrument and is helpful if more than one instrument of the same kind of "device" is present. - -**type:** FIXME. - -**cntrlfn:** Is a handle to the driver (function that controls the instruments) for the instrument. For example @smcYoko. -**channels:** Is a list (char array) of all of the channels that the instrument has. These can include channels that can be set, read, and both. For example "v1", "V2". - -**datadim:** The size of values that may be read (set) from (by) the instrument. This is used if an instrument is capable of returning an array of values (e.g. an entire line scan). There is one datadim entry for each channel in the field smdata.inst(x).channels. An empty datadim implies a scalar value. - -**data:** smdata.inst(x).data is where information about how to control the instrument is stored. For example, this field usually has a single field, smdata.inst(x).data.inst which is a matlab object handle such as GPIB, USB, VISA, etc. - -## smdata.channels ## -smdata.channels has an entry for each channel, which represents some parameter, i.e. an input or and output of an instrument. There is currently no distinction between write and read channels. All channels should support a read operation, but it is up to the user to make sure that channels that do not support write operations (typically acquisition devices) are not used as set channels. - -Let's see what's in smdata.channels: -``` -smdata.channels(3) - -ans = - - 1x67 struct array with fields: - instchan - rangeramp - name -``` - -**name:**: the name of the channel, for example, 'voltage1' which must be a string. - -**instchan:** this field is a 2 x 1 double that indicates which instrument, and channel (as indexed in smdata.inst(instrument).channels a certain channel refers to. For example, -``` -smdata.channles(4).instchan = [3 4] -``` -means that this channel is associated with smdata.inst(3).channels(4). - -**rangeramp:** this field has 4 values: minimum allowed set value, maximum allowed set value, maximum allowed ramp rate, a software multiplier that will be used when setting the channel. For example -``` -instchan: [2 32] -rangeramp: [-0.6000 0 0.0700 11] -name: '4a' -``` -means that the channel named '4a' is associated with instrument 2, channel 32. It can be set from -.6 to 0 and a maximum ramp rate of .07/second. The rangeramep(4) of 11 means that if you issue the command -``` -smset('4a',-.4) -``` -channel 32 of instrument 2 will be set to -4.4. - -## smdata.chandisph ## -is the matlab figure handle for the figure that shows all of the channels and their values. This handle is used to update the figure every time a channels is set or read. - -## smdata.chanvals ## -This double stores the value of every entry in smadata.channels. It gets updated every time smset or smget is called (evey time a channels is set or read). For example, if smdata.channels(4).name = '4a', and smdata.chanvals(4)=.4 means that, if called, -``` -smget('4a') -ans = -0.4 -``` -WARNING: smdata.chanvals should not need to be manually manipulated. Change its entries with extreme caution. - -## smdata.configch ## - -smdata.configch is 1 x n double of all of the channels that will be logged at the beginning of each scan. They are references to smdata.channels. For example, -``` -smdata.configch = [1 4 5 6 7] -``` -means that the values of smdata.channels(1 4 5 6 7) will be logged (POOR NOTATION). - -## smdata.configfn ## - -a function that will be called when smrun is called. This should be a function handle. - - -### See Also ### - * [Special Measure](SpecialMeasure.md) - +# smdata # + +Let's look at what is inside smdata +``` +smdata= + inst: [1x23 struct] + channels: [1x67 struct] + chandisph: 1.0012 + chanvals: [1x69 double] + configch: [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 37 38 39 56 29 52 53 54 55 30] + configfn: {} +``` + +Lets see what each field is: + +# smdata.inst # +smdata.inst is a struct array of all the instruments that special measure knows how to set, read, and control. It has +``` +smdata.inst = +1x23 struct array with fields: + data + datadim + cntrlfn + type + device + name + channels +``` +Let's discuss these out of order: + +**device**: describes the type of instruments, for example "Yoko7651." + +**name:** the name of the instrument, for example, "YOKO1." It is a user define field to help you keep track of the instrument and is helpful if more than one instrument of the same kind of "device" is present. + +**type:** FIXME. + +**cntrlfn:** Is a handle to the driver (function that controls the instruments) for the instrument. For example @smcYoko. +**channels:** Is a list (char array) of all of the channels that the instrument has. These can include channels that can be set, read, and both. For example "v1", "V2". + +**datadim:** The size of values that may be read (set) from (by) the instrument. This is used if an instrument is capable of returning an array of values (e.g. an entire line scan). There is one datadim entry for each channel in the field smdata.inst(x).channels. An empty datadim implies a scalar value. + +**data:** smdata.inst(x).data is where information about how to control the instrument is stored. For example, this field usually has a single field, smdata.inst(x).data.inst which is a matlab object handle such as GPIB, USB, VISA, etc. + +## smdata.channels ## +smdata.channels has an entry for each channel, which represents some parameter, i.e. an input or and output of an instrument. There is currently no distinction between write and read channels. All channels should support a read operation, but it is up to the user to make sure that channels that do not support write operations (typically acquisition devices) are not used as set channels. + +Let's see what's in smdata.channels: +``` +smdata.channels(3) + +ans = + + 1x67 struct array with fields: + instchan + rangeramp + name +``` + +**name:**: the name of the channel, for example, 'voltage1' which must be a string. + +**instchan:** this field is a 2 x 1 double that indicates which instrument, and channel (as indexed in smdata.inst(instrument).channels a certain channel refers to. For example, +``` +smdata.channles(4).instchan = [3 4] +``` +means that this channel is associated with smdata.inst(3).channels(4). + +**rangeramp:** this field has 4 values: minimum allowed set value, maximum allowed set value, maximum allowed ramp rate, a software multiplier that will be used when setting the channel. For example +``` +instchan: [2 32] +rangeramp: [-0.6000 0 0.0700 11] +name: '4a' +``` +means that the channel named '4a' is associated with instrument 2, channel 32. It can be set from -.6 to 0 and a maximum ramp rate of .07/second. The rangeramep(4) of 11 means that if you issue the command +``` +smset('4a',-.4) +``` +channel 32 of instrument 2 will be set to -4.4. + +## smdata.chandisph ## +is the matlab figure handle for the figure that shows all of the channels and their values. This handle is used to update the figure every time a channels is set or read. + +## smdata.chanvals ## +This double stores the value of every entry in smadata.channels. It gets updated every time smset or smget is called (evey time a channels is set or read). For example, if smdata.channels(4).name = '4a', and smdata.chanvals(4)=.4 means that, if called, +``` +smget('4a') +ans = +0.4 +``` +WARNING: smdata.chanvals should not need to be manually manipulated. Change its entries with extreme caution. + +## smdata.configch ## + +smdata.configch is 1 x n double of all of the channels that will be logged at the beginning of each scan. They are references to smdata.channels. For example, +``` +smdata.configch = [1 4 5 6 7] +``` +means that the values of smdata.channels(1 4 5 6 7) will be logged (POOR NOTATION). + +## smdata.configfn ## + +a function that will be called when smrun is called. This should be a function handle. + + +### See Also ### + * [Special Measure](SpecialMeasure.md) + ### Bugs/Known Issues ### \ No newline at end of file diff --git a/doc/smdiagpar.md b/doc/smdiagpar.md index dd6b948fb8396cd0da53063d7bcf9306d9a58af3..27a3d686fbe849547998e55338d72f8370c12312 100644 --- a/doc/smdiagpar.md +++ b/doc/smdiagpar.md @@ -1,12 +1,12 @@ -**smdiagpar**(_scan_,_angle_,_cntr_,_`[`loops`]`_) - -Given a scan _scan_, center it about zero, rotate it by an angle _angle_ in radians, then shift its center by _cntr_. All other global transformations are removed. Loops, if specified, gives loop numbers for the _x_ and _y_ axis of the scan. If not given, the innermost two loops are assumed. - -### Example ### -See known bugs, limitations. - -### Known Bugs/Limitations ### - -In order to rotate a scan, both the _x_ and _y_ channels must be in the setchan for the innermost loop. - +**smdiagpar**(_scan_,_angle_,_cntr_,_`[`loops`]`_) + +Given a scan _scan_, center it about zero, rotate it by an angle _angle_ in radians, then shift its center by _cntr_. All other global transformations are removed. Loops, if specified, gives loop numbers for the _x_ and _y_ axis of the scan. If not given, the innermost two loops are assumed. + +### Example ### +See known bugs, limitations. + +### Known Bugs/Limitations ### + +In order to rotate a scan, both the _x_ and _y_ channels must be in the setchan for the innermost loop. + No examples. \ No newline at end of file diff --git a/doc/smopen.md b/doc/smopen.md index 1b36423fbe353a920e3247e400eaf87775ffd2f3..7ef22de19ed84f7a1388a3c95b99c242b0dcb591 100644 --- a/doc/smopen.md +++ b/doc/smopen.md @@ -1,26 +1,26 @@ -**smopen**(_`[`inst`]`_) - -For many interface types (serial, GPIB, VXI-11), MATLAB requires that you explicitly open a connection to the instrument before communications with it. **smopen** begins communications with such instruments. _inst_ can be: - - * Empty, in which case all instruments in {{{ smdata.inst }} will be opened. - * A vector of numbers, in which case instruments with those numbers will be opened. See _[smprintinst](smprintinst.md)_. - * A string, in which case the instrument with that name is opened. - -An instrument will only be opened if its status is currently "closed". -### Example ### -``` -smopen(1:5); % Open instruments 1-5 -smopen('MyAWG'); % Open the instrument named MyAWG -smopen(); % Open all instruments -``` - -### See Also ### - * _[smclose](smclose.md)_ - * _[smprintinst](smprintinst.md)_ - * The MATLAB manual on VISA/GPIB objects. - * **[smdata](smdata.md)** - -### Known Bugs/Limitations ### -_smopen_ only works on instruments where ` smdata.inst(x).data.inst ` is a handle to a MATLAB communications object. It fails silently otherwise. - +**smopen**(_`[`inst`]`_) + +For many interface types (serial, GPIB, VXI-11), MATLAB requires that you explicitly open a connection to the instrument before communications with it. **smopen** begins communications with such instruments. _inst_ can be: + + * Empty, in which case all instruments in {{{ smdata.inst }} will be opened. + * A vector of numbers, in which case instruments with those numbers will be opened. See _[smprintinst](smprintinst.md)_. + * A string, in which case the instrument with that name is opened. + +An instrument will only be opened if its status is currently "closed". +### Example ### +``` +smopen(1:5); % Open instruments 1-5 +smopen('MyAWG'); % Open the instrument named MyAWG +smopen(); % Open all instruments +``` + +### See Also ### + * _[smclose](smclose.md)_ + * _[smprintinst](smprintinst.md)_ + * The MATLAB manual on VISA/GPIB objects. + * **[smdata](smdata.md)** + +### Known Bugs/Limitations ### +_smopen_ only works on instruments where ` smdata.inst(x).data.inst ` is a handle to a MATLAB communications object. It fails silently otherwise. + If one instrument fails to open, all later instruments will not be opened. \ No newline at end of file diff --git a/doc/smprintrange.md b/doc/smprintrange.md index 04390ab1dc31b404fab4f3a2e7ef2b0db0f740d9..bc2eaae606ba46e2fe4d5878d501b55c9773480e 100644 --- a/doc/smprintrange.md +++ b/doc/smprintrange.md @@ -1,28 +1,28 @@ -**smprintrange**(_`[`ch`]`_) -> Print the range, ramp rate, and attenuation on _ch_. _ch_ can -be a vector of channel numbers, a channel name, or a cell array of channel names. If _ch_ is omitted, all channels are printed. - -Factor is the ratio of the requested value to the actual channel output. For example, an output with 10x external attenuation might have a -factor of 10. - - -### Example ### -``` ->> smprintrange(1:5) -CH Name Min Max Rate (1/s) Factor ---------------------------------------------------------------- - 1 1a -0.6 0 0.07 11 - 2 2a -0.6 0 0.07 11 - 3 3a -0.6 0 0.07 11 - 4 4a -0.6 0 0.07 11 - 5 1b -0.6 0 0.07 11 - ->> sprintrange('PlsRamp3') -CH Name Min Max Rate (1/s) Factor ---------------------------------------------------------------- -54 PlsRamp3 -0.014 0.014 1e+002 71 -``` - -### See Also ### - * [smprintchannels](smprintchannels.md) +**smprintrange**(_`[`ch`]`_) +> Print the range, ramp rate, and attenuation on _ch_. _ch_ can +be a vector of channel numbers, a channel name, or a cell array of channel names. If _ch_ is omitted, all channels are printed. + +Factor is the ratio of the requested value to the actual channel output. For example, an output with 10x external attenuation might have a +factor of 10. + + +### Example ### +``` +>> smprintrange(1:5) +CH Name Min Max Rate (1/s) Factor +--------------------------------------------------------------- + 1 1a -0.6 0 0.07 11 + 2 2a -0.6 0 0.07 11 + 3 3a -0.6 0 0.07 11 + 4 4a -0.6 0 0.07 11 + 5 1b -0.6 0 0.07 11 + +>> sprintrange('PlsRamp3') +CH Name Min Max Rate (1/s) Factor +--------------------------------------------------------------- +54 PlsRamp3 -0.014 0.014 1e+002 71 +``` + +### See Also ### + * [smprintchannels](smprintchannels.md) * [smdata](smdata.md) \ No newline at end of file diff --git a/doc/smprintscan.md b/doc/smprintscan.md index 59dad6ba149a0e556fe711f69c717da07d8f191a..4b7e550f61c302e4b0a7ee2f9e4d2622a48525b0 100644 --- a/doc/smprintscan.md +++ b/doc/smprintscan.md @@ -1,28 +1,28 @@ -**smprintscan**(_scan_) - -Prints a human-readable description of a scan - -### Example ### -``` -smprintscan(scanSDL) -Loop 1 -------- -x = -0.03 to 0.01, 100 points - -Channels set : SD1top -Ramptimes : -5.00e-003 s/point - -Channels read: - -Loop 2 -------- -x = 0.03 to 0.08, 49 points - -Channels set : SD1bot -Ramptimes : NaN s/point - -Channels read: DAQ1 -``` - -### See Also ### +**smprintscan**(_scan_) + +Prints a human-readable description of a scan + +### Example ### +``` +smprintscan(scanSDL) +Loop 1 +------- +x = -0.03 to 0.01, 100 points + +Channels set : SD1top +Ramptimes : -5.00e-003 s/point + +Channels read: + +Loop 2 +------- +x = 0.03 to 0.08, 49 points + +Channels set : SD1bot +Ramptimes : NaN s/point + +Channels read: DAQ1 +``` + +### See Also ### * [scan](scan.md) \ No newline at end of file diff --git a/doc/smrun.md b/doc/smrun.md index 9657bd0255500ed54892a56ba14ce86d01f38773..122ee8d8f17674bfb800ca8de1b7ea70364f8ab3 100644 --- a/doc/smrun.md +++ b/doc/smrun.md @@ -1,42 +1,42 @@ -data = **smrun**(_scan_, _`[`filename`]`_) - -data = **smrun**(_filename_) (will assume _scan_ = _smscan_) - -Run a scan, optionally saving the result to a file. See the page -documenting the [scan](scan.md) structure for help in designing scans. - -### Examples ### -> Fixme -- write an example - -### See Also ### - * [smscanpar](smscanpar.md) - * [smdiagpar](smdiagpar.md) - * [smprintscan](smprintscan.md) - - ---- - -### Pseudocode for smrun ### -Set constant channels - -Call configfn; ` scan=configfn(i).fn(scan,configfn(i).args{:}); ` - -Main loop - * For loops needing update (outer first) - * Set values and/or program ramps - * call prefn - * wait - * trigger ramped channels if needed - * end - - * For loops needing readout (inner first) - * read data - * call postfn - * apply procfn - * display data - * save data if needed - * call datafn - * end -end - +data = **smrun**(_scan_, _`[`filename`]`_) + +data = **smrun**(_filename_) (will assume _scan_ = _smscan_) + +Run a scan, optionally saving the result to a file. See the page +documenting the [scan](scan.md) structure for help in designing scans. + +### Examples ### +> Fixme -- write an example + +### See Also ### + * [smscanpar](smscanpar.md) + * [smdiagpar](smdiagpar.md) + * [smprintscan](smprintscan.md) + + +--- + +### Pseudocode for smrun ### +Set constant channels + +Call configfn; ` scan=configfn(i).fn(scan,configfn(i).args{:}); ` + +Main loop + * For loops needing update (outer first) + * Set values and/or program ramps + * call prefn + * wait + * trigger ramped channels if needed + * end + + * For loops needing readout (inner first) + * read data + * call postfn + * apply procfn + * display data + * save data if needed + * call datafn + * end +end + Save data. \ No newline at end of file diff --git a/doc/smscanpar.md b/doc/smscanpar.md index e9b5a2535eac5bf216def745392e74a4846112f7..ceae953ba630537980ae09e0921338f913474eae 100644 --- a/doc/smscanpar.md +++ b/doc/smscanpar.md @@ -1,13 +1,13 @@ -scan = **smscanpar**(_scan_, _`[`cntr`]`_, _`[`rng`]`_, _`[`npoints`]`_, _`[`loops`]`_) - -Set center, range and number of points for ` scan.loops(loops) `. -_loops_ defaults to ` 1:length(cntr) `. Empty or omitted arguments are left unchanged. `scan.consts` are set and `scan.configfn` is executed at the end if present and not empty. - - -Alternatively, if _cntr_ is `'gca'`, copy the range of the current plot to the scan. This is handy for 'zooming in' on scans. -### See Also ### - * [scan](scan.md) - * [smdiagpar](smdiagpar.md) - -### Known Bugs ### +scan = **smscanpar**(_scan_, _`[`cntr`]`_, _`[`rng`]`_, _`[`npoints`]`_, _`[`loops`]`_) + +Set center, range and number of points for ` scan.loops(loops) `. +_loops_ defaults to ` 1:length(cntr) `. Empty or omitted arguments are left unchanged. `scan.consts` are set and `scan.configfn` is executed at the end if present and not empty. + + +Alternatively, if _cntr_ is `'gca'`, copy the range of the current plot to the scan. This is handy for 'zooming in' on scans. +### See Also ### + * [scan](scan.md) + * [smdiagpar](smdiagpar.md) + +### Known Bugs ### > This documentation is poor. \ No newline at end of file diff --git a/doc/smset.md b/doc/smset.md index a9356b394269654740d22f9cbda16271f8bdb148..6e9b53c2b7a6d11b2301220c1fc872a8391875ba 100644 --- a/doc/smset.md +++ b/doc/smset.md @@ -1,17 +1,17 @@ -**smset**(_channels_,_vals_,_`[`ramprate`]`_) - -Set _channels_ to _vals_. _channels_ can be a single string, a cell array of strings, a channel number, or a vector of channel numbers. _vals_ can correspondingly be a single value, a cell array of values, or a vector of values. If _ramprate_ is not specified, the default from [smdata.channels] is used. - -Normally **smset** does not terminate until the ramp is complete. However, if the ramprate is negative, it will set up the ramp for self-ramping channels but not wait for it to finish. (This feature is chiefly used by [smrun](smrun.md). -### Examples ### -``` - smset('1a',-.123); % sets '1a' to -.123 - smset(1:5,[ 0 0 0 0 0]); % sets channels 1:5 (in smdata.channels) all to 0 - smset({'1b','2b'},{-.2,-.2}); %sets '1b' and '2b' to -.2 each - smset('1a',-.4, .01); % sets '1a' to -.4 ramping at .01/second -``` -### See Also ### - * [smget](smget.md) - * [smprintchannels](smprintchannels.md) - * [smprintrange](smprintrange.md) - * [smdata](smdata.md) for a description of [smdata.channels]. +**smset**(_channels_,_vals_,_`[`ramprate`]`_) + +Set _channels_ to _vals_. _channels_ can be a single string, a cell array of strings, a channel number, or a vector of channel numbers. _vals_ can correspondingly be a single value, a cell array of values, or a vector of values. If _ramprate_ is not specified, the default from [smdata.channels] is used. + +Normally **smset** does not terminate until the ramp is complete. However, if the ramprate is negative, it will set up the ramp for self-ramping channels but not wait for it to finish. (This feature is chiefly used by [smrun](smrun.md). +### Examples ### +``` + smset('1a',-.123); % sets '1a' to -.123 + smset(1:5,[ 0 0 0 0 0]); % sets channels 1:5 (in smdata.channels) all to 0 + smset({'1b','2b'},{-.2,-.2}); %sets '1b' and '2b' to -.2 each + smset('1a',-.4, .01); % sets '1a' to -.4 ramping at .01/second +``` +### See Also ### + * [smget](smget.md) + * [smprintchannels](smprintchannels.md) + * [smprintrange](smprintrange.md) + * [smdata](smdata.md) for a description of [smdata.channels]. diff --git a/sm GUI/sm.m b/sm GUI/sm.m index 12abcf4b6af5ee21a6087532b7d5ccd8b990a358..9d569d155c3c8f7ca87ba5476204a83c48e64443 100755 --- a/sm GUI/sm.m +++ b/sm GUI/sm.m @@ -1,458 +1,458 @@ -function varargout = sm(varargin) -% SM M-file for sm.fig -% SM, by itself, creates a new SM or raises the existing -% singleton*. -% -% H = SM returns the handle to a new SM or the handle to -% the existing singleton*. -% -% SM('CALLBACK',hObject,eventData,handles,...) calls the local -% function named CALLBACK in SM.M with the given input arguments. -% -% SM('Property','Value',...) creates a new SM or raises the -% existing singleton*. Starting from the left, property value pairs are -% applied to the GUI before sm_OpeningFcn gets called. An -% unrecognized property name or invalid value makes property application -% stop. All inputs are passed to sm_OpeningFcn via varargin. -% -% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one -% instance to run (singleton)". -% - -% Copyright 2011 Hendrik Bluhm, Vivek Venkatachalam -% This file is part of Special Measure. -% -% Special Measure 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 3 of the License, or -% (at your option) any later version. -% -% Special Measure 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 Special Measure. If not, see -% <http://www.gnu.org/licenses/>. -% See also: GUIDE, GUIDATA, GUIHANDLES - -% Edit the above text to modify the response to help sm - -% Last Modified by GUIDE v2.5 04-Mar-2011 10:05:43 - -% Begin initialization code - DO NOT EDIT -gui_Singleton = 1; -gui_State = struct('gui_Name', mfilename, ... - 'gui_Singleton', gui_Singleton, ... - 'gui_OpeningFcn', @sm_OpeningFcn, ... - 'gui_OutputFcn', @sm_OutputFcn, ... - 'gui_LayoutFcn', [] , ... - 'gui_Callback', []); -if nargin && ischar(varargin{1}) - gui_State.gui_Callback = str2func(varargin{1}); -end - -if nargout - [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); -else - gui_mainfcn(gui_State, varargin{:}); -end -% End initialization code - DO NOT EDIT - - -% --- Executes just before sm is made visible. -function sm_OpeningFcn(hObject, eventdata, handles, varargin) -% This function has no output args, see OutputFcn. -% hObject handle to figure -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -% varargin command line arguments to sm (see VARARGIN) - -% Choose default command line output for sm -handles.output = hObject; - -% Update handles structure -guidata(hObject, handles); -sm_Callback('Open',handles); -% UIWAIT makes sm wait for user response (see UIRESUME) -% uiwait(handles.figure1); - - -% --- Outputs from this function are returned to the command line. -function varargout = sm_OutputFcn(hObject, eventdata, handles) -% varargout cell array for returning output args (see VARARGOUT); -% hObject handle to figure -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Get default command line output from handles structure -varargout{1} = handles.output; - - -% --- Executes on selection change in scans_lbh. -function scans_lbh_Callback(hObject, eventdata, handles) -% hObject handle to scans_lbh (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('Scans'); - - -% --- Executes during object creation, after setting all properties. -function scans_lbh_CreateFcn(hObject, eventdata, handles) -% hObject handle to scans_lbh (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called -sm_Callback('ScansCreate'); -% Hint: listbox controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on selection change in queue_lbh. -function queue_lbh_Callback(hObject, eventdata, handles) -% hObject handle to queue_lbh (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('Queue'); -% Hints: contents = cellstr(get(hObject,'String')) returns queue_lbh contents as cell array -% contents{get(hObject,'Value')} returns selected item from queue_lbh - - -% --- Executes during object creation, after setting all properties. -function queue_lbh_CreateFcn(hObject, eventdata, handles) -% hObject handle to queue_lbh (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called -sm_Callback('QueueCreate'); -% Hint: listbox controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% -------------------------------------------------------------------- -function file_Callback(hObject, eventdata, handles) -% hObject handle to file (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - - -% -------------------------------------------------------------------- -function openscans_Callback(hObject, eventdata, handles) -% hObject handle to openscans (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('OpenScans'); - - -% -------------------------------------------------------------------- -function savescans_Callback(hObject, eventdata, handles) -% hObject handle to savescans (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('SaveScans'); - - -% -------------------------------------------------------------------- -function openrack_Callback(hObject, eventdata, handles) -% hObject handle to openrack (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('OpenRack'); - - -% -------------------------------------------------------------------- -function saverack_Callback(hObject, eventdata, handles) -% hObject handle to saverack (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('SaveRack'); - - -% -------------------------------------------------------------------- -function editrack_Callback(hObject, eventdata, handles) -% hObject handle to editrack (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('EditRack'); - - -% --- Executes on selection change in smusers_lbh. -function smusers_lbh_Callback(hObject, eventdata, handles) -% hObject handle to smusers_lbh (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('SMusers'); - -% Hints: contents = cellstr(get(hObject,'String')) returns smusers_lbh contents as cell array -% contents{get(hObject,'Value')} returns selected item from smusers_lbh - - -% --- Executes during object creation, after setting all properties. -function smusers_lbh_CreateFcn(hObject, eventdata, handles) -% hObject handle to smusers_lbh (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called -sm_Callback('SMusersCreate'); -% Hint: listbox controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on button press in enqueue. -function enqueue_Callback(hObject, eventdata, handles) -% hObject handle to enqueue (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('Enqueue'); - - -% --- Executes on button press in editscan_pbh. -function editscan_pbh_Callback(hObject, eventdata, handles) -% hObject handle to editscan_pbh (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('EditScan'); - - -% --- Executes on button press in removescan_pbh. -function removescan_pbh_Callback(hObject, eventdata, handles) -% hObject handle to removescan_pbh (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('RemoveScan'); - - - -function qtxt_eth_Callback(hObject, eventdata, handles) -% hObject handle to qtxt_eth (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('Qtxt'); -% Hints: get(hObject,'String') returns contents of qtxt_eth as text -% str2double(get(hObject,'String')) returns contents of qtxt_eth as a double - - -% --- Executes during object creation, after setting all properties. -function qtxt_eth_CreateFcn(hObject, eventdata, handles) -% hObject handle to qtxt_eth (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on button press in txtenqueue. -function txtenqueue_Callback(hObject, eventdata, handles) -% hObject handle to txtenqueue (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('TXTenqueue'); - -% --- Executes on button press in pptauto_cbh. -function pptauto_cbh_Callback(hObject, eventdata, handles) -% hObject handle to pptauto_cbh (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('PPTauto'); -% Hint: get(hObject,'Value') returns toggle state of pptauto_cbh - - -% --- Executes on button press in pptfile_pbh. -function pptfile_pbh_Callback(hObject, eventdata, handles) -% hObject handle to pptfile_pbh (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('PPTFile'); - - - -function comments_eth_Callback(hObject, eventdata, handles) -% hObject handle to comments_eth (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('Comments'); -% Hints: get(hObject,'String') returns contents of comments_eth as text -% str2double(get(hObject,'String')) returns contents of comments_eth as a double - - -% --- Executes during object creation, after setting all properties. -function comments_eth_CreateFcn(hObject, eventdata, handles) -% hObject handle to comments_eth (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - - -function pptsave_eth_Callback(hObject, eventdata, handles) -% hObject handle to pptsave_eth (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('PPTSaveFig'); -% Hints: get(hObject,'String') returns contents of pptsave_eth as text -% str2double(get(hObject,'String')) returns contents of pptsave_eth as a double - - -% --- Executes during object creation, after setting all properties. -function pptsave_eth_CreateFcn(hObject, eventdata, handles) -% hObject handle to pptsave_eth (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on button press in pptsave_pbh. -function pptsave_pbh_Callback(hObject, eventdata, handles) -% hObject handle to pptsave_pbh (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('PPTSaveNow'); - - -% --- Executes on button press in savepath_pbh. -function savepath_pbh_Callback(hObject, eventdata, handles) -% hObject handle to savepath_pbh (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('SavePath'); - - - -function run_eth_Callback(hObject, eventdata, handles) -% hObject handle to run_eth (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('RunNum'); -% Hints: get(hObject,'String') returns contents of run_eth as text -% str2double(get(hObject,'String')) returns contents of run_eth as a double - - -% --- Executes during object creation, after setting all properties. -function run_eth_CreateFcn(hObject, eventdata, handles) -% hObject handle to run_eth (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called -sm_Callback('RunCreate'); -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on button press in runincrement_cbh. -function runincrement_cbh_Callback(hObject, eventdata, handles) -% hObject handle to runincrement_cbh (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('RunIncrement'); -% Hint: get(hObject,'Value') returns toggle state of runincrement_cbh - - -% --- Executes on button press in run_pbh. -function run_pbh_Callback(hObject, eventdata, handles) -% hObject handle to run_pbh (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('Run'); - -% --- Executes on button press in pause_pbh. -function pause_pbh_Callback(hObject, eventdata, handles) -% hObject handle to pause_pbh (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('Pause'); - -% --- Executes on button press in pptfile2_pbh. -function pptfile2_pbh_Callback(hObject, eventdata, handles) -% hObject handle to pptfile2_pbh (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('PPTFile2'); - -% --- Executes on button press in pptsavepriority_cbh. -function pptsavepriority_cbh_Callback(hObject, eventdata, handles) -% hObject handle to pptsavepriority_cbh (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('PPTPriority'); -% Hint: get(hObject,'Value') returns toggle state of pptsavepriority_cbh - - - -function console_eth_Callback(hObject, eventdata, handles) -% hObject handle to console_eth (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('Console'); -% Hints: get(hObject,'String') returns contents of console_eth as text -% str2double(get(hObject,'String')) returns contents of console_eth as a double - - -% --- Executes during object creation, after setting all properties. -function console_eth_CreateFcn(hObject, eventdata, handles) -% hObject handle to console_eth (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles empty - handles not created until after all CreateFcns called -% Hint: edit controls usually have a white background on Windows. -% See ISPC and COMPUTER. -if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) - set(hObject,'BackgroundColor','white'); -end - - -% --- Executes on button press in evaluate_pbh. -function evaluate_pbh_Callback(hObject, eventdata, handles) -% hObject handle to evaluate_pbh (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('Eval'); - - -% --- Executes on key press with focus on queue_lbh and none of its controls. -function queue_lbh_KeyPressFcn(hObject, eventdata, handles) -% hObject handle to queue_lbh (see GCBO) -% eventdata structure with the following fields (see UICONTROL) -% Key: name of the key that was pressed, in lower case -% Character: character interpretation of the key(s) that was pressed -% Modifier: name(s) of the modifier key(s) (i.e., control, shift) pressed -% handles structure with handles and user data (see GUIDATA) -%sm_Callback('QueueKeyPress',eventdata); -sm_Callback('QueueKey',eventdata); - - -% --- Executes on key press with focus on scans_lbh and none of its controls. -function scans_lbh_KeyPressFcn(hObject, eventdata, handles) -% hObject handle to scans_lbh (see GCBO) -% eventdata structure with the following fields (see UICONTROL) -% Key: name of the key that was pressed, in lower case -% Character: character interpretation of the key(s) that was pressed -% Modifier: name(s) of the modifier key(s) (i.e., control, shift) pressed -% handles structure with handles and user data (see GUIDATA) -sm_Callback('ScansKey',eventdata); - - -% --- Executes on button press in editscan2_pbh. -function editscan2_pbh_Callback(hObject, eventdata, handles) -% hObject handle to editscan2_pbh (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -sm_Callback('EditScan2'); +function varargout = sm(varargin) +% SM M-file for sm.fig +% SM, by itself, creates a new SM or raises the existing +% singleton*. +% +% H = SM returns the handle to a new SM or the handle to +% the existing singleton*. +% +% SM('CALLBACK',hObject,eventData,handles,...) calls the local +% function named CALLBACK in SM.M with the given input arguments. +% +% SM('Property','Value',...) creates a new SM or raises the +% existing singleton*. Starting from the left, property value pairs are +% applied to the GUI before sm_OpeningFcn gets called. An +% unrecognized property name or invalid value makes property application +% stop. All inputs are passed to sm_OpeningFcn via varargin. +% +% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one +% instance to run (singleton)". +% + +% Copyright 2011 Hendrik Bluhm, Vivek Venkatachalam +% This file is part of Special Measure. +% +% Special Measure 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 3 of the License, or +% (at your option) any later version. +% +% Special Measure 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 Special Measure. If not, see +% <http://www.gnu.org/licenses/>. +% See also: GUIDE, GUIDATA, GUIHANDLES + +% Edit the above text to modify the response to help sm + +% Last Modified by GUIDE v2.5 04-Mar-2011 10:05:43 + +% Begin initialization code - DO NOT EDIT +gui_Singleton = 1; +gui_State = struct('gui_Name', mfilename, ... + 'gui_Singleton', gui_Singleton, ... + 'gui_OpeningFcn', @sm_OpeningFcn, ... + 'gui_OutputFcn', @sm_OutputFcn, ... + 'gui_LayoutFcn', [] , ... + 'gui_Callback', []); +if nargin && ischar(varargin{1}) + gui_State.gui_Callback = str2func(varargin{1}); +end + +if nargout + [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); +else + gui_mainfcn(gui_State, varargin{:}); +end +% End initialization code - DO NOT EDIT + + +% --- Executes just before sm is made visible. +function sm_OpeningFcn(hObject, eventdata, handles, varargin) +% This function has no output args, see OutputFcn. +% hObject handle to figure +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +% varargin command line arguments to sm (see VARARGIN) + +% Choose default command line output for sm +handles.output = hObject; + +% Update handles structure +guidata(hObject, handles); +sm_Callback('Open',handles); +% UIWAIT makes sm wait for user response (see UIRESUME) +% uiwait(handles.figure1); + + +% --- Outputs from this function are returned to the command line. +function varargout = sm_OutputFcn(hObject, eventdata, handles) +% varargout cell array for returning output args (see VARARGOUT); +% hObject handle to figure +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Get default command line output from handles structure +varargout{1} = handles.output; + + +% --- Executes on selection change in scans_lbh. +function scans_lbh_Callback(hObject, eventdata, handles) +% hObject handle to scans_lbh (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('Scans'); + + +% --- Executes during object creation, after setting all properties. +function scans_lbh_CreateFcn(hObject, eventdata, handles) +% hObject handle to scans_lbh (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called +sm_Callback('ScansCreate'); +% Hint: listbox controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + + +% --- Executes on selection change in queue_lbh. +function queue_lbh_Callback(hObject, eventdata, handles) +% hObject handle to queue_lbh (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('Queue'); +% Hints: contents = cellstr(get(hObject,'String')) returns queue_lbh contents as cell array +% contents{get(hObject,'Value')} returns selected item from queue_lbh + + +% --- Executes during object creation, after setting all properties. +function queue_lbh_CreateFcn(hObject, eventdata, handles) +% hObject handle to queue_lbh (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called +sm_Callback('QueueCreate'); +% Hint: listbox controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + + +% -------------------------------------------------------------------- +function file_Callback(hObject, eventdata, handles) +% hObject handle to file (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + + +% -------------------------------------------------------------------- +function openscans_Callback(hObject, eventdata, handles) +% hObject handle to openscans (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('OpenScans'); + + +% -------------------------------------------------------------------- +function savescans_Callback(hObject, eventdata, handles) +% hObject handle to savescans (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('SaveScans'); + + +% -------------------------------------------------------------------- +function openrack_Callback(hObject, eventdata, handles) +% hObject handle to openrack (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('OpenRack'); + + +% -------------------------------------------------------------------- +function saverack_Callback(hObject, eventdata, handles) +% hObject handle to saverack (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('SaveRack'); + + +% -------------------------------------------------------------------- +function editrack_Callback(hObject, eventdata, handles) +% hObject handle to editrack (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('EditRack'); + + +% --- Executes on selection change in smusers_lbh. +function smusers_lbh_Callback(hObject, eventdata, handles) +% hObject handle to smusers_lbh (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('SMusers'); + +% Hints: contents = cellstr(get(hObject,'String')) returns smusers_lbh contents as cell array +% contents{get(hObject,'Value')} returns selected item from smusers_lbh + + +% --- Executes during object creation, after setting all properties. +function smusers_lbh_CreateFcn(hObject, eventdata, handles) +% hObject handle to smusers_lbh (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called +sm_Callback('SMusersCreate'); +% Hint: listbox controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + + +% --- Executes on button press in enqueue. +function enqueue_Callback(hObject, eventdata, handles) +% hObject handle to enqueue (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('Enqueue'); + + +% --- Executes on button press in editscan_pbh. +function editscan_pbh_Callback(hObject, eventdata, handles) +% hObject handle to editscan_pbh (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('EditScan'); + + +% --- Executes on button press in removescan_pbh. +function removescan_pbh_Callback(hObject, eventdata, handles) +% hObject handle to removescan_pbh (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('RemoveScan'); + + + +function qtxt_eth_Callback(hObject, eventdata, handles) +% hObject handle to qtxt_eth (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('Qtxt'); +% Hints: get(hObject,'String') returns contents of qtxt_eth as text +% str2double(get(hObject,'String')) returns contents of qtxt_eth as a double + + +% --- Executes during object creation, after setting all properties. +function qtxt_eth_CreateFcn(hObject, eventdata, handles) +% hObject handle to qtxt_eth (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called +% Hint: edit controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + + +% --- Executes on button press in txtenqueue. +function txtenqueue_Callback(hObject, eventdata, handles) +% hObject handle to txtenqueue (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('TXTenqueue'); + +% --- Executes on button press in pptauto_cbh. +function pptauto_cbh_Callback(hObject, eventdata, handles) +% hObject handle to pptauto_cbh (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('PPTauto'); +% Hint: get(hObject,'Value') returns toggle state of pptauto_cbh + + +% --- Executes on button press in pptfile_pbh. +function pptfile_pbh_Callback(hObject, eventdata, handles) +% hObject handle to pptfile_pbh (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('PPTFile'); + + + +function comments_eth_Callback(hObject, eventdata, handles) +% hObject handle to comments_eth (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('Comments'); +% Hints: get(hObject,'String') returns contents of comments_eth as text +% str2double(get(hObject,'String')) returns contents of comments_eth as a double + + +% --- Executes during object creation, after setting all properties. +function comments_eth_CreateFcn(hObject, eventdata, handles) +% hObject handle to comments_eth (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called +% Hint: edit controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + + + +function pptsave_eth_Callback(hObject, eventdata, handles) +% hObject handle to pptsave_eth (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('PPTSaveFig'); +% Hints: get(hObject,'String') returns contents of pptsave_eth as text +% str2double(get(hObject,'String')) returns contents of pptsave_eth as a double + + +% --- Executes during object creation, after setting all properties. +function pptsave_eth_CreateFcn(hObject, eventdata, handles) +% hObject handle to pptsave_eth (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called +% Hint: edit controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + + +% --- Executes on button press in pptsave_pbh. +function pptsave_pbh_Callback(hObject, eventdata, handles) +% hObject handle to pptsave_pbh (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('PPTSaveNow'); + + +% --- Executes on button press in savepath_pbh. +function savepath_pbh_Callback(hObject, eventdata, handles) +% hObject handle to savepath_pbh (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('SavePath'); + + + +function run_eth_Callback(hObject, eventdata, handles) +% hObject handle to run_eth (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('RunNum'); +% Hints: get(hObject,'String') returns contents of run_eth as text +% str2double(get(hObject,'String')) returns contents of run_eth as a double + + +% --- Executes during object creation, after setting all properties. +function run_eth_CreateFcn(hObject, eventdata, handles) +% hObject handle to run_eth (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called +sm_Callback('RunCreate'); +% Hint: edit controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + + +% --- Executes on button press in runincrement_cbh. +function runincrement_cbh_Callback(hObject, eventdata, handles) +% hObject handle to runincrement_cbh (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('RunIncrement'); +% Hint: get(hObject,'Value') returns toggle state of runincrement_cbh + + +% --- Executes on button press in run_pbh. +function run_pbh_Callback(hObject, eventdata, handles) +% hObject handle to run_pbh (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('Run'); + +% --- Executes on button press in pause_pbh. +function pause_pbh_Callback(hObject, eventdata, handles) +% hObject handle to pause_pbh (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('Pause'); + +% --- Executes on button press in pptfile2_pbh. +function pptfile2_pbh_Callback(hObject, eventdata, handles) +% hObject handle to pptfile2_pbh (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('PPTFile2'); + +% --- Executes on button press in pptsavepriority_cbh. +function pptsavepriority_cbh_Callback(hObject, eventdata, handles) +% hObject handle to pptsavepriority_cbh (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('PPTPriority'); +% Hint: get(hObject,'Value') returns toggle state of pptsavepriority_cbh + + + +function console_eth_Callback(hObject, eventdata, handles) +% hObject handle to console_eth (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('Console'); +% Hints: get(hObject,'String') returns contents of console_eth as text +% str2double(get(hObject,'String')) returns contents of console_eth as a double + + +% --- Executes during object creation, after setting all properties. +function console_eth_CreateFcn(hObject, eventdata, handles) +% hObject handle to console_eth (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called +% Hint: edit controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + + +% --- Executes on button press in evaluate_pbh. +function evaluate_pbh_Callback(hObject, eventdata, handles) +% hObject handle to evaluate_pbh (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('Eval'); + + +% --- Executes on key press with focus on queue_lbh and none of its controls. +function queue_lbh_KeyPressFcn(hObject, eventdata, handles) +% hObject handle to queue_lbh (see GCBO) +% eventdata structure with the following fields (see UICONTROL) +% Key: name of the key that was pressed, in lower case +% Character: character interpretation of the key(s) that was pressed +% Modifier: name(s) of the modifier key(s) (i.e., control, shift) pressed +% handles structure with handles and user data (see GUIDATA) +%sm_Callback('QueueKeyPress',eventdata); +sm_Callback('QueueKey',eventdata); + + +% --- Executes on key press with focus on scans_lbh and none of its controls. +function scans_lbh_KeyPressFcn(hObject, eventdata, handles) +% hObject handle to scans_lbh (see GCBO) +% eventdata structure with the following fields (see UICONTROL) +% Key: name of the key that was pressed, in lower case +% Character: character interpretation of the key(s) that was pressed +% Modifier: name(s) of the modifier key(s) (i.e., control, shift) pressed +% handles structure with handles and user data (see GUIDATA) +sm_Callback('ScansKey',eventdata); + + +% --- Executes on button press in editscan2_pbh. +function editscan2_pbh_Callback(hObject, eventdata, handles) +% hObject handle to editscan2_pbh (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +sm_Callback('EditScan2'); diff --git a/sm GUI/smauxinit2.m b/sm GUI/smauxinit2.m index 575d92dabb1c8f1cf7077ddfa9944a5110997e63..e81dbe4955746e02d76658db063efebd44d9c99d 100755 --- a/sm GUI/smauxinit2.m +++ b/sm GUI/smauxinit2.m @@ -1,10 +1,10 @@ -global smaux -smaux.datadir = pwd; %uigetdir('C:\Documents and Settings\spm\My Documents\MX 400 Data','Select Data Directory'); - -pptsavefile = ''; - -if ~isfield(smaux,'run') - smaux.run=100; -end - -smaux.initialized=1; +global smaux +smaux.datadir = pwd; %uigetdir('C:\Documents and Settings\spm\My Documents\MX 400 Data','Select Data Directory'); + +pptsavefile = ''; + +if ~isfield(smaux,'run') + smaux.run=100; +end + +smaux.initialized=1; diff --git a/sm/channels/smaNIDAQmx.m b/sm/channels/smaNIDAQmx.m index e55ad1ab11d4faf22701de6ca651ba136aa09f2f..e98bde3a087cc9f22c049d45325c4fcd768e85ef 100755 --- a/sm/channels/smaNIDAQmx.m +++ b/sm/channels/smaNIDAQmx.m @@ -1,44 +1,10 @@ -function scan = smaNIDAQmx(scan, varargin) -% function scan = smaNIDAQmx(scan, varargin) -% provides helpers for the NIDAQmx -% -% optional -% ---------------------------------------------------- -% -% 'inst' name -% name of NI instrument to configure; e.g. 'NIPCIe6363' or 'NIPCI6713' -% default: 'NIPCIe6363' -% -% 'trig' [source destination] -% source is optional; if not specified source = external; if both are -% empty, all remaining trigger connections are removed -% -% 'sngl' boolean -% if true, just read single points (inputSingleScan); defaults to `false` -% -% 'orate' double -% sets sampling rate of output; if sampling rate > ramprate -> set downsampling in -% smcNIDAQmx -% -% 'irate' double -% sets sampling rate of input; if sampling rate > ramprate -> set downsampling in -% smcNIDAQmx -% -% 'npoints' integer -% sets the NumberOfScans property of input and output session -% -% 'rng' [lower upper] -% sets range of input -% -% 'addInput' channels as cell -% manually adds input channels to the session; TODO: add feature to -% remove existing channels -% +function scan = smaNIDAQmx(scan, device, varargin) +% This function is generally deprecated and will likely already not work +% with the current control functions ip = inputParser; ip.FunctionName = 'smaNIDAQmx'; ip.addRequired('scan'); -% changing the default for 'inst' will result in many scans breaking! -ip.addOptional('inst', 'NIPCIe6363'); +ip.addRequired('device'); ip.addOptional('trig', {}); ip.addOptional('sngl', false); ip.addOptional('orate', [], @isnumeric); @@ -46,10 +12,10 @@ ip.addOptional('irate', [], @isnumeric); ip.addOptional('npoints', [], @isnumeric); ip.addOptional('rng', []); ip.addOptional('addInput', []); -ip.parse(scan,varargin{:}); +ip.parse(scan,device,varargin{:}); global smdata -inst = sminstlookup(ip.Results.inst); +inst = sminstlookup(ip.Results.device); devID = smdata.inst(inst).data.id; try smdata.inst(inst).data.input.stop; catch err; end @@ -74,7 +40,16 @@ if ~isempty(ip.Results.addInput) end % determine number of input channels -numInputs = numel(smdata.inst(inst).data.input.Channels); +try + numInputs = numel(smdata.inst(inst).data.input.Channels); +catch err + doThrow = any(~strfind(err.message,... + 'Attempt to reference field of non-structure array.')); + if doThrow + rethrow(err); + end + numInputs = 0; +end % configure triggers if ~isempty(ip.Results.trig) @@ -168,7 +143,7 @@ if ip.Results.irate end if ip.Results.npoints - if strcmp(ip.Results.inst, 'NIPCI6713') + if strcmp(smdata.inst(inst).device, 'NIPCI6713') smdata.inst(inst).data.nout = ip.Results.npoints; else smdata.inst(inst).data.input.NumberOfScans = ip.Results.npoints; diff --git a/sm/channels/smalintrafo.m b/sm/channels/smalintrafo.m index 1643670448a79f711d3bb49011c68ed59dc105a0..4a758425afa48eb0b4a799eb116d222ee1af5e69 100644 --- a/sm/channels/smalintrafo.m +++ b/sm/channels/smalintrafo.m @@ -1,4 +1,4 @@ -function val = smalintrafo(x, xcoeff, xref, fixch, fixcoeff, fixref, const) - -global smdata; +function val = smalintrafo(x, xcoeff, xref, fixch, fixcoeff, fixref, const) + +global smdata; val = (x-xref) * xcoeff + (smdata.chanvals(fixch) - fixref) * fixcoeff + const; \ No newline at end of file diff --git a/sm/channels/smatrigfn.m b/sm/channels/smatrigfn.m index 3bea041779f3a42eda73524d88f2009776e97915..f8bbfd602a4df75c482f16374a4ebb426fb3f5a2 100644 --- a/sm/channels/smatrigfn.m +++ b/sm/channels/smatrigfn.m @@ -15,14 +15,15 @@ if nargin > 1 end -alreadyTriggered = []; +% alreadyTriggered = []; for i = 1:size(inst, 1) + % Collective Channels will be deprecated soon % just trigger collective channels once (does only work with type = 2 % channels at the moment. input channels to be added - if smdata.inst(inst(i, 1)).type(inst(i, 2)) == 2 && ... - any (alreadyTriggered == inst(i, 1)) - continue; - end +% if smdata.inst(inst(i, 1)).type(inst(i, 2)) == 2 && ... +% any (alreadyTriggered == inst(i, 1)) +% continue; +% end smdata.inst(inst(i, 1)).cntrlfn([inst(i, :), op]); end diff --git a/sm/channels/smcANC250.m b/sm/channels/smcANC250.m new file mode 100644 index 0000000000000000000000000000000000000000..668db3cfe49b0538a719662a535a3a0db90670b6 --- /dev/null +++ b/sm/channels/smcANC250.m @@ -0,0 +1,130 @@ +function [val, rate] = smcANC250(ico, val, rate, varargin) +% virtual instrument driver for scanning +global smdata + +switch ico(3) + case 0 + switch ico(2) + case {1,2,3} % setZ/setY/setX + val = smdata.inst(ico(1)).data.currentOutput(ico(2)); + + case {4,5,6} % setZ/setY/setX + val = smdata.inst(ico(1)).data.currentOutput(ico(2)-3); + end + + case 1 + switch ico(2) + case {1,2,3} % linrampZ/linrampY/linrampX + if nargin < 3 + rate = 7.5; +% session = smdata.inst(ico(1)).data.travel; + else +% session = smdata.inst(ico(1)).data.linramp; + end + session = smdata.inst(ico(1)).data.linramp; + + if rate > 0 + queue = repmat(smdata.inst(ico(1)).data.currentOutput,... + smdata.inst(ico(1)).data.npoints,... + 1); + queue(:,ico(2)) = linspace(... + smdata.inst(ico(1)).data.currentOutput(ico(2)),... + val,... + smdata.inst(ico(1)).data.npoints); + session.wait(); + session.queueOutputData(queue); + smdata.inst(ico(1)).data.queue = queue; + + if max(abs(queue(end,:) - queue(1,:))) > 0 + samprate = rate / ... + max(abs(queue(end,:) - queue(1,:))) * ... + smdata.inst(ico(1)).data.travelRatio * ... + smdata.inst(ico(1)).data.npoints; + if samprate > session.RateLimit(2) + samprate = session.RateLimit(2); + end + session.Rate = samprate; + session.prepare(); + if ~isempty(session.Connections) + session.startBackground() + fcnGenerateDigitalTrigger(); + while ~session.IsDone && session.IsRunning + session.wait(); + end + else + session.startForeground(); + end + end + smdata.inst(ico(1)).data.currentOutput = queue(end, :); + elseif rate < 0 + smdata.inst(ico(1)).data.queue(:,ico(2)) = linspace(... + smdata.inst(ico(1)).data.currentOutput(ico(2)),... + val,... + smdata.inst(ico(1)).data.npoints); + warning('off','all'); + session.release(); + warning('on','all'); + queue = smdata.inst(ico(1)).data.queue; + session.queueOutputData(queue); +% samprate = abs(rate) / ... +% max(abs(queue(end,:) - queue(1,:))) * ... +% smdata.inst(ico(1)).data.npoints; +% if samprate > session.RateLimit(2) +% samprate = session.RateLimit(2); +% end +% session.Rate = samprate; + end + + case {4,5,6} % setZ/setY/setX + out = smdata.inst(ico(1)).data.currentOutput; + out(ico(2)-3) = val; + smdata.inst(ico(1)).data.linramp.outputSingleScan(out); + smdata.inst(ico(1)).data.currentOutput = out; + end + + case 3 + switch ico(2) + case {1,2,3} + smdata.inst(ico(1)).data.linramp.startBackground(); + smdata.inst(ico(1)).data.currentOutput = ... + smdata.inst(ico(1)).data.queue(end, :); + end + + case 4 + switch ico(2) + case {1,2,3} + smdata.inst(ico(1)).data.linramp.startBackground(); + smdata.inst(ico(1)).data.currentOutput = ... + smdata.inst(ico(1)).data.queue(end, :); + end + case 6 + % this configures a NIDAQ Session with the NI PCIe-6363 to control + % the scanners + for dev = daq.getDevices + if strcmp (dev.Description, 'National Instruments PCIe-6363') + smdata.inst(ico(1)).data.id = dev.ID; + end + end + + % create default session for linear ramping of scanners + smdata.inst(ico(1)).data.linramp = daq.createSession('ni'); + smdata.inst(ico(1)).data.linramp.addAnalogOutputChannel( ... + smdata.inst(ico(1)).data.id,... + 0:2,... + 'Voltage'... + ); + smdata.inst(ico(1)).data.linramp.outputSingleScan([0 0 0]); + smdata.inst(ico(1)).data.currentOutput = [0 0 0]; + + % helper session to quickly fix some behaviour of sm + % should be replaced by a better concept at some point + smdata.inst(ico(1)).data.travel = daq.createSession('ni'); + smdata.inst(ico(1)).data.travel.addAnalogOutputChannel( ... + smdata.inst(ico(1)).data.id,... + 0:2,... + 'Voltage'... + ); + + otherwise + error('Operation not supported!') +end \ No newline at end of file diff --git a/sm/channels/smcANC350.m b/sm/channels/smcANC350.m index 1ad31896a9441fcfb182b62bc9a9f1e58674527c..311cf9378acd8b0b2168f1802e5a680467bda8b9 100644 --- a/sm/channels/smcANC350.m +++ b/sm/channels/smcANC350.m @@ -1,132 +1,136 @@ -function [val, rate] = smcANC350(ico, val, rate, varargin) -global smdata - -if ~libisloaded('hvpositionerv2') - loadlibrary('hvpositionerv2.dll', 'hvpositionerv2.h'); - - posInfo = libstruct('PositionerInfo'); - numDevices = calllib('hvpositionerv2','PositionerCheck',posInfo); - if numDevices < 1 - error('No device detected!') - end - - devHandle = libpointer('int32Ptr', 0); - devNo = int32(0); - % connect to device - callANC350('PositionerConnect',devNo,devHandle); - smdata.inst(ico(1)).data.devHandle = devHandle.Value; - - if ~isempty(smdata.inst(ico(1)).data.paramFile) - loadParamFile(smdata.inst(ico(1)).data.devHandle,... - smdata.inst(ico(1)).data.paramFile); - end -end - -switch ico(3) - case 0 - switch ico(2) - case 1 - val = getANC350(smdata.inst(ico(1)).data.devHandle,... - 'Position','x'); - case 2 - val = getANC350(smdata.inst(ico(1)).data.devHandle,... - 'Position','y'); - case 3 - val = getANC350(smdata.inst(ico(1)).data.devHandle,... - 'Position','z'); - end - - case 1 - switch ico(2) - case 1 - moveANC350(smdata.inst(ico(1)).data.devHandle,'x',... - 'abs', val); - case 2 - moveANC350(smdata.inst(ico(1)).data.devHandle,'y',... - 'abs', val); - case 3 - moveANC350(smdata.inst(ico(1)).data.devHandle,'z',... - 'abs', val); - otherwise - error('Operation not supported!') - end -end -end - -function retCode = callANC350(cmd,varargin) -% R�ckgabewerte der Funktionen -% #define NCB_Ok 0 Kein Fehler -% #define NCB_Error (-1) Unbekannter/sonstiger Fehler -% #define NCB_Timeout 1 Timeout bei Datenabruf -% #define NCB_NotConnected 2 Kein Kontakt zum Positioner �ber USB -% #define NCB_DriverError 3 Fehler bei der Treiberansprache -% #define NCB_BootIgnored 4 Booten ignoriert, Ger�t lief schon -% #define NCB_FileNotFound 5 Boot-Image nicht gefunden -% #define NCB_InvalidParam 6 �bergebener Parameter ung�ltig -% #define NCB_DeviceLocked 7 Ein Verbindungsversuch schlug fehl, da das Device schon verwendet wird -% #define NCB_NotSpecifiedParam 8 �bergebener Parameter ist au�erhalb der Spezifikation -retCode = calllib('hvpositionerv2',cmd,varargin{:}); - -codes = {'NCB_TimeOut','NCB_NotConnected','NCB_DriverError','NCB_BootIgnored',... - 'NCB_FileNotFound','NCB_InvalidParam','NCB_DeviceLocked','NCB_NotSpecifiedParam'}; -if retCode == 0 - return; -elseif retCode <= length(codes) - error('Call to library returned with error code %s', codes{retCode}) -else - error('Call to library returned with error code NCB_Error') -end - -function moveANC350(handle,axis,ref,pos) -% @param_in axis: specify either 'x', 'y', 'z' -% @param_in ref: either 'abs' for absolute or 'rel' for relative -% positioning -% @param_in: position or distance, depending on argument ref, -% specified in microns (native unit of the ANP101) -axis = (... - 1 * strcmpi(axis,'z')... - + 2 * strcmpi(axis,'y')... - + 3 * strcmpi(axis,'x')... - ) - 1; - -if strcmp(ref,'abs') - cmd = 'PositionerMoveAbsolute'; -elseif strcmp(ref,'rel') - cmd = 'PositionerMoveRelative'; -else - error('Invalid argument for input argument ''ref''') -end - -pos = int32(pos*1000); -callANC350(cmd,handle,axis,pos); -end - -function val = getANC350(handle,cmd,varargin) -if strcmpi(cmd,'Position') - axis = (... - 1 * strcmpi(varargin{1},'z')... - + 2 * strcmpi(varargin{1},'y')... - + 3 * strcmpi(varargin{1},'x')... - ) - 1; - val = libpointer('int32Ptr', -2^16); - callANC350('PositionerGetPosition',handle,axis,val); - val = val.Value / 1000; - return; -end -end - -function loadParamFile(handle,path) -% load file for each axis, preconfigured such that 0==z, 1==y, -% 2==x -callANC350(self,'PositionerLoad',handle,0,... - [path 'ANPz101res.aps']); -callANC350(self,'PositionerLoad',handle,1,... - [path 'ANPx101res.aps']); -callANC350(self,'PositionerLoad',handle,2,... - [path 'ANPx101res.aps']); -end - -end - - - \ No newline at end of file +function [val, rate] = smcANC350(ico, val, rate, varargin) +global smdata + +if ~libisloaded('hvpositionerv2') + if strcmpi(computer('arch'), 'win64') + libname='hvpositionerv2_ia64'; + else + libname='hvpositionerv2'; + end + loadlibrary([libname '.dll'],[libname '.h'],'alias','hvpositionerv2'); + + posInfo = libstruct('PositionerInfo'); + numDevices = calllib('hvpositionerv2','PositionerCheck',posInfo); + if numDevices < 1 + error('No device detected!') + end + + devHandle = libpointer('int32Ptr', 0); + devNo = int32(0); + % connect to device + callANC350('PositionerConnect',devNo,devHandle); + smdata.inst(ico(1)).data.devHandle = devHandle.Value; + + if ~isempty(smdata.inst(ico(1)).data.paramFile) + loadParamFile(smdata.inst(ico(1)).data.devHandle,... + smdata.inst(ico(1)).data.paramFile); + end +end + +switch ico(3) + case 0 + switch ico(2) + case 1 + val = getANC350(smdata.inst(ico(1)).data.devHandle,... + 'Position','x'); + val = double(val); + case 2 + val = getANC350(smdata.inst(ico(1)).data.devHandle,... + 'Position','y'); + val = double(val); + case 3 + val = getANC350(smdata.inst(ico(1)).data.devHandle,... + 'Position','z'); + val = double(val); + end + + case 1 + switch ico(2) + case 1 + moveANC350(smdata.inst(ico(1)).data.devHandle,'x',... + 'abs', val); + case 2 + moveANC350(smdata.inst(ico(1)).data.devHandle,'y',... + 'abs', val); + case 3 + moveANC350(smdata.inst(ico(1)).data.devHandle,'z',... + 'abs', val); + otherwise + error('Operation not supported!') + end +end +end + +function retCode = callANC350(cmd,varargin) +% R�ckgabewerte der Funktionen +% #define NCB_Ok 0 Kein Fehler +% #define NCB_Error (-1) Unbekannter/sonstiger Fehler +% #define NCB_Timeout 1 Timeout bei Datenabruf +% #define NCB_NotConnected 2 Kein Kontakt zum Positioner �ber USB +% #define NCB_DriverError 3 Fehler bei der Treiberansprache +% #define NCB_BootIgnored 4 Booten ignoriert, Ger�t lief schon +% #define NCB_FileNotFound 5 Boot-Image nicht gefunden +% #define NCB_InvalidParam 6 �bergebener Parameter ung�ltig +% #define NCB_DeviceLocked 7 Ein Verbindungsversuch schlug fehl, da das Device schon verwendet wird +% #define NCB_NotSpecifiedParam 8 �bergebener Parameter ist au�erhalb der Spezifikation +retCode = calllib('hvpositionerv2',cmd,varargin{:}); + +codes = {'NCB_TimeOut','NCB_NotConnected','NCB_DriverError','NCB_BootIgnored',... + 'NCB_FileNotFound','NCB_InvalidParam','NCB_DeviceLocked','NCB_NotSpecifiedParam'}; +if retCode == 0 + return; +elseif retCode <= length(codes) + error('Call to library returned with error code %s', codes{retCode}) +else + error('Call to library returned with error code NCB_Error') +end +end + +function moveANC350(handle,axis,ref,pos) +% @param_in axis: specify either 'x', 'y', 'z' +% @param_in ref: either 'abs' for absolute or 'rel' for relative +% positioning +% @param_in: position or distance, depending on argument ref, +% specified in microns (native unit of the ANP101) +axis = (... + 1 * strcmpi(axis,'z')... + + 2 * strcmpi(axis,'y')... + + 3 * strcmpi(axis,'x')... + ) - 1; + +if strcmp(ref,'abs') + cmd = 'PositionerMoveAbsolute'; +elseif strcmp(ref,'rel') + cmd = 'PositionerMoveRelative'; +else + error('Invalid argument for input argument ''ref''') +end + +pos = int32(pos*1000); +callANC350(cmd,handle,axis,pos); +end + +function val = getANC350(handle,cmd,varargin) +if strcmpi(cmd,'Position') + axis = (... + 1 * strcmpi(varargin{1},'z')... + + 2 * strcmpi(varargin{1},'y')... + + 3 * strcmpi(varargin{1},'x')... + ) - 1; + val = libpointer('int32Ptr', -2^16); + callANC350('PositionerGetPosition',handle,axis,val); + val = val.Value / 1000; + return; +end +end + +function loadParamFile(handle,path) +% load file for each axis, preconfigured such that 0==z, 1==y, +% 2==x +callANC350('PositionerLoad',handle,0,... + [path 'ANPz101res.aps']); +callANC350('PositionerLoad',handle,1,... + [path 'ANPx101res.aps']); +callANC350('PositionerLoad',handle,2,... + [path 'ANPx101res.aps']); +end \ No newline at end of file diff --git a/sm/channels/smcAWG33500B.m b/sm/channels/smcAWG33500B.m index 877c8332607aaf205aeb079ce7b76bddd63175cf..ad2670dbf34d8270760fb2482721a3dbd3a27d88 100644 --- a/sm/channels/smcAWG33500B.m +++ b/sm/channels/smcAWG33500B.m @@ -1,123 +1,123 @@ -function [val, rate] = smcAWG33500B(ic, val, rate, ctrl) -% [val, rate] = smcAWG33500B(ic, val, rate, ctrl) -% Functions: 0 -> sin, 1 -> square, 2 -> triangle, -1 -> unknown (can do more but not -% implemented) - -global smdata; - - -switch ic(2) % Channel - case 1 - switch ic(3) - case 0 % get - val = query(smdata.inst(ic(1)).data.inst, 'SOUR1:FUNC?', '%s\n', '%s'); - if(strcmp(val, 'SIN')) - val = 0; - elseif(strcmp(val, 'SQU')) - val = 1; - elseif(strcmp(val, 'TRI')) - val = 2; - else - val = -1; - end - case 1 % set - if(val == 0) - val = 'SIN'; - elseif(val == 1) - val = 'SQU'; - elseif(val == 2) - val = 'TRI'; - else - error('Function not known!'); - return; - end - fprintf(smdata.inst(ic(1)).data.inst, 'SOUR1:FUNC %s', val); - case 6 - error('Operation not supported'); - end - case 2 - switch ic(3) - case 0 % get - val = query(smdata.inst(ic(1)).data.inst, 'SOUR2:FUNC?', '%s\n', '%s'); - if(strcmp(val, 'SIN')) - val = 0; - elseif(strcmp(val, 'SQU')) - val = 1; - elseif(strcmp(val, 'TRI')) - val = 2; - else - val = -1; - end - case 1 % set - if(val == 0) - val = 'SIN'; - elseif(val == 1) - val = 'SQU'; - elseif(val == 2) - val = 'TRI'; - else - error('Function not known!'); - return; - end - fprintf(smdata.inst(ic(1)).data.inst, 'SOUR2:FUNC %s', val); - end - case 3 - switch ic(3) - case 0 % get - val = query(smdata.inst(ic(1)).data.inst, 'SOUR1:VOLT?', '%s\n', '%f'); - case 1 % set - fprintf(smdata.inst(ic(1)).data.inst, 'SOUR1:VOLT %f', val); - end - case 4 - switch ic(3) - case 0 % get - val = query(smdata.inst(ic(1)).data.inst, 'SOUR2:VOLT?', '%s\n', '%f'); - case 1 % set - fprintf(smdata.inst(ic(1)).data.inst, 'SOUR2:VOLT %f', val); - end - case 5 - switch ic(3) - case 0 % get - val = query(smdata.inst(ic(1)).data.inst, 'SOUR1:FREQ?', '%s\n', '%f'); - case 1 % set - fprintf(smdata.inst(ic(1)).data.inst, 'SOUR1:FREQ %f', val); - end - case 6 - switch ic(3) - case 0 % get - val = query(smdata.inst(ic(1)).data.inst, 'SOUR2:FREQ?', '%s\n', '%f'); - case 1 % set - fprintf(smdata.inst(ic(1)).data.inst, 'SOUR2:FREQ %f', val); - end - case 7 - switch ic(3) - case 0 % get - val = query(smdata.inst(ic(1)).data.inst, 'SOUR1:PHAS?', '%s\n', '%f'); - case 1 % set - fprintf(smdata.inst(ic(1)).data.inst, 'SOUR1:PHAS %f', val); - end - case 8 - switch ic(3) - case 0 % get - val = query(smdata.inst(ic(1)).data.inst, 'SOUR2:PHAS?', '%s\n', '%f'); - case 1 % set - fprintf(smdata.inst(ic(1)).data.inst, 'SOUR2:PHAS %f', val); - end - case 9 - switch ic(3) - case 0 % get - val = query(smdata.inst(ic(1)).data.inst, 'OUTP1:LOAD?', '%s\n', '%f'); - case 1 % set - - end - case 10 - switch ic(3) - case 0 % get - val = query(smdata.inst(ic(1)).data.inst, 'OUTP2:LOAD?', '%s\n', '%f'); - case 1 % set - - end - - otherwise - error('Operation not supported'); +function [val, rate] = smcAWG33500B(ic, val, rate, ctrl) +% [val, rate] = smcAWG33500B(ic, val, rate, ctrl) +% Functions: 0 -> sin, 1 -> square, 2 -> triangle, -1 -> unknown (can do more but not +% implemented) + +global smdata; + + +switch ic(2) % Channel + case 1 + switch ic(3) + case 0 % get + val = query(smdata.inst(ic(1)).data.inst, 'SOUR1:FUNC?', '%s\n', '%s'); + if(strcmp(val, 'SIN')) + val = 0; + elseif(strcmp(val, 'SQU')) + val = 1; + elseif(strcmp(val, 'TRI')) + val = 2; + else + val = -1; + end + case 1 % set + if(val == 0) + val = 'SIN'; + elseif(val == 1) + val = 'SQU'; + elseif(val == 2) + val = 'TRI'; + else + error('Function not known!'); + return; + end + fprintf(smdata.inst(ic(1)).data.inst, 'SOUR1:FUNC %s', val); + case 6 + error('Operation not supported'); + end + case 2 + switch ic(3) + case 0 % get + val = query(smdata.inst(ic(1)).data.inst, 'SOUR2:FUNC?', '%s\n', '%s'); + if(strcmp(val, 'SIN')) + val = 0; + elseif(strcmp(val, 'SQU')) + val = 1; + elseif(strcmp(val, 'TRI')) + val = 2; + else + val = -1; + end + case 1 % set + if(val == 0) + val = 'SIN'; + elseif(val == 1) + val = 'SQU'; + elseif(val == 2) + val = 'TRI'; + else + error('Function not known!'); + return; + end + fprintf(smdata.inst(ic(1)).data.inst, 'SOUR2:FUNC %s', val); + end + case 3 + switch ic(3) + case 0 % get + val = query(smdata.inst(ic(1)).data.inst, 'SOUR1:VOLT?', '%s\n', '%f'); + case 1 % set + fprintf(smdata.inst(ic(1)).data.inst, 'SOUR1:VOLT %f', val); + end + case 4 + switch ic(3) + case 0 % get + val = query(smdata.inst(ic(1)).data.inst, 'SOUR2:VOLT?', '%s\n', '%f'); + case 1 % set + fprintf(smdata.inst(ic(1)).data.inst, 'SOUR2:VOLT %f', val); + end + case 5 + switch ic(3) + case 0 % get + val = query(smdata.inst(ic(1)).data.inst, 'SOUR1:FREQ?', '%s\n', '%f'); + case 1 % set + fprintf(smdata.inst(ic(1)).data.inst, 'SOUR1:FREQ %f', val); + end + case 6 + switch ic(3) + case 0 % get + val = query(smdata.inst(ic(1)).data.inst, 'SOUR2:FREQ?', '%s\n', '%f'); + case 1 % set + fprintf(smdata.inst(ic(1)).data.inst, 'SOUR2:FREQ %f', val); + end + case 7 + switch ic(3) + case 0 % get + val = query(smdata.inst(ic(1)).data.inst, 'SOUR1:PHAS?', '%s\n', '%f'); + case 1 % set + fprintf(smdata.inst(ic(1)).data.inst, 'SOUR1:PHAS %f', val); + end + case 8 + switch ic(3) + case 0 % get + val = query(smdata.inst(ic(1)).data.inst, 'SOUR2:PHAS?', '%s\n', '%f'); + case 1 % set + fprintf(smdata.inst(ic(1)).data.inst, 'SOUR2:PHAS %f', val); + end + case 9 + switch ic(3) + case 0 % get + val = query(smdata.inst(ic(1)).data.inst, 'OUTP1:LOAD?', '%s\n', '%f'); + case 1 % set + + end + case 10 + switch ic(3) + case 0 % get + val = query(smdata.inst(ic(1)).data.inst, 'OUTP2:LOAD?', '%s\n', '%f'); + case 1 % set + + end + + otherwise + error('Operation not supported'); end \ No newline at end of file diff --git a/sm/channels/smcDMM34410A.m b/sm/channels/smcDMM34410A.m index a072d6afe38975a127631182060668a307480e49..cee3a6e335b6d9a2d6a8c154bc990007d8ae49d3 100644 --- a/sm/channels/smcDMM34410A.m +++ b/sm/channels/smcDMM34410A.m @@ -1,99 +1,99 @@ -function [val, rate] = smcdmm(ico, val, rate) -% driver for Agilent DMMs with support for buffered readout. -% mainly configured for voltage readings; needs small additions here and -% there for other modes -% for use with the 34401A the commands need to be changed slightly. Some for the 34410A optional -% parameters are necessary. -global smdata; - -switch ico(2) % channel - case 1 - switch ico(3) - case 0 %get - val = query(smdata.inst(ico(1)).data.inst, 'READ?', '%s\n', '%f'); - - otherwise - error('Operation not supported'); - end - - case 2 - switch ico(3) - case 0 - % this blocks until all values are available - val = sscanf(query(smdata.inst(ico(1)).data.inst, 'FETCH?'), '%f,')'; - - case 3 %trigger - pause(smdata.inst(ico(1)).data.trigDelay); - trigger(smdata.inst(ico(1)).data.inst); - - case 4 % arm instrument - fprintf(smdata.inst(ico(1)).data.inst, 'INIT'); - - case 5 % configure instrument - % set range - fprintf(smdata.inst(ico(1)).data.inst, 'SENS:VOLT:RANG:AUTO 0'); - fprintf(smdata.inst(ico(1)).data.inst, 'SENS:VOLT:RANG %i',... - smdata.inst(ico(1)).data.vrng); - - % possible nplc with the 34410A - % {0.006|0.02|0.06|0.2|1|2|10|100} - % the 34401A cannot measure as fast, only 0.02 - % MIN = 0.006 PLC, - % MAX = 100 PLC - bNplc = isfield(smdata.inst(ico(1)).data, 'nplc') && ... - ~isempty(smdata.inst(ico(1)).data.nplc); - if bNplc - nplc = smdata.inst(ico(1)).data.nplc; - fprintf(smdata.inst(ico(1)).data.inst, 'VOLT:NPLC %f', nplc); - fprintf(smdata.inst(ico(1)).data.inst, 'CURR:NPLC %f', nplc); - maxrate = ... - 50/str2double(query(smdata.inst(ico(1)).data.inst, 'VOLT:NPLC?')); - end - - % possible apertures with the 34410A - % ~100 �s to ~1 s (with ~20 �s resolution). - % MIN = ~100 �s, MAX = ~1 s - bAper = isfield(smdata.inst(ico(1)).data, 'aper') && ... - ~isempty(smdata.inst(ico(1)).data.aper); - if bAper - aper = smdata.inst(ico(1)).data.aper; - fprintf(smdata.inst(ico(1)).data.inst, 'VOLT:APER:ENAB ON'); - fprintf(smdata.inst(ico(1)).data.inst, 'CURR:APER:ENAB ON'); - fprintf(smdata.inst(ico(1)).data.inst, 'VOLT:APER %f', aper); - fprintf(smdata.inst(ico(1)).data.inst, 'CURR:APER %f', aper); - maxrate = ... - 1*str2double(query(smdata.inst(ico(1)).data.inst, 'VOLT:APER?')); - end - - if bAper && bNplc - warning('Both aperture and nplc are set. Took aperture for determination of integration time.') - end - - % set measurement type to be with timed intervals - fprintf(smdata.inst(ico(1)).data.inst, 'SAMP:SOUR TIM'); - % the theoretical maxrate is not the actual maxrate. the - % actual maxrate is approx. a factor 2 slower. - if rate > maxrate - rate = maxrate; - warning('Rate set to maxrate.') - end - - rmptime = 1/rate - % sets the timer interval. - fprintf(smdata.inst(ico(1)).data.inst, 'SAMP:TIM %f', rmptime); - fprintf(smdata.inst(ico(1)).data.inst, 'TRIG:DEL 0.0'); - - % hardcoded for 34410A - % for 34401A this value would be 500 - if val > 50000 - error('More than allowed number of samples requested. Correct and try again!\n'); - end - fprintf(smdata.inst(ico(1)).data.inst, 'TRIG:SOUR BUS'); - fprintf(smdata.inst(ico(1)).data.inst, 'TRIG:COUN %i', 1); - fprintf(smdata.inst(ico(1)).data.inst, 'SAMP:COUN %d', val); - smdata.inst(ico(1)).datadim(2,1) = val; - - otherwise - error('Operation not supported'); - end +function [val, rate] = smcdmm(ico, val, rate) +% driver for Agilent DMMs with support for buffered readout. +% mainly configured for voltage readings; needs small additions here and +% there for other modes +% for use with the 34401A the commands need to be changed slightly. Some for the 34410A optional +% parameters are necessary. +global smdata; + +switch ico(2) % channel + case 1 + switch ico(3) + case 0 %get + val = query(smdata.inst(ico(1)).data.inst, 'READ?', '%s\n', '%f'); + + otherwise + error('Operation not supported'); + end + + case 2 + switch ico(3) + case 0 + % this blocks until all values are available + val = sscanf(query(smdata.inst(ico(1)).data.inst, 'FETCH?'), '%f,')'; + + case 3 %trigger + pause(smdata.inst(ico(1)).data.trigDelay); + trigger(smdata.inst(ico(1)).data.inst); + + case 4 % arm instrument + fprintf(smdata.inst(ico(1)).data.inst, 'INIT'); + + case 5 % configure instrument + % set range + fprintf(smdata.inst(ico(1)).data.inst, 'SENS:VOLT:RANG:AUTO 0'); + fprintf(smdata.inst(ico(1)).data.inst, 'SENS:VOLT:RANG %i',... + smdata.inst(ico(1)).data.vrng); + + % possible nplc with the 34410A + % {0.006|0.02|0.06|0.2|1|2|10|100} + % the 34401A cannot measure as fast, only 0.02 + % MIN = 0.006 PLC, + % MAX = 100 PLC + bNplc = isfield(smdata.inst(ico(1)).data, 'nplc') && ... + ~isempty(smdata.inst(ico(1)).data.nplc); + if bNplc + nplc = smdata.inst(ico(1)).data.nplc; + fprintf(smdata.inst(ico(1)).data.inst, 'VOLT:NPLC %f', nplc); + fprintf(smdata.inst(ico(1)).data.inst, 'CURR:NPLC %f', nplc); + maxrate = ... + 50/str2double(query(smdata.inst(ico(1)).data.inst, 'VOLT:NPLC?')); + end + + % possible apertures with the 34410A + % ~100 �s to ~1 s (with ~20 �s resolution). + % MIN = ~100 �s, MAX = ~1 s + bAper = isfield(smdata.inst(ico(1)).data, 'aper') && ... + ~isempty(smdata.inst(ico(1)).data.aper); + if bAper + aper = smdata.inst(ico(1)).data.aper; + fprintf(smdata.inst(ico(1)).data.inst, 'VOLT:APER:ENAB ON'); + fprintf(smdata.inst(ico(1)).data.inst, 'CURR:APER:ENAB ON'); + fprintf(smdata.inst(ico(1)).data.inst, 'VOLT:APER %f', aper); + fprintf(smdata.inst(ico(1)).data.inst, 'CURR:APER %f', aper); + maxrate = ... + 1*str2double(query(smdata.inst(ico(1)).data.inst, 'VOLT:APER?')); + end + + if bAper && bNplc + warning('Both aperture and nplc are set. Took aperture for determination of integration time.') + end + + % set measurement type to be with timed intervals + fprintf(smdata.inst(ico(1)).data.inst, 'SAMP:SOUR TIM'); + % the theoretical maxrate is not the actual maxrate. the + % actual maxrate is approx. a factor 2 slower. + if rate > maxrate + rate = maxrate; + warning('Rate set to maxrate.') + end + + rmptime = 1/rate + % sets the timer interval. + fprintf(smdata.inst(ico(1)).data.inst, 'SAMP:TIM %f', rmptime); + fprintf(smdata.inst(ico(1)).data.inst, 'TRIG:DEL 0.0'); + + % hardcoded for 34410A + % for 34401A this value would be 500 + if val > 50000 + error('More than allowed number of samples requested. Correct and try again!\n'); + end + fprintf(smdata.inst(ico(1)).data.inst, 'TRIG:SOUR BUS'); + fprintf(smdata.inst(ico(1)).data.inst, 'TRIG:COUN %i', 1); + fprintf(smdata.inst(ico(1)).data.inst, 'SAMP:COUN %d', val); + smdata.inst(ico(1)).datadim(2,1) = val; + + otherwise + error('Operation not supported'); + end end \ No newline at end of file diff --git a/sm/channels/smcHP8350B.m b/sm/channels/smcHP8350B.m index 95c83472a9a515a22a27fabf3cb130699b57657e..80a587b53af1ce631b09c3d1bd9c6ecbc200cbc0 100644 --- a/sm/channels/smcHP8350B.m +++ b/sm/channels/smcHP8350B.m @@ -1,18 +1,3 @@ -function val = smcHP8350B(ic, val, rate) -% 1: freq, 2: power -% units are Hz and dBm - -global smdata; - -cmds = {'CW', 'PL'}; -units = {'HZ', 'DM'}; - -switch ic(3) - case 1 - fprintf(smdata.inst(ic(1)).data.inst, sprintf('%s %f %s', cmds{ic(2)}, val, units{ic(2)})); - case 0 - val = query(smdata.inst(ic(1)).data.inst, sprintf('OP %s', cmds{ic(2)}), '%s\n', '%f'); -======= function val = smcHP8350B(ic, val, rate, varargin) % 1 CW CWFreqency % 2 PL PowerLevel @@ -37,7 +22,7 @@ switch ic(3) sprintf('OP %s', cmds{ic(2)}), '%s\n', '%f'); case 1 - switch ic(2) + switch ic(2) case 5 %check for on/off operation fprintf(smdata.inst(ic(1)).data.inst,... sprintf('%s%i', cmds{ic(2)}, val)); diff --git a/sm/channels/smcKeithley2400.m b/sm/channels/smcKeithley2400.m index 73d291ac8f87383e8734137c8528e56546c42162..2ca833d2f9b96359227431dae3636c19456150a6 100644 --- a/sm/channels/smcKeithley2400.m +++ b/sm/channels/smcKeithley2400.m @@ -1,135 +1,135 @@ -function [val, rate] = smcKeithley2400(ico, val, rate) -% driver for Keithley 2400 SourceMeter -% currently just to supply and monitor components, experimental & incomlete -% SMCKEITHLEY2400([ico(1) ico(2) ico(3)] val, rate) -% ico(1): instrument number in rack -% ico(2): channel on instrument 1 =VOLT -% 2 =CURRENT, -% 3 =COMPLIANCE -% 4 =ISSOURCEVOLT -% 5 =OUTPUTON -% ico(3): 0=read, 1=write(, 3=trig, 4=bufferreset, 5=sweepsetup) - -% measurement range is determined by instrument, presumebly slow -% no ramps/triggering implimented, consult smcdmm.m -% no ... -% only dc voltage/current measure/source -% written by eugen.kammerloher@rwth-aachen.de - -global smdata; - -switch ico(2) - case 1 % measure voltage or set constant voltage source - switch ico(3) - case 0 - % slow but simple - fprintf(smdata.inst(ico(1)).data.inst, ':SENS:VOLT:RANG:AUTO ON'); - % set remote output format to voltage only - fprintf(smdata.inst(ico(1)).data.inst, ':FORM:ELEM VOLT'); - val = query(smdata.inst(ico(1)).data.inst, ':READ?', '%s\n', '%f'); - - case 1 - fprintf(smdata.inst(ico(1)).data.inst, ':SOUR:FUNC VOLT'); - fprintf(smdata.inst(ico(1)).data.inst, ':SOUR:VOLT:MODE FIXED'); - fprintf(smdata.inst(ico(1)).data.inst, ':SOUR:VOLT:LEV %f', val); - - otherwise - error('Operation not supported'); - end - - case 2 % measure current or set constant current on source - switch ico(3) - case 0 - % slow but simple - fprintf(smdata.inst(ico(1)).data.inst, ':SENS:CURR:RANG:AUTO ON'); - % set remote output format to current only - fprintf(smdata.inst(ico(1)).data.inst, ':FORM:ELEM CURR'); - val = query(smdata.inst(ico(1)).data.inst, 'READ?', '%s\n', '%f'); - - case 1 - fprintf(smdata.inst(ico(1)).data.inst, ':SOUR:FUNC CURR'); - fprintf(smdata.inst(ico(1)).data.inst, ':SOUR:CURR:MODE FIXED'); - fprintf(smdata.inst(ico(1)).data.inst, ':SOUR:CURR:LEV %f', val); - - otherwise - error('Operation not supported'); - end - - case 3 % get real compliance as minimum of measuring range and compliance value. Set compliance - switch ico(3) - case 0 - source = query(smdata.inst(ico(1)).data.inst, ':SOUR:FUNC?', '%s\n', '%s'); - if strcmp(source, 'VOLT') - sense = 'CURR'; - else - sense = 'VOLT'; - end - - % Query measurement range, compliance limit - range = query(smdata.inst(ico(1)).data.inst, [':' sense ':RANGE?'], '%s\n', '%f'); - prot = query(smdata.inst(ico(1)).data.inst, [':' sense ':PROT?'], '%s\n', '%f'); - - % Take the smaller one as compliance readback - val = min(range, prot); - - case 1 % does not work for ohm - source = query(smdata.inst(ico(1)).data.inst, ':SOUR:FUNC?', '%s\n', '%s'); - if strcmp(source, 'VOLT') - sense = 'CURR'; - else - sense = 'VOLT'; - end - - % sometimes too small for sense range error, reason unknown - % range auto on should set compliance independently from - % sense range - fprintf(smdata.inst(ico(1)).data.inst, [':SOUR:' source ':RANG:AUTO ON']); - fprintf(smdata.inst(ico(1)).data.inst, [':' sense ':PROT %f'], val); - - otherwise - error('Operation not supported'); - end - - case 4 % get 1 if sourcing voltage. Set 1 to source voltage (0 for current) - switch ico(3) - case 0 % instrument outputs VOLT, CURR - val = query(smdata.inst(ico(1)).data.inst, ':SOUR:FUNC?', '%s\n', '%s'); - if strcmp(val, 'VOLT') - val = 1; - else - val = 0; - end - - case 1 - if val == 1 - cmd = 'VOLT'; - else - cmd = 'CURR'; - end - fprintf(smdata.inst(ico(1)).data.inst, ':SOUR:FUNC %s', cmd); - - otherwise - error('Operation not supported'); - end - - case 5 % get 1 if output is on. Set 1 to set output on (0 for off) - switch ico(3) - case 0 % instruments outputs 1 for ON, 0 for OFF - val = query(smdata.inst(ico(1)).data.inst, ':OUTP:STAT?', '%s\n', '%d'); - - case 1 - if (val == 1) - cmd = 'ON'; - else - cmd = 'OFF'; - end - fprintf(smdata.inst(ico(1)).data.inst, ':OUTP:STAT %s', cmd); - - otherwise - error('Operation not supported'); - end - - otherwise - %error('Operation not supported'); - error(['Channel ', num2str(ico(2)) ,' is not available']); -end +function [val, rate] = smcKeithley2400(ico, val, rate) +% driver for Keithley 2400 SourceMeter +% currently just to supply and monitor components, experimental & incomlete +% SMCKEITHLEY2400([ico(1) ico(2) ico(3)] val, rate) +% ico(1): instrument number in rack +% ico(2): channel on instrument 1 =VOLT +% 2 =CURRENT, +% 3 =COMPLIANCE +% 4 =ISSOURCEVOLT +% 5 =OUTPUTON +% ico(3): 0=read, 1=write(, 3=trig, 4=bufferreset, 5=sweepsetup) + +% measurement range is determined by instrument, presumebly slow +% no ramps/triggering implimented, consult smcdmm.m +% no ... +% only dc voltage/current measure/source +% written by eugen.kammerloher@rwth-aachen.de + +global smdata; + +switch ico(2) + case 1 % measure voltage or set constant voltage source + switch ico(3) + case 0 + % slow but simple + fprintf(smdata.inst(ico(1)).data.inst, ':SENS:VOLT:RANG:AUTO ON'); + % set remote output format to voltage only + fprintf(smdata.inst(ico(1)).data.inst, ':FORM:ELEM VOLT'); + val = query(smdata.inst(ico(1)).data.inst, ':READ?', '%s\n', '%f'); + + case 1 + fprintf(smdata.inst(ico(1)).data.inst, ':SOUR:FUNC VOLT'); + fprintf(smdata.inst(ico(1)).data.inst, ':SOUR:VOLT:MODE FIXED'); + fprintf(smdata.inst(ico(1)).data.inst, ':SOUR:VOLT:LEV %f', val); + + otherwise + error('Operation not supported'); + end + + case 2 % measure current or set constant current on source + switch ico(3) + case 0 + % slow but simple + fprintf(smdata.inst(ico(1)).data.inst, ':SENS:CURR:RANG:AUTO ON'); + % set remote output format to current only + fprintf(smdata.inst(ico(1)).data.inst, ':FORM:ELEM CURR'); + val = query(smdata.inst(ico(1)).data.inst, 'READ?', '%s\n', '%f'); + + case 1 + fprintf(smdata.inst(ico(1)).data.inst, ':SOUR:FUNC CURR'); + fprintf(smdata.inst(ico(1)).data.inst, ':SOUR:CURR:MODE FIXED'); + fprintf(smdata.inst(ico(1)).data.inst, ':SOUR:CURR:LEV %f', val); + + otherwise + error('Operation not supported'); + end + + case 3 % get real compliance as minimum of measuring range and compliance value. Set compliance + switch ico(3) + case 0 + source = query(smdata.inst(ico(1)).data.inst, ':SOUR:FUNC?', '%s\n', '%s'); + if strcmp(source, 'VOLT') + sense = 'CURR'; + else + sense = 'VOLT'; + end + + % Query measurement range, compliance limit + range = query(smdata.inst(ico(1)).data.inst, [':' sense ':RANGE?'], '%s\n', '%f'); + prot = query(smdata.inst(ico(1)).data.inst, [':' sense ':PROT?'], '%s\n', '%f'); + + % Take the smaller one as compliance readback + val = min(range, prot); + + case 1 % does not work for ohm + source = query(smdata.inst(ico(1)).data.inst, ':SOUR:FUNC?', '%s\n', '%s'); + if strcmp(source, 'VOLT') + sense = 'CURR'; + else + sense = 'VOLT'; + end + + % sometimes too small for sense range error, reason unknown + % range auto on should set compliance independently from + % sense range + fprintf(smdata.inst(ico(1)).data.inst, [':SOUR:' source ':RANG:AUTO ON']); + fprintf(smdata.inst(ico(1)).data.inst, [':' sense ':PROT %f'], val); + + otherwise + error('Operation not supported'); + end + + case 4 % get 1 if sourcing voltage. Set 1 to source voltage (0 for current) + switch ico(3) + case 0 % instrument outputs VOLT, CURR + val = query(smdata.inst(ico(1)).data.inst, ':SOUR:FUNC?', '%s\n', '%s'); + if strcmp(val, 'VOLT') + val = 1; + else + val = 0; + end + + case 1 + if val == 1 + cmd = 'VOLT'; + else + cmd = 'CURR'; + end + fprintf(smdata.inst(ico(1)).data.inst, ':SOUR:FUNC %s', cmd); + + otherwise + error('Operation not supported'); + end + + case 5 % get 1 if output is on. Set 1 to set output on (0 for off) + switch ico(3) + case 0 % instruments outputs 1 for ON, 0 for OFF + val = query(smdata.inst(ico(1)).data.inst, ':OUTP:STAT?', '%s\n', '%d'); + + case 1 + if (val == 1) + cmd = 'ON'; + else + cmd = 'OFF'; + end + fprintf(smdata.inst(ico(1)).data.inst, ':OUTP:STAT %s', cmd); + + otherwise + error('Operation not supported'); + end + + otherwise + %error('Operation not supported'); + error(['Channel ', num2str(ico(2)) ,' is not available']); +end diff --git a/sm/channels/smcKeysight34410A.m b/sm/channels/smcKeysight34410A.m index 1a1ef91fcddb2a5179a7c2415a8cf0f79371ffaf..9c1e91f68ca5ba6214e8ae48e2bbbba2e8508477 100644 --- a/sm/channels/smcKeysight34410A.m +++ b/sm/channels/smcKeysight34410A.m @@ -1,90 +1,90 @@ -function [val, rate] = smcdmm(ico, val, rate) -% driver for Agilent DMMs with support for buffered readout. -% mainly configured for voltage readings; needs small additions here and -% there for other modes -global smdata; - -switch ico(2) % channel - case 1 - switch ico(3) - case 0 %get - val = query(smdata.inst(ico(1)).data.inst, 'READ?', '%s\n', '%f'); - - otherwise - error('Operation not supported'); - end - - case 2 - switch ico(3) - case 0 - % this blocks until all values are available - val = sscanf(query(smdata.inst(ico(1)).data.inst, 'FETCH?'), '%f,')'; - - case 3 %trigger - pause(smdata.inst(ico(1)).data.trigDelay); - trigger(smdata.inst(ico(1)).data.inst); - - case 4 % arm instrument - fprintf(smdata.inst(ico(1)).data.inst, 'INIT'); - - case 5 % configure instrument - % set range - fprintf(smdata.inst(ico(1)).data.inst, 'SENS:VOLT:RANG:AUTO 0'); - fprintf(smdata.inst(ico(1)).data.inst, 'SENS:VOLT:RANG %i',... - smdata.inst(ico(1)).data.vrng); - - % possible nplc with the 34410A - % {0.006|0.02|0.06|0.2|1|2|10|100} - % MIN = 0.006 PLC, - % MAX = 100 PLC - bNplc = isfield(smdata.inst(ico(1)).data, 'nplc') && ... - ~isempty(smdata.inst(ico(1)).data.nplc); - if bNplc - nplc = smdata.inst(ico(1)).data.nplc; - fprintf(smdata.inst(ico(1)).data.inst, 'VOLT:NPLC %f', nplc); - fprintf(smdata.inst(ico(1)).data.inst, 'CURR:NPLC %f', nplc); - maxrate = ... - 50*str2double(query(smdata.inst(ico(1)).data.inst, 'VOLT:NPLC?')); - end - - % possible apertures with the 34410A - % ~100 �s to ~1 s (with ~20 �s resolution). - % MIN = ~100 �s, MAX = ~1 s - bAper = isfield(smdata.inst(ico(1)).data, 'aper') && ... - ~isempty(smdata.inst(ico(1)).data.aper); - if bAper - aper = smdata.inst(ico(1)).data.aper; - fprintf(smdata.inst(ico(1)).data.inst, 'VOLT:APER:ENAB ON'); - fprintf(smdata.inst(ico(1)).data.inst, 'CURR:APER:ENAB ON'); - fprintf(smdata.inst(ico(1)).data.inst, 'VOLT:APER %f', aper); - fprintf(smdata.inst(ico(1)).data.inst, 'CURR:APER %f', aper); - maxrate = ... - 1/str2double(query(smdata.inst(ico(1)).data.inst, 'VOLT:APER?')); - end - - if bAper && bNplc - warning('Both aperture and nplc are set. Took aperture for determination of integration time.') - end - - fprintf(smdata.inst(ico(1)).data.inst, 'SAMP:SOUR IMM'); - if rate > maxrate - rate = maxrate; - warning('Rate set to maxrate.') - end - - delay = 1/rate - 1/maxrate; - fprintf(smdata.inst(ico(1)).data.inst, 'TRIG:DEL %f', delay); - - % hardcoded for 34410A - if val > 50000 - error('More than allowed number of samples requested. Correct and try again!\n'); - end - fprintf(smdata.inst(ico(1)).data.inst, 'TRIG:SOUR BUS'); - fprintf(smdata.inst(ico(1)).data.inst, 'TRIG:COUN %i', 1); - fprintf(smdata.inst(ico(1)).data.inst, 'SAMP:COUN %d', val); - smdata.inst(ico(1)).datadim(2,1) = val; - - otherwise - error('Operation not supported'); - end +function [val, rate] = smcdmm(ico, val, rate) +% driver for Agilent DMMs with support for buffered readout. +% mainly configured for voltage readings; needs small additions here and +% there for other modes +global smdata; + +switch ico(2) % channel + case 1 + switch ico(3) + case 0 %get + val = query(smdata.inst(ico(1)).data.inst, 'READ?', '%s\n', '%f'); + + otherwise + error('Operation not supported'); + end + + case 2 + switch ico(3) + case 0 + % this blocks until all values are available + val = sscanf(query(smdata.inst(ico(1)).data.inst, 'FETCH?'), '%f,')'; + + case 3 %trigger + pause(smdata.inst(ico(1)).data.trigDelay); + trigger(smdata.inst(ico(1)).data.inst); + + case 4 % arm instrument + fprintf(smdata.inst(ico(1)).data.inst, 'INIT'); + + case 5 % configure instrument + % set range + fprintf(smdata.inst(ico(1)).data.inst, 'SENS:VOLT:RANG:AUTO 0'); + fprintf(smdata.inst(ico(1)).data.inst, 'SENS:VOLT:RANG %i',... + smdata.inst(ico(1)).data.vrng); + + % possible nplc with the 34410A + % {0.006|0.02|0.06|0.2|1|2|10|100} + % MIN = 0.006 PLC, + % MAX = 100 PLC + bNplc = isfield(smdata.inst(ico(1)).data, 'nplc') && ... + ~isempty(smdata.inst(ico(1)).data.nplc); + if bNplc + nplc = smdata.inst(ico(1)).data.nplc; + fprintf(smdata.inst(ico(1)).data.inst, 'VOLT:NPLC %f', nplc); + fprintf(smdata.inst(ico(1)).data.inst, 'CURR:NPLC %f', nplc); + maxrate = ... + 50*str2double(query(smdata.inst(ico(1)).data.inst, 'VOLT:NPLC?')); + end + + % possible apertures with the 34410A + % ~100 �s to ~1 s (with ~20 �s resolution). + % MIN = ~100 �s, MAX = ~1 s + bAper = isfield(smdata.inst(ico(1)).data, 'aper') && ... + ~isempty(smdata.inst(ico(1)).data.aper); + if bAper + aper = smdata.inst(ico(1)).data.aper; + fprintf(smdata.inst(ico(1)).data.inst, 'VOLT:APER:ENAB ON'); + fprintf(smdata.inst(ico(1)).data.inst, 'CURR:APER:ENAB ON'); + fprintf(smdata.inst(ico(1)).data.inst, 'VOLT:APER %f', aper); + fprintf(smdata.inst(ico(1)).data.inst, 'CURR:APER %f', aper); + maxrate = ... + 1/str2double(query(smdata.inst(ico(1)).data.inst, 'VOLT:APER?')); + end + + if bAper && bNplc + warning('Both aperture and nplc are set. Took aperture for determination of integration time.') + end + + fprintf(smdata.inst(ico(1)).data.inst, 'SAMP:SOUR IMM'); + if rate > maxrate + rate = maxrate; + warning('Rate set to maxrate.') + end + + delay = 1/rate - 1/maxrate; + fprintf(smdata.inst(ico(1)).data.inst, 'TRIG:DEL %f', delay); + + % hardcoded for 34410A + if val > 50000 + error('More than allowed number of samples requested. Correct and try again!\n'); + end + fprintf(smdata.inst(ico(1)).data.inst, 'TRIG:SOUR BUS'); + fprintf(smdata.inst(ico(1)).data.inst, 'TRIG:COUN %i', 1); + fprintf(smdata.inst(ico(1)).data.inst, 'SAMP:COUN %d', val); + smdata.inst(ico(1)).datadim(2,1) = val; + + otherwise + error('Operation not supported'); + end end \ No newline at end of file diff --git a/sm/channels/smcNIDAQmx.m b/sm/channels/smcNIDAQmx.m deleted file mode 100755 index 319e7bb08624b15cd2c7dca193163ed314e11faf..0000000000000000000000000000000000000000 --- a/sm/channels/smcNIDAQmx.m +++ /dev/null @@ -1,339 +0,0 @@ -function [val, rate] = smcNIDAQmx(ico, val, rate) -global smdata -% little workaround because of the session interface -wrapper = @(varargin) varargin; - -% workaround; better ideas are always welcome -COLLCHANS = smdata.inst(ico(1)).type == 2; -if length(ico) > 3 - COLLCHANS = ico(2:end-1); - ico(2) = 0; - ico(3) = ico(end); - ico(4:end) = []; - rate = rate ( find (abs(rate) == min (abs (rate)), 1) ); -end - -switch ico(3) - case 0 %Read - ch = strtrim (smdata.inst(ico(1)).channels(ico(2),:) ); - - %Add channel DEPRECATED -% try smdata.inst(ico(1)).data.input.addAnalogInputChannel(... -% smdata.inst(ico(1)).data.id,... -% ch,... -% 'Voltage'... -% ); -% catch err -% errStr = 'NI: The channel ''ai([0-9]|([1-2][0-9])|(3[01]))'' cannot be added to the session because it has been added previously.'; -% if ~regexp (err.message, errStr, 'ONCE') -% rethrow(err); -% end -% end - - switch ico(2) - case num2cell(1:32) %analog inputs - chanlist = wrapper (smdata.inst(ico(1)).data.input.Channels.ID); - ind = strcmp (ch, chanlist); - downsamp = smdata.inst(ico(1)).data.downsamp; - nsamp = smdata.inst(ico(1)).datadim(ico(2), 1); - - while (smdata.inst(ico(1)).data.input.IsRunning && ... - ~smdata.inst(ico(1)).data.input.IsDone) - smdata.inst(ico(1)).data.input.wait; -% fprintf('running...\n'); - end - - if (nsamp > 1 || downsamp > 1) %buffered readout - if smdata.inst(ico(1)).data.input.IsDone - val = smdata.inst(ico(1)).data.buf(:, ind); - if downsamp > 1 - val = mean(reshape(val(1:downsamp*nsamp), downsamp, nsamp)); - end - else - error('Wait for DataAvailable failed!') - end - else %just read current value - val = smdata.inst(ico(1)).data.input.inputSingleScan(); - val = val(ind); - end - - case num2cell(33:36) %analog outputs - chanlist = wrapper (smdata.inst(ico(1)).data.output.Channels.ID); - ind = strcmp (ch, chanlist); - val = smdata.inst(ico(1)).data.currentOutput(ind); - - case num2cell(37:51) %pfi0-pfi14 - chanlist = wrapper (smdata.inst(ico(1)).data.digital.Channels.ID); - ind = strcmp (ch, chanlist); - val = smdata.inst(ico(1)).data.currentDigitalOutput(ind); - - otherwise - error('Channel not (yet?) configured for readout!') - end - - case 1 %Set/Ramp - switch ico(2) - case {0, 33, 34, 35, 36} %{collective, ao0, ao1, ao2, ao3} - % if not all outputs are set, just set specified outputs and leave - % the rest as is - chans = smdata.inst(ico(1)).channels(COLLCHANS, :); - chans = arrayfun (@(x) strtrim(chans(x, 1:end)),... - 1:size(chans, 1),... - 'UniformOutput', false... - ); - if ico(2) == 0 - for ch = 1:length(smdata.inst(ico(1)).data.currentOutput) - tmp = val(... - strcmp (chans, smdata.inst(ico(1)).data.output.Channels(ch).ID)... - ); - if isempty(tmp) - queue(ch) = smdata.inst(ico(1)).data.currentOutput(ch); - else - queue(ch) = tmp; - end - end - else - queue = smdata.inst(ico(1)).data.currentOutput; - ch = strtrim (smdata.inst(ico(1)).channels(ico(2),:) ); - ind = strcmp (ch, chans); - queue(ind) = val; - end - - smdata.inst(ico(1)).data.output.wait; %safety wait -% while(smdata.inst(ico(1)).data.output.IsRunning) -% drawnow() -% end - - % in case you just want to step - if nargin < 3 - rate = Inf; - end - - rate = sign(rate) * smdata.inst(ico(1)).data.output.Rate; - - if rate > 0 - %fprintf ([mat2str(queue) '\n']); - smdata.inst(ico(1)).data.output.outputSingleScan (queue); - smdata.inst(ico(1)).data.currentOutput = queue; - val = 0; - elseif rate < 0 -% npoints = smdata.inst(ico(1)).data.output.Rate / abs(rate) *... -% max(abs(smdata.inst(ico(1)).data.currentOutput - queue)); - % dirty workaround - if ~isempty(smdata.inst(ico(1)).data.sync) - inst = smdata.inst(ico(1)).data.sync; - else - inst = ico(1); - end - - npoints = smdata.inst(inst).data.input.NumberOfScans / ... - smdata.inst(inst).data.downsamp; - - fun = @(x) linspace (smdata.inst(ico(1)).data.currentOutput(x),... - queue(x),... - npoints)'; - % not very generic, to be changed - ramp = [fun(1) fun(2) fun(3) fun(4)]; -% smdata.inst(ico(1)).data.output.release; - smdata.inst(ico(1)).data.output.queueOutputData (ramp); - %smdata.inst(ico(1)).data.output.prepare(); - smdata.inst(ico(1)).data.currentlyQueuedOutput = queue; - val = size(queue, 1) / abs(smdata.inst(ico(1)).data.output.Rate); - else - error('Cannot ramp at zero ramprate!') - end - - case num2cell(37:51) %pfi0-pfi14 - setDigitalChannel (ico, val); - - end - case 3 %Trigger, has to be 'collectivelized' as well; - switch ico(2) - case num2cell(1:32) %analog inputs - if ~smdata.inst(ico(1)).data.input.IsRunning - %Start background job - smdata.inst(ico(1)).data.input.startBackground; - end - - case num2cell(33:36) %analog outputs - %Start background job - smdata.inst(ico(1)).data.output.startBackground; - %not safe when measurement fails - smdata.inst(ico(1)).data.currentOutput = ... - smdata.inst(ico(1)).data.currentlyQueuedOutput; - -% UNSUPPORTED! See auxiliary function smaNIDAQmx for further details -% do not like this way of triggering any longer; inconvenient to work with -% case num2cell(1:51) %pfi0-pfi14 -% %trigger on rising edge -% smdata.inst(ico(1)).data.input.startBackground(); -% setDigitalChannel (ico, 0); -% setDigitalChannel (ico, 1); -% setDigitalChannel (ico, 0); - - otherwise - error('No trigger available for selected channel!') - end - - case 4 %Arm - switch ico(2) - case num2cell(1:32) %analog inputs - if ~smdata.inst(ico(1)).data.input.IsRunning - %Start background job - smdata.inst(ico(1)).data.input.startBackground; - end - - otherwise - error('No arming procedure available for selected channel!') - end - - case 5 %configure - ch = strtrim (smdata.inst(ico(1)).channels(ico(2),:) ); - %Add channel - try smdata.inst(ico(1)).data.input.addAnalogInputChannel(... - smdata.inst(ico(1)).data.id,... - ch,... - 'Voltage'... - ); - catch err - errStr = 'NI: The channel ''ai([0-9]|([1-2][0-9])|(3[01]))'' cannot be added to the session because it has been added previously.'; - if ~regexp (err.message, errStr, 'ONCE') - rethrow(err); - end - end - - smdata.inst(ico(1)).data.downsamp = ... - floor(smdata.inst(ico(1)).data.input.Rate / rate); - rate = smdata.inst(ico(1)).data.input.Rate / smdata.inst(ico(1)).data.downsamp; - - if smdata.inst(ico(1)).data.downsamp == 0 - error('Input rate too large.'); - end - - % could add some error checks here - if smdata.inst(ico(1)).data.downsamp > 1 - npt = val * smdata.inst(ico(1)).data.downsamp; - else - npt = val; - end - - smdata.inst(ico(1)).data.input.NumberOfScans = npt; - smdata.inst(ico(1)).data.input.NotifyWhenDataAvailableExceeds = npt; - - %Create listener for acquisition - smdata.inst(ico(1)).data.lh = ... - smdata.inst(ico(1)).data.input.addlistener(... - 'DataAvailable',... - @(src, event) outputData(ico(1), event.Data)... - ); - - %smdata.inst(ico(1)).data.input.prepare(); - smdata.inst(ico(1)).datadim(ico(2), 1) = val; - %fprintf('CHECK!\n') - - case 6 %Initialize card - %TODO: Needs to be improved, if more than one NI daq-device is installed - %dev = daq.getDevices; - - % --------------------------------------------------------------- - % THIS SECTION CAN VERY EASILY BE MIGRATED TO THE RESPECTIVE SMA - % FUNCTION TO ADD VARIABILITY AND BETTER ERROR HANDLING - % --------------------------------------------------------------- -% daq.HardwareInfo.getInstance('DisableReferenceClockSynchronization',true); - - for dev = daq.getDevices - if strcmp (dev.Description, 'National Instruments PCIe-6363') - smdata.inst(ico(1)).data.id = dev.ID; - smdata.inst(ico(1)).data.output = daq.createSession('ni'); - smdata.inst(ico(1)).data.input = daq.createSession('ni'); - smdata.inst(ico(1)).data.digital = daq.createSession('ni'); - disp('Found NI PCIe-6363!') - end - end - - %Add all analog channels - smdata.inst(ico(1)).data.output.addAnalogOutputChannel(... - smdata.inst(ico(1)).data.id,... - 0:3,... - 'Voltage'... - ); - smdata.inst(ico(1)).data.output.queueOutputData([0 0 0 0]); - smdata.inst(ico(1)).data.output.startForeground; - smdata.inst(ico(1)).data.currentOutput = [0 0 0 0]; - - %Digital channels (PFI1-13) - smdata.inst(ico(1)).data.digital.addDigitalChannel(... - smdata.inst(ico(1)).data.id,... - 'port1/line1:7',... - 'OutputOnly'... - ); - smdata.inst(ico(1)).data.digital.addDigitalChannel(... - smdata.inst(ico(1)).data.id,... - 'port2/line0:5',... - 'OutputOnly'... - ); - queue = zeros (1, length(smdata.inst(ico(1)).data.digital.Channels)); - smdata.inst(ico(1)).data.digital.outputSingleScan (queue); - smdata.inst(ico(1)).data.currentDigitalOutput = queue; - - %Maybe add configuration for analog outputs here, e.g. range, triggers etc. - smdata.inst(ico(1)).data.digital.prepare(); - - otherwise - error('Operation not supported!') -end -end - -%callback function for 'DataAvailable'-listener -function outputData (inst, data) - global smdata - smdata.inst(inst).data.buf = []; - smdata.inst(inst).data.buf = data; -end - -function val = setDigitalChannel (ico, val) - global smdata - wrapper = @(varargin) varargin; - - ch = strtrim (smdata.inst(ico(1)).channels(ico(2),:) ); - chanlist = wrapper (smdata.inst(ico(1)).data.digital.Channels.ID); - ind = strcmp (ch, chanlist); - - queue = smdata.inst(ico(1)).data.currentDigitalOutput; - queue(ind) = val; - - smdata.inst(ico(1)).data.digital.outputSingleScan (queue); - smdata.inst(ico(1)).data.currentDigitalOutput = queue; -end - - -% function waitRunning (inst, session, timeout) -% %wait implemented manually -% global smdata -% % t = now; -% % while smdata.inst(inst).data.(session).IsRunning -% % if 24*3600*(now-t) > timeout % in seconds -% % error ('Wait timeout!'); -% % end -% % end -% -% % MODIFIED VERSION OF doWait in Session.m -% obj = smdata.inst(inst).data.(session); -% % Validate timeout -% if ~isscalar(timeout) || ~isnumeric(timeout) || isnan(timeout) || timeout <= 0 -% error('Invalid timeout!') -% end -% if obj.IsContinuous && isinf(timeout) -% error('No inf wait in continuous mode allowed!') -% end -% -% % Wait for up to timeout seconds for obj to reach IsRunning state. -% localTimer = tic; -% while obj.IsRunning == true &&... -% (isinf(timeout) || toc(localTimer) < timeout) -% drawnow(); -% end -% if obj.IsRunning == true -% error('Wait timeout!') -% end -% end \ No newline at end of file diff --git a/sm/channels/smcNIPCI6713.m b/sm/channels/smcNIPCI6713.m index dcce7350f2a5b60b7dcf1fccddfc256a108d0bce..8a84d3559ab90f2e33ec4b836ef99127485b24d1 100644 --- a/sm/channels/smcNIPCI6713.m +++ b/sm/channels/smcNIPCI6713.m @@ -1,181 +1,188 @@ -function [val, rate] = smcNIPCI6713(ico, val, rate) -global smdata -%little workaround because of the session interface -wrapper = @(varargin) varargin; - -% workaround; better ideas are always welcome -COLLCHANS = smdata.inst(ico(1)).type == 2; -if length(ico) > 3 - COLLCHANS = ico(2:end-1); - ico(2) = 0; - ico(3) = ico(end); - ico(4:end) = []; - rate = rate ( find (abs(rate) == max (abs (rate)), 1) ); -end - -switch ico(3) - case 0 %Read - ch = strtrim (smdata.inst(ico(1)).channels(ico(2),:)); - - switch ico(2) - case {0,1,2,3,4,5,6,7,8} %{collective, ao0, ao1, ...} - chanlist = wrapper (smdata.inst(ico(1)).data.output.Channels.ID); - ind = strcmp (ch, chanlist); - val = smdata.inst(ico(1)).data.currentOutput(ind); - - otherwise - error('Channel not (yet?) configured for readout!') - end - - case 1 %Set/Ramp - switch ico(2) - case {0,1,2,3,4,5,6,7,8} %{collective, ao0, ao1, ...} - % if not all outputs are set, just set specified outputs and leave - % the rest as is - chans = smdata.inst(ico(1)).channels(COLLCHANS, :); - chans = arrayfun (@(x) strtrim(chans(x, 1:end)),... - 1:size(chans, 1),... - 'UniformOutput', false... - ); - if ico(2) == 0 - for ch = 1:length(smdata.inst(ico(1)).data.currentOutput) - tmp = val(... - strcmp (chans, smdata.inst(ico(1)).data.output.Channels(ch).ID)... - ); - if isempty(tmp) - queue(ch) = smdata.inst(ico(1)).data.currentOutput(ch); - else - queue(ch) = tmp; - end - end - else - queue = smdata.inst(ico(1)).data.currentOutput; - ch = strtrim (smdata.inst(ico(1)).channels(ico(2),:) ); - ind = strcmp (ch, chans); - queue(ind) = val; - end - - smdata.inst(ico(1)).data.output.wait; %safety wait - - % in case you just want to step - if nargin < 3 - rate = Inf; - end - - rate = sign(rate) * smdata.inst(ico(1)).data.output.Rate; - - if rate > 0 - %fprintf ([mat2str(queue) '\n']); -% smdata.inst(ico(1)).data.output.outputSingleScan (queue); - % this hack does not allow triggered stepping, solution - % is to check for trigger connection to external - % targets - smdata.inst(ico(1)).data.output.queueOutputData(queue); - smdata.inst(ico(1)).data.output.startBackground(); - smdata.inst(ico(1)).data.currentOutput = queue; - val = 0; - elseif rate < 0 - npoints = smdata.inst(ico(1)).data.nout; - - fun = @(x) linspace (smdata.inst(ico(1)).data.currentOutput(x),... - queue(x),... - npoints)'; - %not very generic, to be changed - ramp = [fun(1) fun(2) fun(3) fun(4)... - fun(5) fun(6) fun(7) fun(8)]; - smdata.inst(ico(1)).data.output.release; - smdata.inst(ico(1)).data.output.queueOutputData (ramp); - %smdata.inst(ico(1)).data.output.prepare(); - smdata.inst(ico(1)).data.currentlyQueuedOutput = queue; - val = size(queue, 1) / abs(smdata.inst(ico(1)).data.output.Rate); - else - error('Cannot ramp at zero ramprate!') - end - - case num2cell(37:51) %pfi0-pfi14 - setDigitalChannel (ico, val); - - end - case 3 % Trigger, has to be 'collectivelized' as well; - switch(ico(2)) - case {0,1,2,3,4,5,6,7,8} %{collective, ao0, ao1, ...} - % Start background job - smdata.inst(ico(1)).data.output.startBackground; - % not safe when measurement fails - smdata.inst(ico(1)).data.currentOutput = ... - smdata.inst(ico(1)).data.currentlyQueuedOutput; - - otherwise - error('No trigger available for selected channel!') - end - - case 4 %Arm - switch ico(2) - case {0,1,2,3,4,5,6,7,8} %{collective, ao0, ao1, ...} - if ~smdata.inst(ico(1)).data.output.IsRunning - %Start background job - smdata.inst(ico(1)).data.output.startBackground; - end - - otherwise - error('No arming procedure available for selected channel!') - end - - case 5 %configure - - case 6 %Initialize card - % See further details in smcNIDAQmx.m -% daq.HardwareInfo.getInstance('DisableReferenceClockSynchronization',true); - - for dev = daq.getDevices - if strcmp (dev.Description, 'National Instruments PCI-6713') - smdata.inst(ico(1)).data.id = dev.ID; - smdata.inst(ico(1)).data.output = daq.createSession('ni'); - smdata.inst(ico(1)).data.digital = daq.createSession('ni'); - disp('Found NI PCI-6713!') - end - end - - %Add all analog channels - smdata.inst(ico(1)).data.output.addAnalogOutputChannel(... - smdata.inst(ico(1)).data.id,... - 0:7,... - 'Voltage'... - ); - smdata.inst(ico(1)).data.output.queueOutputData(zeros(1,8)); - smdata.inst(ico(1)).data.output.startForeground; - smdata.inst(ico(1)).data.currentOutput = zeros(1,8); - - %Digital channels -% smdata.inst(ico(1)).data.digital.addDigitalChannel(... -% smdata.inst(ico(1)).data.id,... -% 'port0/line0:7',... -% 'OutputOnly'... -% ); - -% queue = zeros (1, length(smdata.inst(ico(1)).data.digital.Channels)); -% smdata.inst(ico(1)).data.digital.outputSingleScan (queue); -% smdata.inst(ico(1)).data.currentDigitalOutput = queue; - - %Maybe add configuration for analog outputs here, e.g. range, triggers etc. -% smdata.inst(ico(1)).data.digital.prepare(); - - otherwise - error('Operation not supported!') -end -end - -function val = setDigitalChannel (ico, val) - global smdata - wrapper = @(varargin) varargin; - - ch = strtrim (smdata.inst(ico(1)).channels(ico(2),:) ); - chanlist = wrapper (smdata.inst(ico(1)).data.digital.Channels.ID); - ind = strcmp (ch, chanlist); - - queue = smdata.inst(ico(1)).data.currentDigitalOutput; - queue(ind) = val; - - smdata.inst(ico(1)).data.digital.outputSingleScan (queue); - smdata.inst(ico(1)).data.currentDigitalOutput = queue; +function [val, rate] = smcNIPCI6713(ico, val, rate) +global smdata +%little workaround because of the session interface +wrapper = @(varargin) varargin; + +% workaround; better ideas are always welcome +COLLCHANS = smdata.inst(ico(1)).type == 2; +if length(ico) > 3 + COLLCHANS = ico(2:end-1); + ico(2) = 0; + ico(3) = ico(end); + ico(4:end) = []; + rate = rate ( find (abs(rate) == max (abs (rate)), 1) ); +end + +switch ico(3) + case 0 %Read + ch = strtrim (smdata.inst(ico(1)).channels(ico(2),:)); + + switch ico(2) + case {0,1,2,3,4,5,6,7,8} %{collective, ao0, ao1, ...} + chanlist = wrapper (smdata.inst(ico(1)).data.output.Channels.ID); + ind = strcmp (ch, chanlist); + val = smdata.inst(ico(1)).data.currentOutput(ind); + + otherwise + error('Channel not (yet?) configured for readout!') + end + + case 1 %Set/Ramp + switch ico(2) + case {0,1,2,3,4,5,6,7,8} %{collective, ao0, ao1, ...} + % if not all outputs are set, just set specified outputs and leave + % the rest as is + chans = smdata.inst(ico(1)).channels(COLLCHANS, :); + chans = arrayfun (@(x) strtrim(chans(x, 1:end)),... + 1:size(chans, 1),... + 'UniformOutput', false... + ); + if ico(2) == 0 + for ch = 1:length(smdata.inst(ico(1)).data.currentOutput) + tmp = val(... + strcmp (chans, smdata.inst(ico(1)).data.output.Channels(ch).ID)... + ); + if isempty(tmp) + queue(ch) = smdata.inst(ico(1)).data.currentOutput(ch); + else + queue(ch) = tmp; + end + end + else + queue = smdata.inst(ico(1)).data.currentOutput; + ch = strtrim (smdata.inst(ico(1)).channels(ico(2),:) ); + ind = strcmp (ch, chans); + queue(ind) = val; + end + + smdata.inst(ico(1)).data.output.wait; %safety wait + + % in case you just want to step + if nargin < 3 + rate = Inf; + end + + rate = sign(rate) * smdata.inst(ico(1)).data.output.Rate; + + if rate > 0 + smdata.inst(ico(1)).data.output.outputSingleScan(queue); + smdata.inst(ico(1)).data.currentOutput = queue; +% disp('setStartRamp') + val = 0; + elseif rate < 0 + npoints = smdata.inst(ico(1)).data.npoints; + + fun = @(x) linspace (smdata.inst(ico(1)).data.currentOutput(x),... + queue(x),... + npoints)'; + ramp = [fun(1) fun(2) fun(3) fun(4)... + fun(5) fun(6) fun(7) fun(8)]; +% smdata.inst(ico(1)).data.output.release; + smdata.inst(ico(1)).data.output.queueOutputData (ramp); +% smdata.inst(ico(1)).data.output.prepare(); + smdata.inst(ico(1)).data.currentlyQueuedOutput = queue; + smdata.inst(ico(1)).data.output.startBackground(); +% disp('setStopRamp') + val = size(queue, 1) / abs(smdata.inst(ico(1)).data.output.Rate); + else + error('Cannot ramp at zero ramprate!') + end + + case num2cell(37:51) %pfi0-pfi14 + setDigitalChannel (ico, val); + + end + case 3 % Trigger, has to be 'collectivelized' as well; + switch(ico(2)) + case {0,1,2,3,4,5,6,7,8} %{collective, ao0, ao1, ...} + smdata.inst(ico(1)).data.output.startBackground(); + % not safe when measurement fails + smdata.inst(ico(1)).data.currentOutput = ... + smdata.inst(ico(1)).data.currentlyQueuedOutput; + + otherwise + error('No trigger available for selected channel!') + end + + case 4 %Arm + switch ico(2) + case {0,1,2,3,4,5,6,7,8} %{collective, ao0, ao1, ...} +% This is generally not a good idea; do this in configfn +% if isfield(smdata.inst(ico(1)).data,'trigIn') && ... +% ~isempty(smdata.inst(ico(1)).data.trigIn) +% try +% smdata.inst(ico(1)).data.output.addTriggerConnection(... +% 'external',... +% [smdata.inst(ico(1)).data.id '/' smdata.inst(ico(1)).data.trigIn],... +% 'StartTrigger'); +% catch err +% doThrow = any( [ ~strfind(err.message, 'A StartTrigger connection already exists between'),... +% ~strfind(err.message, 'Attempt to reference field of non-structure array.') ] ); +% if doThrow +% rethrow(err); +% end +% end +% end +% disp('armOutput') + + otherwise + error('No arming procedure available for selected channel!') + end + + case 5 %configure + + case 6 %Initialize card + % See further details in smcNIDAQmx.m +% daq.HardwareInfo.getInstance('DisableReferenceClockSynchronization',true); + + for dev = daq.getDevices + if strcmp (dev.Description, 'National Instruments PCI-6713') + smdata.inst(ico(1)).data.id = dev.ID; + smdata.inst(ico(1)).data.output = daq.createSession('ni'); + disp('Found NI PCI-6713!') + end + end + + %Add all analog channels + smdata.inst(ico(1)).data.output.addAnalogOutputChannel(... + smdata.inst(ico(1)).data.id,... + 0:7,... + 'Voltage'... + ); + smdata.inst(ico(1)).data.output.queueOutputData(zeros(1,8)); + smdata.inst(ico(1)).data.output.startForeground; + smdata.inst(ico(1)).data.currentOutput = zeros(1,8); + + %Digital channels +% smdata.inst(ico(1)).data.digital.addDigitalChannel(... +% smdata.inst(ico(1)).data.id,... +% 'port0/line0:7',... +% 'OutputOnly'... +% ); + +% queue = zeros (1, length(smdata.inst(ico(1)).data.digital.Channels)); +% smdata.inst(ico(1)).data.digital.outputSingleScan (queue); +% smdata.inst(ico(1)).data.currentDigitalOutput = queue; + + %Maybe add configuration for analog outputs here, e.g. range, triggers etc. +% smdata.inst(ico(1)).data.digital.prepare(); + + otherwise + error('Operation not supported!') +end +end + +function val = setDigitalChannel (ico, val) + global smdata + wrapper = @(varargin) varargin; + + ch = strtrim (smdata.inst(ico(1)).channels(ico(2),:) ); + chanlist = wrapper (smdata.inst(ico(1)).data.digital.Channels.ID); + ind = strcmp (ch, chanlist); + + queue = smdata.inst(ico(1)).data.currentDigitalOutput; + queue(ind) = val; + + smdata.inst(ico(1)).data.digital.outputSingleScan (queue); + smdata.inst(ico(1)).data.currentDigitalOutput = queue; end \ No newline at end of file diff --git a/sm/channels/smcNIPCIe6363.m b/sm/channels/smcNIPCIe6363.m new file mode 100644 index 0000000000000000000000000000000000000000..5596aa89b25a86a2693fa9b6b2736363496344ac --- /dev/null +++ b/sm/channels/smcNIPCIe6363.m @@ -0,0 +1,148 @@ +function [val, rate] = smcNIDAQmx(ico, val, rate) +% general note: outputs will be deprecated by this driver; it works out +% best to implement outputs as virtual instruments for the respective task +% you want to accomplish; this gets rid of a lot of headaches when +% configuring, updating and syncing the nidaq's state; as of now this +% control function will be rewritten as a pure acquisition instrument +global smdata +% little workaround because of the session interface +wrapper = @(varargin) varargin; + +switch ico(3) + case 0 %Read + ch = strtrim (smdata.inst(ico(1)).channels(ico(2),:) ); + + switch ico(2) + case num2cell(1:32) %analog inputs + chanlist = wrapper (smdata.inst(ico(1)).data.input.Channels.ID); + ind = find(strcmp (ch, chanlist)); + downsamp = smdata.inst(ico(1)).data.downsamp; + nsamp = smdata.inst(ico(1)).datadim(ico(2), 1); + + while (smdata.inst(ico(1)).data.input.IsRunning && ... + ~smdata.inst(ico(1)).data.input.IsDone) +% smdata.inst(ico(1)).data.input.wait; + drawnow(); + end + + if (nsamp > 1 || downsamp > 1) %buffered readout + if smdata.inst(ico(1)).data.input.IsDone + val = smdata.inst(ico(1)).data.buf(:, ind); + if downsamp > 1 + val = mean(reshape(val(1:downsamp*nsamp), downsamp, nsamp)); + end + else + error('Wait for DataAvailable failed!') + end + else %just read current value + val = smdata.inst(ico(1)).data.input.inputSingleScan(); + val = val(ind); + end +% disp('fetchBuffer') + + otherwise + error('Channel not (yet?) configured for readout!') + end + + case 3 %Trigger, has to be 'collectivelized' as well; + switch ico(2) + case num2cell(1:32) %analog inputs + if ~smdata.inst(ico(1)).data.input.IsRunning + smdata.inst(ico(1)).data.input.startBackground; + end + + otherwise + error('No trigger available for selected channel!') + end + + case 4 %Arm + switch ico(2) + case num2cell(1:32) %analog inputs +% if ~isempty(smdata.inst(ico(1)).data.trigIn) +% try +% smdata.inst(ico(1)).data.input.addTriggerConnection(... +% 'external',... +% [smdata.inst(ico(1)).data.id '/' smdata.inst(ico(1)).data.trigIn],... +% 'StartTrigger'); +% catch err +% doThrow = any( [ ~strfind(err.message, 'A StartTrigger connection already exists between'),... +% ~strfind(err.message, 'Attempt to reference field of non-structure array.') ] ); +% if doThrow +% rethrow(err); +% end +% end +% end + + if ~smdata.inst(ico(1)).data.input.IsRunning + smdata.inst(ico(1)).data.input.prepare(); + smdata.inst(ico(1)).data.input.startBackground(); +% disp('armInput') + end + + otherwise + error('No arming procedure available for selected channel!') + end + + case 5 %configure +% ch = strtrim (smdata.inst(ico(1)).channels(ico(2),:) ); + %Add channel +% DEPRECATED: use interface functions as configfns instead +% try smdata.inst(ico(1)).data.input.addAnalogInputChannel(... +% smdata.inst(ico(1)).data.id,... +% ch,... +% 'Voltage'... +% ); +% catch err +% errStr = 'NI: The channel ''ai([0-9]|([1-2][0-9])|(3[01]))'' cannot be added to the session because it has been added previously.'; +% if ~regexp (err.message, errStr, 'ONCE') +% rethrow(err); +% end +% end + + smdata.inst(ico(1)).data.downsamp = ... + ceil(smdata.inst(ico(1)).data.input.Rate / rate); + rate = smdata.inst(ico(1)).data.input.Rate / smdata.inst(ico(1)).data.downsamp; + + if smdata.inst(ico(1)).data.downsamp == 0 + error('Input rate too large.'); + end + + % could add some error checks here + if smdata.inst(ico(1)).data.downsamp > 1 + npt = val * smdata.inst(ico(1)).data.downsamp; + else + npt = val; + end + + smdata.inst(ico(1)).data.input.NumberOfScans = npt; + smdata.inst(ico(1)).data.input.NotifyWhenDataAvailableExceeds = npt; + + %Create listener for acquisition + smdata.inst(ico(1)).data.lh = ... + smdata.inst(ico(1)).data.input.addlistener(... + 'DataAvailable',... + @(src, event) outputData(ico(1), event.Data)... + ); + + smdata.inst(ico(1)).datadim(ico(2), 1) = val; + + case 6 % initialize + for dev = daq.getDevices + if strcmp (dev.Description, 'National Instruments PCIe-6363') + smdata.inst(ico(1)).data.id = dev.ID; + smdata.inst(ico(1)).data.input = daq.createSession('ni'); + disp('Found NI PCIe-6363!') + end + end + + otherwise + error('Operation not supported!') +end +end + +%callback function for 'DataAvailable'-listener +function outputData (inst, data) + global smdata + smdata.inst(inst).data.buf = []; + smdata.inst(inst).data.buf = data; +end \ No newline at end of file diff --git a/sm/channels/smcStepAttenuator.m b/sm/channels/smcStepAttenuator.m index 3a84f0d8f80fc03d82575e1a5bb3eaa2b39b5bc3..d0898c25dac8a5e977dc4e195647ffb268868372 100755 --- a/sm/channels/smcStepAttenuator.m +++ b/sm/channels/smcStepAttenuator.m @@ -1,59 +1,69 @@ -function val = smcStepAttenuator (ico, val) +function [val, rate] = smcStepAttenuator (ico, val, rate, varargin) % function val = smcStepAttenuator (ico, val) % This driver is tailored for usage with the NIDAQmx PCIe-6363. It uses % PFI1-PFI6 as outputs with PFI6 being the control/latch bit. global smdata -INST = sminstlookup('NIPCIe6363'); % TODO:CORRECT THIS! -CHANS = 38:43; %PFI1-PFI6 switch ico(3) - case 1 + case 0 switch ico(2) case 1 - setBit([INST CHANS(6) 1], 0); - - val = dec2bin(val*2, 5); - setBit([INST CHANS(5) 1], str2num(val(1))); - setBit([INST CHANS(4) 1], str2num(val(2))); - setBit([INST CHANS(3) 1], str2num(val(3))); - setBit([INST CHANS(2) 1], str2num(val(4))); - setBit([INST CHANS(1) 1], str2num(val(5))); - - setBit([INST CHANS(6) 1], 1); - setBit([INST CHANS(6) 1], 0); - - val = 2 * bin2dec(num2str(val)); + % little endian + val = bin2dec(num2str(... + fliplr(smdata.inst(ico(1)).data.currentDigitalOutput(1:5))))/2; otherwise error('Channel not available!') end - case 0 + + case 1 switch ico(2) case 1 - val(1) = getBit([INST, CHANS(5)]); - val(2) = getBit([INST, CHANS(4)]); - val(3) = getBit([INST, CHANS(3)]); - val(4) = getBit([INST, CHANS(2)]); - val(5) = getBit([INST, CHANS(1)]); + % set queue + val = dec2bin(val*2, 5); + queue = []; + queue(5) = str2num(val(1)); + queue(4) = str2num(val(2)); + queue(3) = str2num(val(3)); + queue(2) = str2num(val(4)); + queue(1) = str2num(val(5)); + + % latch low-high-low + smdata.inst(ico(1)).data.digital.outputSingleScan(... + [queue 0]); + smdata.inst(ico(1)).data.digital.outputSingleScan(... + [queue 1]); + smdata.inst(ico(1)).data.digital.outputSingleScan(... + [queue 0]); - val = bin2dec(num2str(val))/2; + smdata.inst(ico(1)).data.currentDigitalOutput = [queue 0]; + + val = 2 * bin2dec(num2str(val)); otherwise error('Channel not available!') end + + case 6 + % this configures a NIDAQ Session with the NI PCIe-6363 to control + % the digital step attenuator + for dev = daq.getDevices + if strcmp (dev.Description, 'National Instruments PCIe-6363') + smdata.inst(ico(1)).data.id = dev.ID; + end + end + + % create default session for linear ramping of scanners + smdata.inst(ico(1)).data.digital = daq.createSession('ni'); + + % digital channels (PFI1-6) + smdata.inst(ico(1)).data.digital.addDigitalChannel(... + smdata.inst(ico(1)).data.id,... + 'port1/line1:6',... + 'OutputOnly'... + ); + queue = zeros(1, length(smdata.inst(ico(1)).data.digital.Channels)); + smdata.inst(ico(1)).data.digital.outputSingleScan (queue); + smdata.inst(ico(1)).data.currentDigitalOutput = queue; end -end - -function val = setBit(ic, val) - retVal = smcNIDAQmx([ic(1) ic(2) 1], val); - - if retVal ~= val - error ('Error setting bit!') - end - - val = retVal; -end - -function val = getBit(ic) - val = smcNIDAQmx([ic(1) ic(2) 0]); end \ No newline at end of file diff --git a/sm/smdiagpar.m b/sm/smdiagpar.m index e4097899cfe90e51c203d364167f75960a3d60d8..6f18f69008af67282fa5a87f81dcb054b30f5ac8 100755 --- a/sm/smdiagpar.m +++ b/sm/smdiagpar.m @@ -1,52 +1,52 @@ -function scan = smdiagpar(scan, angle, cntr, loops) -% smdiagpar(scan, angle, cntr, loops) -% configure scan rotation by angle, followed by shift to cntr. -% loops specifies to which loops to apply the operation. Default is the -% two innermost loops. -% Other global transformation functions are removed, and the range of the two -% loops affected is shifted to be symmetric around 0. -% An exception is angle = 0, which removes all transformation functions -% and sets the scan range to be centered around cntr. -% Keep in mind thatin order to rotate the scan, both x and y channels must -% be set in the innermost loop. -%angle in radians - -if nargin < 4 - loops =[]; -end - -nloops = length(scan.loops); - -switch length(loops) - case 0 - loops = 1:2; - case 1 - loops = loops + [0, 1]; - case 2 - - otherwise - fprintf('n-D rotations not implemented\n'); - return; -end - -% difficult for repeated calls - would have to get center back from trafo -%if nargin < loops -% cntr = mean(vertcat(scan.loops(loops).rng), 2)'; -%end - -if angle ~= 0 - M = eye(nloops); - M(loops, loops) = [cos(angle), -sin(angle); sin(angle), cos(angle)]; - b = zeros(1, nloops); - b(loops) = cntr; - - scan.trafofn{1} = @(x) x*M' + b; - for i = loops - scan.loops(i).rng = scan.loops(i).rng - mean(scan.loops(i).rng); - end -else - scan.trafofn = {}; - for i = 1:length(loops) - scan.loops(loops(i)).rng = scan.loops(loops(i)).rng - mean(scan.loops(loops(i)).rng) + cntr(i); - end +function scan = smdiagpar(scan, angle, cntr, loops) +% smdiagpar(scan, angle, cntr, loops) +% configure scan rotation by angle, followed by shift to cntr. +% loops specifies to which loops to apply the operation. Default is the +% two innermost loops. +% Other global transformation functions are removed, and the range of the two +% loops affected is shifted to be symmetric around 0. +% An exception is angle = 0, which removes all transformation functions +% and sets the scan range to be centered around cntr. +% Keep in mind thatin order to rotate the scan, both x and y channels must +% be set in the innermost loop. +%angle in radians + +if nargin < 4 + loops =[]; +end + +nloops = length(scan.loops); + +switch length(loops) + case 0 + loops = 1:2; + case 1 + loops = loops + [0, 1]; + case 2 + + otherwise + fprintf('n-D rotations not implemented\n'); + return; +end + +% difficult for repeated calls - would have to get center back from trafo +%if nargin < loops +% cntr = mean(vertcat(scan.loops(loops).rng), 2)'; +%end + +if angle ~= 0 + M = eye(nloops); + M(loops, loops) = [cos(angle), -sin(angle); sin(angle), cos(angle)]; + b = zeros(1, nloops); + b(loops) = cntr; + + scan.trafofn{1} = @(x) x*M' + b; + for i = loops + scan.loops(i).rng = scan.loops(i).rng - mean(scan.loops(i).rng); + end +else + scan.trafofn = {}; + for i = 1:length(loops) + scan.loops(loops(i)).rng = scan.loops(loops(i)).rng - mean(scan.loops(loops(i)).rng) + cntr(i); + end end \ No newline at end of file diff --git a/sm/sminitdisp.m b/sm/sminitdisp.m index 6ec2b3253de317952a5b2b144c0c70fb435bee02..f3e5627812ad60a4ae36064a62ae2845c9cfa600 100644 --- a/sm/sminitdisp.m +++ b/sm/sminitdisp.m @@ -3,7 +3,7 @@ function sminitdisp % % Initialize figure 999 to display current channel values. % The displayed values of all scalar channels will be updated by every -% call of smset or smget as long is figure 999 is open. +% call of smset or smget as long as figure 999 is open. global smdata; nchan = length(smdata.channels); @@ -23,5 +23,4 @@ uicontrol('style', 'text', 'position', [10, 10, 200, 14*nchan], ... 'HorizontalAlignment', 'Left', 'string', str, 'BackgroundColor', [.8 .8 .8]); smdata.chandisph = uicontrol('style', 'text', 'position', [110, 10, 100, 14*nchan], ... - 'HorizontalAlignment', 'Left', 'string', repmat({''}, nchan, 1), 'BackgroundColor', [.8 .8 .8]); - + 'HorizontalAlignment', 'Left', 'string', repmat({''}, nchan, 1), 'BackgroundColor', [.8 .8 .8]); \ No newline at end of file diff --git a/sm/smprintchannels.m b/sm/smprintchannels.m index 5291a421970b393421b851fc78fd7e5ae8c8ef75..443f6809f03b40c26d01cb1991973d6568a5810f 100755 --- a/sm/smprintchannels.m +++ b/sm/smprintchannels.m @@ -11,7 +11,7 @@ elseif ischar(ch)||iscell(ch) ch = smchanlookup(ch); end -fmt = '%2d %-10s %-10s %-10s %-10s\n'; +fmt = '%2d %-10s %-15s %-15s %-10s\n'; fprintf(['CH', fmt(4:end)], 'Name', 'Device', 'Dev. Name', 'Dev. Ch.'); fprintf([repmat('-', 1, 60), '\n']); for i = ch; diff --git a/sm/smprintinst.m b/sm/smprintinst.m index 9c2c27c765a8947202a76cfaefa7f85a2b1aa2ed..d3ae424788f76c95dedb51a5383f7a508347e275 100755 --- a/sm/smprintinst.m +++ b/sm/smprintinst.m @@ -12,12 +12,12 @@ else inst = sminstlookup(inst); end -fmt = '%2d %-10s %-10s\n'; +fmt = '%4d %-15s %-15s\n'; fprintf(['Inst', fmt(4:end)], 'Device', 'Dev. Name'); fprintf([repmat('-', 1, 60), '\n']); for i = inst; fprintf(fmt, i, smdata.inst(i).device, smdata.inst(i).name); end if length(inst) == 1 - disp(strvcat(smdata.inst(i).channels)); + disp(char(smdata.inst(i).channels)); end \ No newline at end of file diff --git a/sm/smrestore.m b/sm/smrestore.m index 117f90484d22a26c6a9fcb72031406c556ac2761..b3f9ba1063ef9d409a9d0c6fcfcc662b5906f1e3 100755 --- a/sm/smrestore.m +++ b/sm/smrestore.m @@ -1,19 +1,19 @@ -function smrestore(file, channels) -% smrestore(file, channels) -% restore channel values from a datafile. -% channels can be strings or indices and specifies which values to set, default is all. - -load(file, 'configvals', 'configch'); - -configch = smchanlookup(configch); -if nargin >= 2 - channels = smchanlookup(channels); - if ~all(ismember(channels, configch)) - fprintf('WARNING: some channel values not found.\n'); - end - mask = ismember(configch, channels); - configch = configch(mask); - configvals = configvals(mask); -end - +function smrestore(file, channels) +% smrestore(file, channels) +% restore channel values from a datafile. +% channels can be strings or indices and specifies which values to set, default is all. + +load(file, 'configvals', 'configch'); + +configch = smchanlookup(configch); +if nargin >= 2 + channels = smchanlookup(channels); + if ~all(ismember(channels, configch)) + fprintf('WARNING: some channel values not found.\n'); + end + mask = ismember(configch, channels); + configch = configch(mask); + configvals = configvals(mask); +end + smset(configch, configvals); \ No newline at end of file diff --git a/sm/smrun.m b/sm/smrun.m index 0fae29b1cd97e01bb726a9d7e4dfd7b5207847eb..1453ca738ebaf5cdeb8ee84f24798c47e8e64d94 100644 --- a/sm/smrun.m +++ b/sm/smrun.m @@ -78,7 +78,7 @@ end % provided if ~isempty(scan.loops(1).ramptime) && scan.loops(1).ramptime<0 && (~isfield(scan.loops(1),'trigfn') || ... isempty(scan.loops(1).trigfn) || ... - (isfield(scan.loops(1).trigfn,'autoset') && scan.loops(1).trigfn.autoset)) + (isfield(scan.loops(1).trigfn,'autoset') && scan.loops(1).trigfn(1).autoset)) scan.loops(1).trigfn.fn=@smatrigfn; scan.loops(1).trigfn.args{1}=smchaninst(scan.loops(1).setchan); end @@ -531,6 +531,9 @@ for i = 1:totpoints % this is a bit of a hack % alternative place to call prefn +% if isfield(scandef, 'preprefn') +% fncall(scandef(j).preprefn, xt); +% end % set autochannels and program ramp only at first loop point if count(j) == 1 % @@ -567,7 +570,7 @@ for i = 1:totpoints % prolog functions if isfield(scandef, 'prefn') fncall(scandef(j).prefn, xt); - end + end tp=(tloop(j) - now)*24*3600 + count(j) * max(abs(scandef(j).ramptime)); pause(tp); % Pause always waits 10ms @@ -594,7 +597,7 @@ for i = 1:totpoints % could save a function call/data copy here - not a lot of code newdata = smget(scandef(j).getchan); - if isfield(scandef, 'postfn') + if isfield(scandef(j), 'postfn') && ~isempty(scandef(j).postfn) fncall(scandef(j).postfn, xt); end diff --git a/sm/smscanpar.m b/sm/smscanpar.m index 90963078ff7b7225f2f8d62607810f8005ef9b84..3fe989c3f45cb7c21c742626e45bcd8c5619bbdf 100644 --- a/sm/smscanpar.m +++ b/sm/smscanpar.m @@ -1,49 +1,49 @@ -function scan = smscanpar(scan, cntr, rng, npoints, loops) -% scan = smscanpar(scan, cntr, rng, npoints, loops) -% Set center, range and number of points for scan.loops(loops). -% loops defaults to 1:length(cntr). Empty or omitted arguments are left unchanged. -% scan.configfn is executed at the end if present and not empty. -% not anymore( Tim Botzem): scan.configfn is executed at the end if present and not empty. -% -% if cntr is 'gca', copy the range of the current plot to the scan. - -if nargin < 5 - loops = 1:length(cntr); -end - -if ~isempty(cntr) - if ischar(cntr) && strcmp(cntr,'gca') - xrng=get(gca,'XLim'); - yrng=get(gca,'YLim'); - scan.loops(loops(1)).rng = xrng; - scan.loops(loops(2)).rng = yrng; - fprintf('X range: [%g,%g] Y range: [%g,%g]\n',xrng,yrng); - return; - end - for i = 1:length(loops) - scan.loops(loops(i)).rng = scan.loops(loops(i)).rng - mean(scan.loops(loops(i)).rng) + cntr(i); - end -end - -if nargin >=3 && ~isempty(rng) - for i = 1:length(loops) - scan.loops(loops(i)).rng = mean(scan.loops(loops(i)).rng) + rng(i) * [-.5 .5]; - end -end - -if nargin >=4 && ~isempty(npoints) - for i = 1:length(loops) - scan.loops(loops(i)).npoints = npoints(i); - end -end - -for i=1:length(scan.consts) -if isfield(scan, 'consts') - for i=1:length(scan.consts) - smset(scan.consts(i).setchan,scan.consts(i).val); - end -end - -if isfield(scan, 'configfn') && ~isempty(scan.configfn) - scan = scan.configfn.fn(scan, scan.configfn.args{:}); -end +function scan = smscanpar(scan, cntr, rng, npoints, loops) +% scan = smscanpar(scan, cntr, rng, npoints, loops) +% Set center, range and number of points for scan.loops(loops). +% loops defaults to 1:length(cntr). Empty or omitted arguments are left unchanged. +% scan.configfn is executed at the end if present and not empty. +% not anymore( Tim Botzem): scan.configfn is executed at the end if present and not empty. +% +% if cntr is 'gca', copy the range of the current plot to the scan. + +if nargin < 5 + loops = 1:length(cntr); +end + +if ~isempty(cntr) + if ischar(cntr) && strcmp(cntr,'gca') + xrng=get(gca,'XLim'); + yrng=get(gca,'YLim'); + scan.loops(loops(1)).rng = xrng; + scan.loops(loops(2)).rng = yrng; + fprintf('X range: [%g,%g] Y range: [%g,%g]\n',xrng,yrng); + return; + end + for i = 1:length(loops) + scan.loops(loops(i)).rng = scan.loops(loops(i)).rng - mean(scan.loops(loops(i)).rng) + cntr(i); + end +end + +if nargin >=3 && ~isempty(rng) + for i = 1:length(loops) + scan.loops(loops(i)).rng = mean(scan.loops(loops(i)).rng) + rng(i) * [-.5 .5]; + end +end + +if nargin >=4 && ~isempty(npoints) + for i = 1:length(loops) + scan.loops(loops(i)).npoints = npoints(i); + end +end + +for i=1:length(scan.consts) +if isfield(scan, 'consts') + for i=1:length(scan.consts) + smset(scan.consts(i).setchan,scan.consts(i).val); + end +end + +if isfield(scan, 'configfn') && ~isempty(scan.configfn) + scan = scan.configfn.fn(scan, scan.configfn.args{:}); +end