arduino-0.12.1/0000755000000000000000000000000014545566645010206 5ustar00arduino-0.12.1/.hgignore0000644000000000000000000000142414545566645012012 0ustar00syntax: regexp # The recurrent (^|/) idiom in the regexps below should be understood # to mean "at any directory" while the ^ idiom means "from the # project's top-level directory". (^|/).*\.dvi$ (^|/).*\.pdf$ (^|/).*\.o$ (^|/).*\.log$ (^|/).*\.oct$ (^|/).*\.octlink$ (^|/)octave-core$ (^|/).*\.tar\.gz$ ## Our Makefile target ^release/ ## Files generated automatically by autoconf and the configure script (^|/)aclocal\.m4$ (^|/)configure$ (^|/)autom4te\.cache($|/) ^src/config\.log$ ^src/config\.h\.in$ ^src/config\.status$ ^src/Makefile$ # e.g. doc/faq/OctaveFAQ.info # doc/interpreter/octave.info-4 ^doc/.*\.info(-\d)?$ ^doc/\w*/stamp-vti$ ^doc/\w*/version\.texi$ # Emacs tools create these (^|/)TAGS$ (^|/)semantic.cache$ # Other text editors often create these (^|/)~.* arduino-0.12.1/COPYING0000644000000000000000000010451314545566645011245 0ustar00 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. 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. Copyright (C) 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 . 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: Copyright (C) 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 . 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 . arduino-0.12.1/DESCRIPTION0000644000000000000000000000110414545566645011710 0ustar00Name: arduino Version: 0.12.1 Date: 2023-01-04 Author: John Donoghue Maintainer: John Donoghue Title: Octave Arduino Toolkit Description: Basic Octave implementation of the matlab arduino extension, allowing communication to a programmed arduino board to control its hardware. Categories: Arduino Toolkit Depends: octave (>= 4.0.0), instrument-control (>= 0.5.0) SystemRequirements: arduino-ide (>= 1.5) License: GPLv3+ Url: https://gnu-octave.github.io/octave-arduino/ Repository: https://github.com/gnu-octave/octave-arduino/ arduino-0.12.1/INDEX0000644000000000000000000000655414545566645011012 0ustar00arduino >> Arduino Toolkit General Functions arduinosetup isarduino listArduinoLibraries scanForArduinos Arduino Functions @arduino/checkI2CAddress @arduino/configurePin @arduino/configurePinResource @arduino/decrementResourceCount @arduino/delete @arduino/disp @arduino/getEndian @arduino/getI2CTerminals @arduino/getInterruptTerminals @arduino/getLEDTerminals @arduino/getMCU @arduino/getPWMTerminals @arduino/getPinAlias @arduino/getPinInfo @arduino/getPinsFromTerminals @arduino/getResourceCount @arduino/getResourceOwner @arduino/getSPITerminals @arduino/getServoTerminals @arduino/getSharedResourceProperty @arduino/getTerminalMode @arduino/getTerminalsFromPins @arduino/incrementResourceCount @arduino/isTerminalAnalog @arduino/isTerminalDigital @arduino/playTone @arduino/readAnalogPin @arduino/readDigitalPin @arduino/readVoltage @arduino/reset @arduino/sendCommand @arduino/setSharedResourceProperty @arduino/uptime @arduino/validatePin @arduino/version @arduino/writeDigitalPin @arduino/writePWMDutyCycle @arduino/writePWMVoltage @arduino/arduino Arduino I2C Functions scanI2Cbus @i2cdev/delete @i2cdev/disp @i2cdev/read @i2cdev/readRegister @i2cdev/subsref @i2cdev/write @i2cdev/writeRegister @i2cdev/i2cdev @device/delete @device/disp @device/read @device/readRegister @device/subsref @device/write @device/writeRegister Arduino Rotary Encoder Functions @rotaryEncoder/delete @rotaryEncoder/disp @rotaryEncoder/readCount @rotaryEncoder/readSpeed @rotaryEncoder/resetCount @rotaryEncoder/subsref @rotaryEncoder/rotaryEncoder Arduino Servo Functions @servo/delete @servo/disp @servo/readPosition @servo/subsref @servo/writePosition @servo/servo Arduino Shiftregister Functions @shiftRegister/delete @shiftRegister/disp @shiftRegister/read @shiftRegister/reset @shiftRegister/write @shiftRegister/subsref @shiftRegister/shiftRegister Arduino SPI Functions @spidev/delete @spidev/disp @spidev/subsref @spidev/writeRead @spidev/spidev @device/delete @device/disp @device/subsref @device/writeRead Arduino Serial Functions @device/delete @device/disp @device/flush @device/read @device/subsref @device/write @device/device Arduino Device Functions @device/delete @device/disp @device/flush @device/read @device/readRegister @device/subsref @device/write @device/writeRead @device/writeRegister @device/device Arduino Ultrasonic Functions @ultrasonic/delete @ultrasonic/disp @ultrasonic/subsref @ultrasonic/readDistance @ultrasonic/readEchoTime @ultrasonic/ultrasonic Arduino Addons addon arduinoioaddons.ExampleAddon.Echo arduinoioaddons.ExampleLCD.LCD arduinoioaddons.EEPRomAddon.EEPRom arduinoioaddons.RTCAddon.DS1307 arduinoioaddons.adafruit.motorshieldv2 arduinoioaddons.adafruit.dcmotorv2 arduinoioaddons.adafruit.stepper arduinoioaddons.SimpleStepper.SimpleStepper Arduino Sensors arduinosensor.DS1307 arduinosensor.MPC3002 arduinosensor.SI7021 arduinosensor.GUVAS12SD Arduino I/O package arduinoio.AddonBase arduinoio.FilePath arduinoio.LibFiles arduinoio.LibraryBase arduinoio.getBoardConfig Matlab Compatibility Classes matlabshared.addon.LibraryBase Sensors bme280 bno055 lis3dh lps22hb lsm6dso mpu6050 si7021 Test Functions arduino_bistsetup arduino-0.12.1/NEWS0000644000000000000000000001403614545566645010711 0ustar00Summary of important user-visible changes for arduino 0.12.1: ------------------------------------------------------------------- ** Bugfix for scanForArduinos to ensure release of serial port ** Use disp not display for object display functionality Summary of important user-visible changes for arduino 0.12.0: ------------------------------------------------------------------- ** Minor doc changes ** New Board Configurations: - Arduino Nano ESP32 ** Support for different communication baudrates ** Added additional scanForArduinos functionality ** expanded search for arduino binary Summary of important user-visible changes for arduino 0.11.0: ------------------------------------------------------------------- ** New board configurations: - Arduino Uno WIFI r4 - Arduino Uno Minima r4 ** Minor doc updates Summary of important user-visible changes for arduino 0.10.0: ------------------------------------------------------------------- ** New board configurations: - ESP32 Dev ** Doc corrections for using addons ** @arduino/arduino - added 'forcebuildon' input property Summary of important user-visible changes for arduino 0.9.1: ------------------------------------------------------------------- ** @arduino/playTone: fix bitshifted values (Bug #62538) ** Save/Restore arduinobinary to prefs arduino.arduino_binary. Summary of important user-visible changes for arduino 0.9.0: ------------------------------------------------------------------- ** @arduino/arduino - added ability to connection via ip address ** Core Libraries - added initial Wifi connectivity ** added sensors - bme280 - bno055 - lis3dh - lps22hb - lsm6dso - mpu6050 - si7021 ** added addons - SimpleStepper ** added QT docs Summary of important user-visible changes for arduino 0.8.0: ------------------------------------------------------------------- ** New board configurations: - Raspberry Pi Pico - Arduino Nano RP2040 Connect - Arduino MKR1000 ** New functions: - @arduino/getEndian ** @device/read and writeXXXXX: - only fix endian when host and device do not match ** updates for closer matlab code compatibility ** updates for octave 7 compatibility Summary of important user-visible changes for arduino 0.7.0: ------------------------------------------------------------------- ** New board configurations: - Arduino Due - Arduino MKRZero - Arduino Nano 33 BLE ** @arduino/arduino - added analogreference property - added matlab compatible property names - playTone duration bug fix ** New functions: - @arduino/getPinAlias ** Core Libraries: - provide basic debugPrint function - support multiple i2c device buses correctly - support differing spi device settings - use global error messages for common errors Summary of important user-visible changes for arduino 0.6.0: ------------------------------------------------------------------- ** New functions: - arduinoio.LibraryBase/sendCommand override ** Modified functions: - added debug mode to scanForArduinos ** spidev, i2c, servo, rotaryEncoder, ultrasonic, shiftRegister and device are now classdef objects ** minor function documentation updates ** minor updates to support octave 6 compatibility Summary of important user-visible changes for arduino 0.5.0: ------------------------------------------------------------------- ** Modified functions: - return fraction of time for rotaryEncoder.readCount (Bug #56377) ** New functions: - @arduino/getInterruptTerminals ** new classes - @ultrasonic - @device ** Depreciated - @spidev - use @device - @i2cdev - use @device ** New board configurations: - Arduino Pro Micro - Arduino Leonardo - Arduino Micro - Arduino Nano Every Summary of important user-visible changes for arduino 0.4.0: ------------------------------------------------------------------- ** New addons - adafruit.motorshieldv2 ** New functions: - @arduino/checkI2CAddress - arduino_bistsetup ** Modified functions: - added optional libtype specifier to listArduinoLibraries - bugfix to core subsref functions - updated property compare on core - attempt to use user arduino preferences as back up for arduino binary find - get full windows port for scanForArduinos, no case compare for board type ** minor function documentation updates ** Added sensors package: - arduinosensor.DS1307 - arduinosensor.MPC3002 - arduinosensor.SI7021 - arduinosensor.GUVAS12SD Summary of important user-visible changes for arduino 0.3.0: ------------------------------------------------------------------- ** added getLibName, setup and loop functions to LibraryBase ** Modified functions: - implemented playTone - added forcebuild property to arduino - @spidev/writeRead uses transaction based transfers - @spidev/spidev allow any CS pin to be used - @i2cdev/readRegister return data only ** New functions: - @rotationalEncoder - @arduino/getPinInfo - @arduino/uptime - @arduino/version - @arduino/getSharedResourceProperty - @arduino/setSharedResourceProperty - arduinoio.AddonBase - isarduino ** New addons - ExampleLCD.LCD - EEPRomAddon.EEPRom - RTCAddon.DS1307 ** minor function documentation updates ** New board configurations: - Arduino Pro/Pro Mini - Arduino Nano - Lilypad ** updated to arduinoaddons to query using metadata Summary of important user-visible changes for arduino 0.2.0: ------------------------------------------------------------------- ** update arduinosetup for windows arduino ide changes ** bug fixes for use with older versions of octave ** bug fix mode config in flash ** added initial support for additional board types: - ARM sparkfun SAMD21 dev board ** added manual Summary of important user-visible changes for arduino 0.1.0: ------------------------------------------------------------------- ** Initial release arduino-0.12.1/README.md0000644000000000000000000000646314545566645011476 0ustar00
Octave Arduino Toolkit
---------------------- --- Introduction ============ This is a basic implementation of the Matlab toolkit extension. It attempts to provide the same function calls as the Matlab toolkit, as well as additional functionality, **HOWEVER**, it is not binary compatible with matlab. (ie: you must program the arduino with the GNU octave code to commuicate with the octave arduino toolkit). Requirements ============ The arduino toolkit requires the [Arduino IDE](https://www.arduino.cc/en/software) for programming the arduino board, and the [instrument-control toolkit](https://octave.sourceforge.io/instrument-control/index.html) to communicate to the board. Installing ========== To install, run the octave package manager: 1. To install from source forge: `pkg install -forge arduino` 2. To install from a local tarball. `pkg install arduino-XXXXXXX.tar.gz` Where XXXXXXX is the version of the the downloaded tarball. Usage: ====== 1. Load the arduino package. `pkg load arduino` 2. If the arduino board is not programmed, program it with the arduino communication software. `arduinosetup` Additional libraries can be programmed with it. Use the listArduinoLibraries to retrieve a list of known libraries. 3. Open a connection to the arduino `a = arduino ()` **NOTE**: the board MUST be programmed before the ardino function call will be abele to open the board connection. 4. Use the arduino function calls to control arduino hardware. See the function list and examples directories. Expanding the known board types =============================== Currently the toolkit recognizes these boards: * due * esp32 dev * leonardo * lilypad * mega2560 * micro * mkrzero * mkr1000 * nano * nano every * nano 33 ble * nano rp2040 connect * nano esp32 * promini * promicro * raspberry pi pico * sparkfunsamd21 * uno minima r4 * uno wifi rev2 * uno wifi r4 * uno Additional boards can usually be added with minimal code changes. To add an additional board: 1. The arduino core library (code programmed to the arduino) must provide a board id that is unique and matches the config id. 2. The arduinoio.boardTypeString function must return the board name when provided the id. 3. A config_.m file must be present as arduinoio.config.config_, which describes the pin functionality for the board. A Matlab script in available in arduino toolkit sources that to create 90% of the config file based on the arduino_pins header file from the arduino ide. Adding additional addon libraries ================================= Addon libraries can be created using a similar interface as the Matlab toolkit, or use existing Matlab code with minor changes. Known limitations and bugs ========================== 1. Octave does not document classdef files, so documentation for the arduino class and arduinoio.LibraryBase is not created in the function reference, however is in the reference manual. 2. Octave has issues with displaying function help after the classdef constructor is called, and may not show the help for a given function. 3. Communication between the arduino and Octave occurs only during arduino function calls, so data may be lost if the arduino sends additional information that is not read fast enough. arduino-0.12.1/doc/0000755000000000000000000000000014545566645010753 5ustar00arduino-0.12.1/doc/arduino.css0000644000000000000000000000133714545566645013132 0ustar00pre.example, .header, .float-caption, hr { /* base00 ~ body text in light solarized theme */ color: #657b83; border-color: #657b83; } pre.example { /* base3 ~ background color in light solarized theme */ background-color: #fdf6e3; padding: 0.5em; } table.cartouche { border: 1px solid #948473; background-color: #FFE3C6; width: 100%; } table.cartouche td, table.cartouche th { border: 1px solid #948473; padding: 4px 4px; } /* newer texinfo generation styles */ div.example { /* base00 ~ body text in light solarized theme */ color: #657b83; border-color: #657b83; } pre.example-preformatted { /* base3 ~ background color in light solarized theme */ background-color: #fdf6e3; padding: 0.5em; } arduino-0.12.1/doc/arduino.html0000644000000000000000000162477714545566645013332 0ustar00 Arduino Toolkit - a somewhat Matlab compatible arduino toolkit for GNU octave.

Introduction

The Arduino toolkit is a somewhat Matlab compatible arduino toolkit for GNU octave.

Table of Contents


1 Installing and loading

The Arduino toolkit must be installed and then loaded to be used.

It can be installed in GNU Octave directly from octave-forge, or can be installed in an off-line mode via a downloaded tarball.

NOTE

The toolkit requires the Arduino IDE in order to program Arduino devices.

NOTE

The toolkit has a dependency on the instrument-control package, so it must be installed in order to successfully install the Arduino toolkit

The toolkit must be then be loaded once per each GNU Octave session in order to use its functionality.

1.1 Online Direct install

With an internet connection available, the Arduino package can be installed from octave-forge using the following command within GNU Octave:

pkg install -forge arduino

The latest released version of the toolkit will be downloaded and installed.

1.2 Off-line install

With the arduino toolkit package already downloaded, and in the current directory when running GNU Octave, the package can be installed using the following command within GNU Octave:

pkg install arduino-0.12.1.tar.gz

1.3 Loading

Regardless of the method of installing the Arduino toolkit, in order to use its functions, the toolkit must be loaded using the pkg load command:

pkg load arduino

The toolkit must be loaded on each GNU Octave session.


2 Hardware setup

In order to use the arduino hardware with the toolkit, it must be programmed with special firmware.

2.1 Programming the Arduino

To program the hardware, using a default configuration, run the arduinosetup command:

arduinosetup

A temporary Arduino project will be created, with the Arduino toolkit files copied to it and the Arduino IDE will open.

Set the board type and port correctly for the connected Arduino and press the upload button on the IDE.

The sources will be compiled and then uploaded to the connected arduino board.

After successful upload the Arduino IDE should be closed.

NOTE

The arduino programming is not compatible with the Matlab arduino library, so must be programmed by the Octave Arduino toolkit to communicate to the arduino, even if it was previously used to work with Matlab.

NOTE

The toolkit requires the Arduino IDE in order to program the Arduino device.

The binary can set using the ’arduinobinary’ property when running setup.

For arduino IDEs before version 2, if the toolkit can not find the IDE, run the IDE manually, close it and retry programming the Arduino. Otherwise, use the ’arduino’ binary property.

2.2 Known Arduino Board Types

The board type must be known in order to successfully detect and connect to the Arduino board after programming.

Currently, known boards are:

  • Arduino Due
  • Arduino UNO
  • Arduino Mega 2560
  • Arduino Nano
  • Arduino Nano Every
  • Arduino Nano 33 BLE
  • Arduino Nano RP2040 Connect
  • Arduino Pro/Pro Mini
  • Arduino Pro Micro
  • Arduino Leonardo
  • Arduino Micro
  • Arduino MKR1000
  • Arduino MKRZero
  • Sparkfun SAMD21
  • Arduino Lilypad
  • Arduino UNO WiFi rev2

    NOTE

    The Arduino servo library code may require modifications to eliminate conflicts between servos and the tone library

  • Arduino UNO WiFi r4
  • Arduino UNO Minima r4
  • Raspberry Pi Pico
  • EPS32 Dev

Additional boards can be added easily, however require minor code changes.


3 Connecting to an arduino

To control an arduino device, a connection must be made to it by creating an arduino object.

3.1 Connecting to a single arduino

Assuming a single arduino device is connected to the computer, creating an arduino object with no arguments will find the connected arduino and connect to it:

ar = arduino()

3.2 Connecting to a specific arduino

Where multiple arduinos may be connected to the computer, a specific board can be connected by specifying the name of the port it is connected to:

ar = arduino("/dev/ttyACM0")

The port name will be operating system dependent.

3.3 Querying available arduinos

To list the ports of all programmed available arduinos, the scanForArduinos function can be used:

scanForArduinos

It will provide a list of all available boards it can find with the port they are connected to.

NOTE

The scanForArduinos function will only detect boards that have been programmed using the arduinosetup command


4 Basic Input and Output Overview

Basic input and output can be performed on a connected arduino device using by calling the read and write functions for a specific named pin on the arduino.

A list of available pins can get found from the pins property of the connected arduino object and are also displayed as part of the default shown properties:

ar = arduino();
% get the pin names
pins = ar.availablepins

Pin generally follow a naming scheme of D<number> for digital pins and A<number> for analog pins.

Digital pins can be used to read and write digital data, but can not read analog voltages. Analog pins can perform digital I/O as well as reading voltages.

4.1 Performing Digital I/O

A pin’s digital logic value can be true (1) or false (0) and can be set using the writeDigitalPin function.

The following example attempts to set the D2 pin of the connected arduino object "ar" to true, waits 5 seconds and then sets it to false:

writeDigitalPin (ar,  "d2", true);
pause 5
writeDigitalPin (ar,  "d2", false);

Using the readDigitalPin will read the current logic state of the pin.

value = readDigitalPin (ar,  "d2");

4.2 Performing Analog Input

For analog pins, the voltage level can be read using a analog to digital conversion and will return a voltage level between 0 and the boards voltage (nominally 5V):

value = readVoltage (ar,  "a0");

The raw digital value of the pin can also be read instead of a voltage, giving a value between 0 and 2^x where x is the number of bits used by the analog to digital converter.

value = readAnalogPin (ar,  "a0");

5 Protocol based I/O Overview

The arduino toolkit supports more complex I/O for SPI, I2C, Servo control and more.

5.1 SPI communication

SPI communication can be performed by creating a SPI device object and then calling the writeRead function:

spi = device (ar,  "spichipselectpin", "d2");

The function call expects a connected arduino object as the first argument, followed by the chip select pin of the SPI device.

After a device is created, a write to device followed by read can can be made using the writeRead function:

spi = device (ar,  "spichipselectpin", "d2");
data = writeRead (spi,  100);

5.2 I2C communication

I2C communication can be performed by creating an I2C device object for a specific I2C address.

The following example creates an I2C device that will communicate with a I2C device at address 100"

i2c = device (ar,  "i2caddress", 100);

After creating an I2C device, data can be read and written using read, write, readRegister and writeRegister. The data to send and receive will be device dependent.

5.3 Servo communication

Servo communication can be performed after creating a servo device object to operate on a PWM pin:

servoobj = servo(ar, "d9", "minpulseduration", 1.0e-3, ...
  "maxpulseduration", 2e-3);

The servo function expects the connected arduino object and the PWM pin that the servo is connected to. Optional properties can be specified to control the setup of device.

In the example, the min and max pulse width values are set.

Using the servo object the current position and be read or set with values ranging between 0 to 1, with 0 being the minimum pulse width and 1 being the maximum.

The following example sets the servo to its middle position.

servoobj = servo(ar, "d9", "minpulseduration", 1.0e-3, ...
  "maxpulseduration", 2e-3);

writePosition (servoobj, 0.5);

5.4 Shift Registers

A shift register can be controlled by creating a shiftRegister object:

registerobj = shiftRegister(ar, '74hc164', "d2", "d3");

The parameters required are dependent on the type of shift register created.

Once a register object has been created, it can be read and written to using the read and write functions.

5.5 Rotary Encoders

A rotary encoder can be created by creating a rotaryEncoder object.

encoder = rotaryEncoder(ar, "d2", "d3", 180);

Using the created object, the rotary encoder value and speed can be read.

5.6 Ultrasonic Sensors

An ultrasonic sensor can be read by creating an ultrasonic object.

sensor = ultrasonic(ar, "d9", "d10");

Using the created object, the sensor distance and echo time and be read.

5.7 Serial communication

Serial communication can be performed on devices that support multiple serial devices such as the leonardo and mega2560 boards. The communications port to Octave is reserved and can not be used as a user controlled communications port.

Serial communication can be performed by creating a serial device object and then calling the read and write functions:

ser = device (ar,  "serial", 1);

The function call expects a connected arduino object as the first argument, followed "serial" and serial id.

After a device is created, the device can be read and written:

ser = device (ar,  "serial", 1);
write(ser, "hello");
data = read(ser, 100);

6 Addons Overview

This chapter provides an overview of the arduino package addon functionality for adding additional addons to arduino.

6.1 Addon Introduction

Addons provide a way of adding additional functionality to the arduino toolkit that provides Matlab access directly to the arduino hardware.

Addons are implemented in two parts.

  1. code running on the arduino that implements the required functionality
  2. a octave wrapper class that provides the Matlab interface and communication to the code.

Both parts are required to create a plugin.

The arduino toolkit provides a number of pre-created addons. These can be seen using the following command:


listArduinoLibraries

The command will display all known arduino libraries (addons as well as core libraries), however addons typically use a "foldername/classname" for this naming.

See also: listArduinoLibraries.

6.2 Creating an addon

An addon requires at minimum 3 things:

  1. A addon package directory that will contain the addon files
  2. A Matlab file within that directory that is a subclass of arduinoio.LibraryBase
  3. A arduino source/header file that contains the arduino code to load, sub-classed for LibraryBase

So the addon directory structure at a minimum will be:


  +arduinoioaddons  (dir) [somewhere in the octave load path]
    +MyAddons (dir)
      MyAddon1.m 
      MyAddon1.h

6.2.1 Addon package directory

The addon architecture looks for plugins in the octave load path in a package directory called +arduinoioaddons

So this directory must be created somewhere within the paths that octave will check for functions.

In addition, the addon architecture expects plugins to be contained in a sub directory within the +arduinoioaddons folder. The subdirectory must begin with a ’+’.

Multiple plugin .m files can be within the same sub directory.

6.2.2 Addon package .m file

The Matlab interface file within the addon directory provides the Matlab interface for the arduino code as well as provides information about the addon.

Class inheritance and required properties

The interface file must be a subclass of arduinoio.LibraryBase and must contain some constant properties values that provide the information.

A minimum example of required is below:


classdef MyAddon1 < arduinoio.LibraryBase
  properties(Access = protected, Constant = true)
    LibraryName = 'MyAddons/MyAddon1';
    CppHeaderFile = fullfile(arduinoio.FilePath(mfilename('fullpath')), 'MyAddon1.h');
    CppClassName = 'MyAddon1';
  endproperties
  .
  .
  .
endclassdef

The following constant properties can be set within the addon:

LibraryName

(Required) The name of the addon. My convention this is usually the directoryname / theclassname

CppHeaderFile

(Required) The header file for the arduino code

CppSourceFile

(Optional) The source file (if any) for the arduino code

CppClassName

(Required) The classname used within the cppheaderfile for the arduino library

DependantLibraries

(Optional) Any additional addons or cores that are needed for this library to be used

ArduinoLibraryHeaderFiles

(Optional) Any additional header files that need to be included

Class constructor

The Matlab class constructor will be called from the addon function when creating a instance of the addon and should initialize at least two properties in inherited from arduinoio.LibraryBase:

  1. Parent should be set to the first input argument (the arduino class)
  2. Pins should be set to a list of pins that are used for the plugin

classdef MyAddon1 < arduinoio.LibraryBase
  .
  .
  methods
    function obj = MyAddon1(parentObj, varargin)
      obj.Parent = parentObj;
      # no pins being used
      obj.Pins = [];
      # send any command to the arduino during setup ?
    endfunction
    .
    .
  endmethods
endclassdef

Class functions

The class functions will usually communicate to the arduino and use the response for what is returned to the user.

By convention, the commands sent to the arduino are defined as constants in the class file but do not have to be.


classdef MyAddon1 < arduinoio.LibraryBase
  properties(Access = private, Constant = true)
    INIT_COMMAND = hex2dec('00');
    FUNC1_COMMAND = hex2dec('01');
  endproperties
  .
  .
  methods
    function obj = MyAddon1(parentObj, varargin)
      obj.Parent = parentObj;
      # no pins being used
      obj.Pins = [];
      # send any command to the arduino during setup ?
      sendCommand(obj.Parent, obj.LibraryName, obj.INIT_COMMAND, []);
    endfunction

    function retval = func1(obj)
       cmdID = obj.FUNC1_COMMAND;
       retval = sendCommand(obj.Parent, obj.LibraryName, cmdID, []);
    endfunction
    .
    .
  endmethods
endclassdef

NOTE

the sendCommand uses the objects parent for the arduino, the objects library name and the command id

See also: sendCommand.

6.2.3 Addon package header file

The header file should contain a class that matches the functionally and information of the matlab file and provides the ability to register the code on the arduino.

The following things should occur in the arduino class files:

  1. The class name within the file must be the same as the one set in the .m file CppClassName property.
  2. The libName variable must be the same as the LibraryName property.
  3. The constructor should call registerLibrary
  4. the commandHandler function to act on cmdID values that match the commands that will be sent from .m file and send data back using sendResponseMsg
  5. on receiving unknown cmdID values, the commandHandler should use sendUnknownCmdIDMsg

An example, matching the previous .m file code is below:


#include "LibraryBase.h"

#define MYADDON1_INIT  0x00
#define MYADDON1_FUNC1 0x01

class MyAddon1 : public LibraryBase
{
  uint8_t cnt;
public:
  MyAddon1(OctaveArduinoClass& a)
  {
    libName = "MyAddons/MyAddon1";
    a.registerLibrary(this);
  }
  void commandHandler(uint8_t cmdID, uint8_t* data, uint8_t datasz)
  {
    switch (cmdID)
      {
      case MYADDON1_INIT:
        {
          cnt = 0;
          sendResponseMsg(cmdID, 0,0);
          break;
        }
      case MYADDON1_FUNC1:
        {
          // func 1 is just returning a uint8 count of number of times called
          cnt ++;
          sendResponseMsg(cmdID, &cnt, 1);
          break;
        }
      default:
        {
          // notify of invalid cmd
          sendUnknownCmdIDMsg();
        }
      }
  }
}
;

The body of functions can be in the CppSourceFile file is it is defined or within the header file as illustrated above.

6.2.4 Verify octave can see the addon

Use the listArduinoLibaries command to verify that the new addon appears in the list of known libraries.

If it does not, ensure that the +arduinoioaddons directory is within one of the octave class paths, and that the directory structure and inheritance requirements have been met.

6.3 Using addons

6.3.1 Programming the arduino with the addon

To use a addon, the code must be programmed onto the arduino.

Using the libraries command, when creating a arduino object, the arduino can be reprogrammed if the library does not already exist on the arduino.


  ar = arduino([],[], 'libraries', 'MyAddons/MyAddon1', 'forcebuild', true)

The libraries property of the arduino object should list the libraries programmed on the arduino.

Alternatively, the library can be added using the libraries property and arduinosetup

See also: arduino, arduinosetup.

6.3.2 Creating a addon object

An object of the addon type can be created using the addon command.


  ar = arduino([],[], 'libraries', 'MyAddons/MyAddon1', 'forcebuild', true)
  obj = addon(ar, "MyAddons/MyAddon1");


7 Sensors Overview

There are two types of sensors available:

  1. Matlab compatible(ish) sensors for environment and IMU.
  2. Additional lightweight wrappers for some chips in a arduinosensor namespace.

7.1 Matlab Compatible Sensors

7.1.1 Overview

Matlab compatible functions are provided for a number of sensors, using a similar function naming as provided by the Matlab arduino package.

7.1.2 Available Sensors

The functions for each sensor is listed in the function reference, Sensors and provides for:

bme280

BME280 temperature, pressure and humidity sensor

bno005

BNO055 acceleration, angular velocity, orientation and magnetic field sensor

lis3dh

LIS3DH acceleration sensor

lps22hb

LPS22HB temperature and pressure sensor

lsm6dso

LSM6DSO acceleration, angular velocity sensor

mpu6050

MPU-6050 acceleration, angular velocity sensor

SI7021

SI7021 temperature and humidity sensor

7.2 Lightweight Arduino Sensors

7.2.1 Overview

Arduino sensors are a collection of lightweight wrappers around other underlying protocols for providing specific sensor functionality.

For instance a DS1307 chip communicates using I2C protocol and so a DS1307 class exists that provides the conversion/commands in order to communicate to the chip.

Using the class, providing the functionality is very easy:


a = arduino()
rtc = arduinosensor.DS1307(a)
# get and display rtc time as a date string
datestr(rtc.clock)

It is lightweight compared to the addon functionality, as it only requires a wrapper class rather than add on code, however it is limited to then using available addon and core codes rather than creating new ones.

Currently the are only a small number of sensors available, however this will be built upon in future versions.

7.2.2 Available Sensors

The functions for each sensor is listed in the function reference, Arduino Sensors and provides for:

DS1307

DS1307 RTC clock using i2c.

MPC3002

MPC3002 ADC using SPI

SI7021

SI7021 temperature and humidity sensor

GUVAS12SD

GUVAS12SD analog UV-B sensor


8 Examples

8.1 Blinking an LED

This example shows blinking the inbuilt LED on the Arduino board. Code is available by running:

edit examples/example_blink

Hardware setup

This example uses in the builtin LED, so requires only a connection of the Arduino board to computer for communication.

Create an Arduino object

ar = arduino ();

If you have more than one Arduino board connected, you may need to specify the port in order to connect to the correct device.

Query Device for pins connected to builtin LED

The pin connected to the Arduino UNO built in led if D13.

led_pin = "d13";

The connected pins can be queried programatically if desired.

pins = getLEDTerminals (ar);

Connected to a Arduino UNO would return a list pins containing only one item ’13’.

The terminal number can be converted to a pin using getPinsFromTerminals:

led_pin = getPinsFromTerminals (ar, pins{1});

Turn the LED off

Write a 0 value to the pin to turn it off.

writeDigitalPin (ar, led_pin, 0);

Turn the LED on

Write a 1 value to the pin to turn it on

writeDigitalPin (ar, led_pin, 1);

Add a while loop with a pause between the changes in the pin state to blink.

while true
  writeDigitalPin (ar, led_pin, 0);
  pause (0.5)
  writeDigitalPin (ar, led_pin, 1);
  pause (0.5)
endwhile

8.2 Using I2C to communicate with an EEPROM

This example shows using I2C to communicate with a EEPROM chip. Code is available by running:

edit examples/example_i2c_eeprom

Hardware setup

Using an Arduino UNO, the board should be configured with the following connections between the board and a 24XX256 EEPROM chip:

A4

Connected to pin 5 of EEPROM

A5

Connected to pin 6 of EEPROM

5V

Connected to pin 8 of EEPROM

GND

Connected to pin 1,2,3,4 of EEPROM

Create an Arduino object

ar = arduino ();

If you have more than one Arduino board connected, you may need to specify the port in order to connect to the correct device.

Query I2C pins

Display the I2C terminals of the board:

getI2CTerminals(ar)

Scan the arduino for the connected device

scanI2Cbus(ar)

The devices listed should contain 0x50, the address of the EEPROM chip.

Create an I2C object to communicate to the EEPROM

eeprom = device (ar, "i2caddress", 0x50)

Write data to the EEPROM

The EEPROM expects the first byte to be the page number, the second the offset, followed by data, so to write 1 2 3 4, starting address 0 (page 0, offset 0):

write(eeprom, [0 0 1 2 3 4])

Reading from the EEPROM

Reading from the EEPROM requires first writing the address to read from, in this case, if we want to read the 3, 4, this would be page 0, offset 2:

write(eeprom, [0 2])

Next read the 2 bytes:

data = read(eeprom, 2)

8.3 Using SPI to communicate with a mcp3002 10 bit ADC

This example shows using SPI to communicate with an mcp3002 10 bit ADC. Code is available by running:

edit examples/example_spi_mcp3002

Hardware setup

Using an Arduino UNO, the board should be configured with the following connections between the board and a mcp3002 chip:

D10

Connected to pin 1 (CS) of MCP3002

D11

Connected to pin 5 (DI) of MCP3002

D12

Connected to pin 6 (DO) of MCP3002

D13

Connected to pin 7 (CLK) MCP3002

VCC

Connected to pin 8 (VDD) MCP3002

GND

Connected to pin 4 (VSS) MCP3002

Analog input

Connected from pin 2 of the MCP3002 to a LOW (< 5V) voltage to measure

Create an Arduino object

ar = arduino ();

If you have more than one Arduino board connected, you may need to specify the port in order to connect to the correct device.

Create an SPI object to communicate to the MCP3002

adc = device(ar, "spichipselectpin", "d10")

The d10 is the chip select pin connected from the Arduino to the MCP3002.

Read the ADC

The MCP3002 expects specific commands in order to read a channel.

For illustration for the command to read chan 0 in single ended mode:

command (bits) in MSB mode to device:
[START SGL ODN MSBF X X X X] [ X X X X X X X X ] 
   1    1   0    1   1 1 1 1    1 1 1 1 1 1 1 1 
      [chan 0 ] MSB    
data back:
   X    X  X     X   X 0 D D    D D D D D D D D

D is a output data bit

X is a don’t care what value is input/output

The first byte contains the command and start of the data read back, the second bytes is written to clock out the rest of the ADC data.

In hex, this corresponds to 0xDF 0xFF,

data = writeRead(adc, [hex2dec("DF") hex2dec("FF")])

Of the data returned, the last 10 bits is the actual data, so convert data to a 16 bit value:

val = uint16(data(1))*256 + uint16(data(2))

Then bitand it to remove the non value parts, to get the ADC value:

val = bitand (val, hex2dec('3FF'))

To make the value correspond to a voltage it needs to be scaled as 0 will be 0 Volts, 1023 will be 5 Volts.

volts = double(val) * 5.0 / 1023.0;

9 Function Reference

The functions currently available in the Arduino toolkit are described below;


9.1 General Functions

9.1.1 arduinosetup

: retval = arduinosetup ()
: retval = arduinosetup (propertyname, propertyvalue)

Open the arduino config / programming tool to program the arduino hardware for usage with the Octave arduino functions.

arduinosetup will create a temporary project using the arduino IDE and allow compiling and programming of the code to an arduino.

Inputs

propertyname, propertyvalue - A sequence of property name/value pairs can be given to set defaults while programming.

Currently the following properties can be set:

libraries

The value should be the name of a library, or string array of libraries to program on the arduino board.

arduinobinary

The value should be the name/path of the arduino IDE binary for programming. If not specified, the function will use getpref preferences of arduino.arduino_binary, and if not found, the function will attempt to find the binary itself.

If provided, the value will be saved to preferences for future calls.

Outputs

retval - return 1 if arduino IDE returned without an error

See also: arduino, __arduino_binary__.

9.1.2 isarduino

: retval = isarduino (obj)

Check if input value is an arduino object

Function is essentially just a call of retval = isa(obj, "arduino");

Inputs

obj - The object to check

Outputs

retval is true, if obj is an arduino object, false otherwise.

See also: arduino.

9.1.3 listArduinoLibraries

: retval = listArduinoLibraries ()
: retval = listArduinoLibraries (libtypes)

Retrieve list of all known arduino library modules that are available.

Inputs

libtypes - optional specifier for type of libraries to list.

Options are:

all

List core and addons

core

List core only libraries

addons

List addons only

When no libtypes is specified, all libraries are shown.

Outputs

retval is an cell array of string library names that are available for programming to the arduino.

See also: arduino, arduinosetup.

9.1.4 scanForArduinos

: retval = scanForArduinos ()
: retval = scanForArduinos (maxCount)
: retval = scanForArduinos ("debug")
: retval = scanForArduinos (maxCount, type)
: retval = scanForArduinos (propertyname, propertvalue ...)

Scan system for programmed serial connected arduino boards.

scanForArduinos will scan the system for programmed arduino boards and return at most maxCount of them as a cell array in retval.

Inputs

maxCount - max number of arduino boards to detect. if maxCount is not specified, or is a less than 1, the function will return as many arduino boards as it can detect.

type - optional board type to match. If specified, the board type must match for the arduino to be added to the return list.

"debug" - if single input parameter is "debug", the scanForArduinos will display debug information as it scans all available ports for arduinos.

propertyname, propertyvalue - property name/value pairs to match search with.

’BaudRate’

Numeric BaudRate to use when trying to scan for arduinos.

’MaxCount’

Max number of arduinos to scan for.

’BoardType’

Boardtype to match.

’Debug’

Logical flag for debug mode.

Outputs

retval structure cell array of matching detected arduino boards.

Each cell value of the cell array will contain a structure with values of:

port

the serial port the arduino is connected to

board

the board type of the arduino

See also: arduino.


9.2 Arduino Functions

9.2.1 @arduino/arduino

: retval = arduino ()
: retval = arduino (port)
: retval = arduino (port, board)
: retval = arduino (port, board[, [propname, propvalue]*)
: retval = arduino (iaddress)
: retval = arduino (ipaddress, board)

Create a arduino object with a connection to an arduino board.

Inputs

port - full path of serial port to connect to. For Linux, usually /dev/ttySXXX, for windows COMXX.

board - name of board to connect (default is ’uno’).

propname, propvalue - property name and value pair for additional properties to pass to the creation of the arduino object.

Currently properties are ignored, with the exception of:

debug

true / false flag for whether setting debug (default false)

forcebuildon

true / false flag for whether to force show of the arduino IDE to rebuild the installed code on the arduino (default false)

baudrate (read only)

the communications baudrate to the board. (default 9600)

libraries

The libraries to be enabled on the arduino board. (default uses whatever is already installed)

if the arduino function is called without parameters, it will scan for the first available arduino it can find and connect to it.

Outputs

retval - a successfully connected arduino object.

Properties

The arduino object has the following public properties:

name

name assigned to the arduino object

debug

true / false flag for whether debug is turned on

forcebuildon

true / false flag for whether to force show of the arduino IDE to reprogram the arduino

port (read only)

the communications port the board is connected to.

baudrate (read only)

the communications baudrate to the board.

board (read only)

The name of the board type that the arduino connected to

libraries (read only)

The libraries currently programmed onto the board

availablepins

The pins available for use on the board

analogreference

The analog voltage reference

See also: scanForArduinos, arduinosetup.

9.2.2 @arduino/checkI2CAddress

: retval = checkI2CAddress (ar, address)
: retval = checkI2CAddress (ar, address, bus)

Check that an address of given address responds on the I2C bus

Inputs

ar - arduino object connected to a arduino board.

address - I2C address number to check

bus - bus number to check for I2C device, when multiple buses are available. If the bus is not specified, it will default to 0.

Outputs

retval - boolean value of true if address responds on the I2C bus

Example


 # create arduino connection.
 ar = arduino();
 # scan for devices on the I2C bus
 checkI2CAddress (ar)
 # output if a device using that address is attached
 ans =
   1
 

See also: arduino, scanI2Cbus.

9.2.3 @arduino/configurePin

: currmode = configurePin (ar, pin)
: configurePin (ar, pin, mode)

Set/Get pin mode for a specified pin on arduino connection.

configurePin (ar, pin) will get the current mode of the specified pin.

configurePin (ar, pin, mode) will attempt set the pin to the specified mode if the mode is unset.

Inputs

ar - the arduino object of the connection to an arduino board.

pin - string name of the pin to set/get the mode of.

mode - string mode to set the pin to.

Outputs

mode - string current mode of the pin.

Valid modes can be:

  • AnalogInput - Acquire analog signals from pin
  • DigitalInput - Acquire digital signals from pin
  • DigitalOutput - Generate digital signals from pin
  • I2C - Specify a pin to use with I2C protocol
  • Pullup - Specify pin to use a pullup switch
  • PWM - Specify pin to use a pulse width modulator
  • Servo - Specify pin to use a servo
  • SPI - Specify a pin to use with SPI protocol
  • Interrupt - Specify a pin to use for with interrupts
  • Reserved - Specify a pin to be reserved
  • Unset - Clears pin designation. The pin is no longer reserved and can be automatically set at the next operation.

See also: arduino.

9.2.4 @arduino/configurePinResource

: currmode = configurePinResource (ar, pin)
: configurePinResource (ar, pin, owner, mode)
: configurePinResource (ar, pin, owner, mode, force)

Set/Get pin mode for a specified pin on arduino connection.

configurePinResource (ar, pin) will get the current mode of the specified pin.

configurePinResource (ar, pin, owner, mode) will attempt set the pin to the specified mode and owner.

If the pin is already owned by another owner, the configure will fail unless the force option is used. If the mode is already set, configure will fail unless force is used.

Inputs

ar - the arduino object of the connection to an arduino board.

pin - string name of the pin to set/get the mode of.

mode - string mode to set the pin to.

owner - string name to use as the pin owner.

force - boolean to force mode change. If not set, it will be false.

Outputs

currmode - current string mode of the pin.

Valid modes can be:

  • AnalogInput - Acquire analog signals from pin
  • DigitalInput - Acquire digital signals from pin
  • DigitalOutput - Generate digital signals from pin
  • I2C - Specify a pin to use with I2C protocol
  • Pullup - Specify pin to use a pullup switch
  • PWM - Specify pin to use a pulse width modulator
  • Servo - Specify pin to use a servo
  • SPI - Specify a pin to use with SPI protocol
  • Interrupt - Specify a pin to use with interrupts
  • Reserved - Pin marked reserved, but not for of any particular mode
  • Unset - Clears pin designation. The pin is no longer reserved and can be automatically set at the next operation.

See also: arduino, configurePin.

9.2.5 @arduino/decrementResourceCount

: count = decrementResourceCount (ar, resource)

Decrement the count of a named resource by 1 and return the new count.

Inputs

ar - connected arduino object

resource - name of resource to decrement count.

Outputs

count = count of uses registered to resource.

See also: getResourceCount. incrementResourceCount.

9.2.6 @arduino/delete

: delete (dev)

Free resources of an arduino object.

Inputs

dev - object to free

See also: arduino.

9.2.7 @arduino/disp

: disp (ar)

Display the arduino object in a verbose way, showing the board and available pins.

Inputs

ar - the arduino object.

If the arduino object has debug mode set, additional information will be displayed.

See also: arduino.

9.2.8 @arduino/getEndian

: mcu = getEndian (ar)

Get the endian used by the connected arduino.

Inputs

ar - arduino object connected to a arduino board.

Outputs

endian - string representing the endian used by the arduino board.

’L’ means little endian, ’B’ means big endian

See also: arduino, getMCU.

9.2.9 @arduino/getI2CTerminals

: pinlist = getI2CTerminals (ar)
: pinlist = getI2CTerminals (ar, bus)

Get a cell list of pin Ids available are used for I2C mode.

Inputs

ar - the arduino object.

bus - optional bus number 0 or 1 for boards that support more than 1 bus.

Outputs

pinlist - cell list of pin numbers available for I2C use.

See also: arduino.

9.2.10 @arduino/getInterruptTerminals

: pinlist = getInterruptTerminals (ar)

Get a cell list of pin Ids available have interrupt functionality

Inputs

ar - the arduino object.

Outputs

pinlist - cell list of pin numbers available for interrupt use.

See also: arduino.

9.2.11 @arduino/getLEDTerminals

: pinlist = getLEDTerminals (ar)

Get a cell list of pin Ids available are connected natively to LEDs.

Inputs

ar - the arduino object.

Outputs

pinlist - cell list of pin numbers available for LED use.

See also: arduino.

9.2.12 @arduino/getMCU

: mcu = getMCU (ar)

Get the MCU used by the connected arduino.

Inputs

ar - arduino object connected to a arduino board.

Outputs

mcu - string representing the mcu used by the arduino board.

See also: arduino.

9.2.13 @arduino/getPWMTerminals

: pinlist = getPWMTerminals (ar)

Get a cell list of pin Ids available for PWM use.

Inputs

ar - the arduino object.

Outputs

pinlist - cell list of pin numbers available for PWM use.

See also: arduino.

9.2.14 @arduino/getPinAlias

: ouy = getPinAlias (ar, pin)

Get the pin actual pin name from a pin alias.

For example, the arduino Leonardo, pin "D4" is also "A6".

Inputs

ar - the connected arduino object.

pin - a pin name.

Outputs

out - alias pin name, or same as pin if the pin doesnt have any alias names.

See also: arduino, configurePinResource, getResourceOwner.

9.2.15 @arduino/getPinInfo

: pininfo = getPinInfo (ar, pin)
: pininfoarray = getPinInfo (ar, pinarray)

Get the pin information from the input pins values.

getPinInfo (ar, pin) will get information for a single pin.

getPinInfo (ar, pinarray) will get a cell array of pin information

Inputs

ar - the connected arduino object.

pin - a pin number or pin name.

pinarray - the array of pin numbers or names

The pininfo struct contains the following fields:

terminal

Terminal number of the pin

name

String name of the pin

owner

Current item owner of the pin

mode

Current configured mode for the pin

Outputs

pininfo - struct on pin information.

pininfolist - cell array of pin info

See also: arduino, configurePinResource, getResourceOwner.

9.2.16 @arduino/getPinsFromTerminals

: pinnames = getPinsFromTerminals (ar, terminals)

Get the pin names from the input terminal values.

Inputs

ar - the connected arduino object.

terminals - the numeric pin number, or array of pin numbers to get pin names.

Outputs

pinnames - the string names of each input pin. If terminals was a single value, the return will be a single string, otherwise it will return a cell array of each pin name.

See also: arduino, getTerminalsFromPins.

9.2.17 @arduino/getResourceCount

: count = getResourceCount (ar, resource)

Get the count of uses of a given resource.

Inputs

ar - connected arduino object

resource - name of resource to get count for.

Outputs

count = count of uses registered to resource.

See also: incrementResourceCount. decrementResourceCount.

9.2.18 @arduino/getResourceOwner

: owner = getResourceOwner (ar, terminal)

Get the owner of pin allocated previously by configurePinResource.

Inputs

ar - connected arduino object

terminal - terminal number to get owner of.

Outputs

owner = owner of the terminal pin, or "" if not owned.

See also: configurePinResource.

9.2.19 @arduino/getSPITerminals

: pinlist = getSPITerminals (ar)

Get a cell list of pin Ids available for SPI mode.

Inputs

ar - the arduino object.

Outputs

pinlist - cell list of pin numbers available for SPI use.

See also: arduino.

9.2.20 @arduino/getServoTerminals

: pinlist = getServoTerminals (ar)

Get a cell list of pin Ids available for servo use.

Inputs

ar - the arduino object.

Outputs

pinlist - cell list of pin numbers available for servo use.

See also: arduino, getPWMTerminals.

9.2.21 @arduino/getSharedResourceProperty

: count = getSharedResourceProperty (ar, resource, property)

Get the value of a property from a given resource.

Inputs

ar - connected arduino object

resource - name of resource to get property for.

property - name of property from the resource.

Outputs

propvalue - value of the property

See also: getResourceCount, setSharedResourceProperty.

9.2.22 @arduino/getTerminalMode

: mode = getTerminalMode (ar, terminal)

Get the mode of a pin allocated previously by configurePinResource.

Inputs

ar - connected arduino object

terminal - terminal number to get owner of.

Outputs

mode - mode of the terminal pin, or "not_set" if not owned.

See also: configurePinResource, getResourceOwner.

9.2.23 @arduino/getTerminalsFromPins

: pinnums = getTerminalsFromPins (ar, pins)

Get the terminal number for each pin.

Inputs

ar - connected arduino object

pins - single pin name or cell or vector array of pin names.

Outputs

pinnums - pin number of each named pin. If the input was a single string, returns a number. if the input pins was a vector or cell array, return a cell array of pin numbers corresponding to each input pin name.

See also: arduino, getPinsFromTerminals.

9.2.24 @arduino/incrementResourceCount

: count = incrementResourceCount (ar, resource)

Increment the count value of a named resource by 1 and return the new count

Inputs

ar - connected arduino object

resource - name of resource to increment count.

Outputs

count = count of uses registered to resource.

See also: getResourceCount. decrementResourceCount.

9.2.25 @arduino/isTerminalAnalog

: ret = isTerminalAnalog (obj, terminal)

Return true if pin is capable of analog input

Inputs

ar - the connected arduino object

terminal is a terminal number to check

Outputs

ret return 1 if terminal is a analog pin, 0 otherwise

9.2.26 @arduino/isTerminalDigital

: ret = isTerminalDigital(obj, terminal)

Return true if pin is capable of digital functions

Inputs

ar - the connected arduino object

terminal is a terminal number to check

Outputs

ret return 1 if terminal is a digital pin, 0 otherwise

9.2.27 @arduino/playTone

: playTone (ar, pin, freq, duration)

Play a tone of a given frequency on a specified pin.

Inputs

ar - connected arduino object

pin - digital pin to play tone on

freq - frequency in hertz to play between 0 and 32767Hz.

duration duration in seconds to play tone between 0 and 30 seconds

If duration is 0 or not specified, tone will continue to play until next tone is commanded. If frequency is 0, tone will stop playing

NOTE: use of playTone can interfere with PWM output.

9.2.28 @arduino/readAnalogPin

: value = readAnalogPin (ar, pin)

Read analog voltage of pin.

Inputs

ar - connected arduino object.

pin - string name of the pin to read.

Outputs

value - analog value of the pin

Example


 ar = arduino ();
 readAnalogPin(ar, "A4");
 ans =
     87
 

See also: arduino, readVoltage.

9.2.29 @arduino/readDigitalPin

: value = readDigitalPin (obj, pin)

Read digital value from a digital I/O pin.

Inputs

ar - connected arduino object.

pin - string name of the pin to read.

Outputs

value - the logical value (0, 1, true false) of the current pin state.

Example


 a = arduino ();
 pinvalue = readDigitalPin (a, 'D5');
 

See also: arduino, writeDigitalPin.

9.2.30 @arduino/readVoltage

: voltage = readVoltage (ar, pin)

Read analog voltage of a pin.

Inputs

ar - connected arduino.

pin - pin name or number to query for voltage

Outputs

voltage - scaled pin value as a voltage

Example


 ar = arduino ();
 readVoltage(ar, "A4");
 ans =
     1.401
 

See also: arduino, readAnalogPin.

9.2.31 @arduino/reset

: reset (ar)

Send reset command to arduino hardware to force a hardware reset.

Inputs

ar - connected arduino object.

See also: arduino.

9.2.32 @arduino/sendCommand

: outdata, outsize = sendCommand (ar, libname, commandid)
: outdata, outsize = sendCommand (ar, libname, commandid, data)
: outdata, outsize = sendCommand (ar, libname, commandid, data, timeout)

Send a command with option data to the connected arduino, waiting up to a specified number of seconds for a response.

Inputs

ar - connected arduino object.

libname - library sending the command. The name should match a programmed library of the arduino, or an error will be displayed.

commandid - integer value for the command being sent to the arduino.

data - optional data sent with the command.

timeout - optional timeout to wait for data

Outputs

outdata - data returned back from the arduino in response to command

outsize - size of data received

If the arduino fails to respond with a valid reply, sendCommand will error.

See also: arduino.

9.2.33 @arduino/setSharedResourceProperty

: setSharedResourceProperty (ar, resource, propname, propvalue)
: setSharedResourceProperty (ar, resource, propname, propvalue, ___)

Set property values for a given resource.

Inputs

ar - connected arduino object

resource - name of resource to get property for.

propname - name of property from the resource.

propvalue - value of property from the resource.

Multiple propname, propvalue pairs can be given.

Outputs

None

Example


 ar = arduino();
 setSharedResourceProperty(ar, "myresource", "myproperty", [1 2 3])
 

See also: getSharedResourceProperty.

9.2.34 @arduino/uptime

: sec = uptime (ar)

Get the number of seconds the arduino board has been running concurrently.

Inputs

ar - the arduino object of the connection to an arduino board.

Outputs

sec - the number seconds the board has been running. Note that the count will wrap around after approximately 50 days.

See also: arduino.

9.2.35 @arduino/validatePin

: validatePin (ar, pin, type)

Validate that the mode is allowed for specified pin

If the mode is not valid, and error will be thrown.

Inputs

ar - connected arduino object

pin - name of pin to query mode validity of

mode - mode to query

Known modes are:

  • ’I2C’
  • ’SPI’
  • ’PWM’
  • ’Servo’
  • ’analog’
  • ’digital’

See also: arduino, configurePin.

9.2.36 @arduino/version

: ver = version (ar)

Get version of library code installed on arduino board

Inputs

ar - the arduino object of the connection to an arduino board.

Outputs

ver - version string in format of X.Y.Z.

See also: arduino.

9.2.37 @arduino/writeDigitalPin

: writeDigitalPin (ar, pin, value)

Write digital value to a digital I/O pin.

Inputs

ar - connected arduino object.

pin - string name of the pin to write to.

value - the logical value (0, 1, true false) to write to the pin.

If pin was unconfigured before using, pin is set into digital mode.

Example


 a = arduino();
 writeDigitalPin(a,'D5',1);
 

See also: arduino, readDigitalPin.

9.2.38 @arduino/writePWMDutyCycle

: writePWMDutyCyle (ar, pin, value)

Set pin to output a square wave with a specified duty cycle.

Inputs

ar - connected arduino object

pin - pin to write to.

value - duty cycle value where 0 = off, 0.5 = 50% on, 1 = always on.

Example


 a = arduino();
 writePWMDutyCycle(a,'D5',0.5);
 

See also: arduino, writePWMVoltage.

9.2.39 @arduino/writePWMVoltage

: writePWMVoltage (ar, pin, voltage)

Emulate an approximate voltage out of a pin using PWM.

Inputs

ar - connected arduino object

pin - pin to write to.

voltage - voltage to emulate with PWM, between 0 - 5.0

Example


 a = arduino();
 writePWMVoltage(a,'D5',1.0);
 

See also: arduino, writePWMDutyCycle.


9.3 Arduino I2C Functions

9.3.1 @device/delete

: delete (dev)

Free resources of a device object.

Inputs

dev - object to free

See also: device.

9.3.2 @device/disp

: disp (dev)

Display device object.

Inputs

dev - device object to display

See also: device.

9.3.3 @device/read

: data = read (dev, numbytes)
: data = read (dev, numbytes, precision)

Read a specified number of bytes from a i2c or serial device object using optional precision for bytesize.

Inputs

dev - connected i2c or serial device opened using device

numbytes - number of bytes to read.

precision - Optional precision for the output data read data. Currently known precision values are uint8 (default), int8, uint16, int16

Outputs

data - data read from the device

See also: arduino, device.

9.3.4 @device/readRegister

: data = readRegister (dev, reg, numbytes)
: data = readRegister (dev, reg, numbytes, precision)

Read a specified number of bytes from a register of an i2cdev object using optional precision for bytesize.

Inputs

dev - connected i2c device opened using device

reg - registry value number

numbytes - number of bytes to read.

precision - Optional precision for the output data read data. Currently known precision values are uint8 (default), int8, uint16, int16

Output

data - data read from device.

See also: arduino, device.

9.3.5 @device/subsref

: val = subsref (dev, sub)

subref for device

See also: device.

9.3.6 @device/write

: write (dev, datain)
: write (dev, datain, precision)

Write data to a I2C or serial device object using optional precision for the data byte used for the data.

Inputs

dev - connected i2c or serial device opened using device

datain - data to write to device. Datasize should not exceed the constraints of the data type specified for the precision.

precision - Optional precision for the input write data. Currently known precision values are uint8 (default), int8, uint16, int16

See also: arduino, device, read.

9.3.7 @device/writeRegister

: writeRegister (dev, reg, datain)
: writeRegister (dev, dev, datain, precision)

Write data to i2c device object at a given registry position using optional precision for the data byte used for the data.

Inputs

dev - connected i2c device opened using device

reg - registry position to write to.

datain - data to write to device. Datasize should not exceed the constraints of the data type specified for the precision.

precision - Optional precision for the input write data. Currently known precision values are uint8 (default), int8, uint16, int16

See also: arduino, device, read.

9.3.8 @i2cdev/delete

: delete (dev)

Free resources of a i2cdev object.

Inputs

dev - object to free

See also: i2cdev.

9.3.9 @i2cdev/disp

: disp (dev)

Display i2cdev object.

Inputs

dev - i2cdev object

See also: i2cdev.

9.3.10 @i2cdev/i2cdev

: dev = i2cdev (ar, address)
: dev = i2cdev (ar, address, propname, propvalue)

i2cdev is depreciated and will be removed in a future version. Use device instead.

Create an i2cdev object to communicate to the i2c port on a connected arduino.

Inputs

ar - connected arduino object

address - address to use for device on I2C bus.

propname, propvalue - property name/value pair for values to pass to devices.

Currently known properties:

bus

bus number (when arduino board supports multiple I2C buses) with value of 0 or 1.

Outputs

dev - new created i2cdev object.

Properties

The i2cdev object has the following public properties:

parent

The parent (arduino) for this device

pins

pins used by this object

bus

bus used for created object

address

I2C address set for object

See also: arduino.

9.3.11 @i2cdev/read

: data = read (dev, numbytes)
: data = read (dev, numbytes, precision)

Read a specified number of bytes from a i2cdev object using optional precision for bytesize.

Inputs

dev - connected i2c device opened using i2cdev

numbytes - number of bytes to read.

precision - Optional precision for the output data read data. Currently known precision values are uint8 (default), int8, uint16, int16

Outputs

data - data read from i2cdevice

See also: arduino, i2cdev.

9.3.12 @i2cdev/readRegister

: data = readRegister (dev, reg, numbytes)
: data = readRegister (dev, reg, numbytes, precision)

Read a specified number of bytes from a register of an i2cdev object using optional precision for bytesize.

Inputs

dev - connected i2c device opened using i2cdev

reg - registry value number

numbytes - number of bytes to read.

precision - Optional precision for the output data read data. Currently known precision values are uint8 (default), int8, uint16, int16

Output

data - data read from device.

See also: arduino, i2cdev.

9.3.13 @i2cdev/subsref

: val = subsref (dev, sub)

subref for i2cdev

See also: i2cdev.

9.3.14 @i2cdev/write

: write (dev, datain)
: write (dev, datain, precision)

Write data to a i2cdev object using optional precision for the data byte used for the data.

Inputs

dev - connected i2c device opened using i2cdev

datain - data to write to device. Datasize should not exceed the constraints of the data type specified for the precision.

precision - Optional precision for the input write data. Currently known precision values are uint8 (default), int8, uint16, int16

See also: arduino, i2cdev, read.

9.3.15 @i2cdev/writeRegister

: writeRegister (dev, reg, datain)
: writeRegister (dev, dev, datain, precision)

Write data to i2cdev object at a given registry position using optional precision for the data byte used for the data.

Inputs

dev - connected i2c device opened using i2cdev

reg - registry position to write to.

datain - data to write to device. Datasize should not exceed the constraints of the data type specified for the precision.

precision - Optional precision for the input write data. Currently known precision values are uint8 (default), int8, uint16, int16

See also: arduino, i2cdev, read.

9.3.16 scanI2Cbus

: retval = scanI2Cbus (ar)
: retval = scanI2Cbus (ar, bus)

Scan arduino for devices on the I2C bus.

Inputs

ar - arduino object connected to a arduino board.

bus - bus number to scan I2C devices, when multiple buses are available. If the bus is not specified, it will default to 0.

Outputs

retval - cell array of addresses as strings in format of "0xXX".

Example


 # create arduino connection.
 ar = arduino();
 # scan for devices on the I2C bus
 scanI2Cbus (ar)
 # output is each detected i2c address as a string
 ans =
{
  [1,1] = 0x50
}
 

See also: arduino, i2cdev, checkI2CAddress.


9.4 Arduino Rotary Encoder Functions

9.4.1 @rotaryEncoder/delete

: delete (dev)

Free resources of a encoder object.

Inputs

dev - object to free

See also: rotartEncoder.

9.4.2 @rotaryEncoder/disp

: retval = disp (obj)

Display the rotary encoder object in a verbose way,

Inputs

obj - the arduino rotary encoder object created with rotaryEncoder

See also: rotaryEncoder.

9.4.3 @rotaryEncoder/readCount

: [count, time] = readCount (obj)
: [count, time] = readCount (obj, name, value)

read count value from the rotary encoder.

subsubheading Inputs obj - rotary encoder object created with rotaryEncoder call.

name, value - optional name,value pairs

Valid option name pairs currently are:

reset

Reset the count after reading (if true)

Outputs

count - returned count read from the encoder.

time - seconds since arduino started

See also: rotaryEncoder, resetCount.

9.4.4 @rotaryEncoder/readSpeed

: speed = readSpeed (obj)

read rotational speed from the rotary encoder.

Inputs

obj - rotary encoder object created with rotaryEncoder call.

Outputs

speed - returned speed in revolutions per minute read from the encoder.

See also: rotaryEncoder, resetCount.

9.4.5 @rotaryEncoder/resetCount

: reset (obj)
: reset (obj, cnt)

reset the rotary encoder count values

Inputs

obj - the rotaryEncoder object

cnt - optional count value to reset to

See also: rotaryEncoder, readCount.

9.4.6 @rotaryEncoder/rotaryEncoder

: obj = rotaryEncoder (ar, chanApin, chanBpin)
: obj = rotaryEncoder (ar, chanApin, chanBpin, ppr)

Create a rotaryEncoder object controlled by the input pins.

Inputs

ar - connected arduino object.

chanApin - pin used for channel A

chanBpin - pin used for channel B

ppr - count of encoder pulsed required for a full revolution of the encoder.

Outputs

obj - created rotary encoder object

Example

 a = arduino ();
 enc = rotaryEncoder(a, "d2", "d3", 180);

Properties

The rotaryEncoder object has the following public properties:

parent

The parent (arduino) for this device

pins

pins used by this object

ppr

Number of pulses used per rotation

See also: arduino.

9.4.7 @rotaryEncoder/subsref

: val = subsref (dev, sub)

subref for rotaryEncoder

See also: rotaryEncoder.


9.5 Arduino Servo Functions

9.5.1 @servo/delete

: delete (dev)

Free resources of a servo object.

Inputs

dev - object to free

See also: servo.

9.5.2 @servo/disp

: disp (dev)

Display servo object.

Inputs

dev - servo device to display

See also: servo.

9.5.3 @servo/readPosition

: position = readPosition (servo)

Read the position of a servo

Inputs

servo - servo object created from arduino.servo.

Outputs

position - value between 0 .. 1 for the current servo position, where 0 is the servo min position, 1 is the servo maximum position.

See also: servo, writePosition.

9.5.4 @servo/servo

: obj = servo (arduinoobj, pin)
: obj = servo (arduinoobj, pin, propertyname, propertyvalue)

Create a servo object using a specified pin on a arduino board.

Inputs

obj - servo object

arduinoobj - connected arduino object

propertyname, propertyvalue - name value pairs for properties to pass to the created servo object.

Current properties are:

minpulseduration

min PWM pulse value in seconds.

maxpulseduration

max PWM pulse value in seconds.

Outputs

obj - created servo object.

Example

 # create arduino connection
 ar = arduino();
 # create hobby servo (1 - 2 ms pulse range)
 servo = servo(ar, "d9", "minpulseduration", 1.0e-3, "maxpulseduration", 2e-3);
 # center the servo
 writePosition(servo, 0.5);

Properties

The servo object has the following public properties:

parent

The parent (arduino) for this device

pins

pins used by this object

minpulseduration

minpulseduration set for object

maxpulseduration

maxpulseduration set for object

See also: arduino, readPosition, writePosition.

9.5.5 @servo/subsref

: val = subsref (dev, sub)

subref for servo

See also: servo.

9.5.6 @servo/writePosition

: writePosition (servo, position)

Write the position to a servo.

Inputs

servo - servo object created from arduino.servo.

position - value between 0 .. 1 for the current servo position, where 0 is the servo min position, 1 is the servo maximum position.

See also: servo, readPosition.


9.6 Arduino Shiftregister Functions

9.6.1 @shiftRegister/delete

: delete (dev)

Free resources of a shiftRegister object.

Inputs

dev - object to free

See also: shiftRegister.

9.6.2 @shiftRegister/disp

: disp (register)

Display the register object in a verbose way,

Inputs

register - the arduino register object created with shiftRegister.

See also: shiftRegister.

9.6.3 @shiftRegister/read

: retval = read (register)
: retval = read (register, precision)

read a value from the shift register.

Inputs

register - shift register created from shiftRegister call.

precision - optional precision of the data, where precision can be a number in a multiple of 8 (ie: 8,16,32) or can be a named integer type: 8 of ’uint8’, ’uint16’, ’uint32’. The default precision is 8.

Outputs

retval - returned data read from the register.

See also: shiftRegister, write.

9.6.4 @shiftRegister/reset

: reset (register)

clear the shift register value.

Inputs

register - shift register created from shiftRegister call.

See also: shiftRegister, read, write.

9.6.5 @shiftRegister/shiftRegister

: register = shiftRegister (ar, shifttype, dataPin, clockPin ...)
: register = shiftRegister (ar,'74hc164', dataPin, clockPin, resetPin)
: register = shiftRegister (ar,'74hc165', dataPin, clockPin, loadPin, clockEnablePin)
: register = shiftRegister(ar,'74hc595', dataPin, clockPin, latchPin , resetPin)

Create shift register of a given type, controlled by the input pins.

Inputs

Common function parameter definition:

ar - connected arduino object.

shifttype - string name of the shift register type.

dataPin - pin used for data in/out of the device.

clockPin - pin used for clocking data on the shiftRegister.

Other variables are dependent on the shift register type:

’74hc164’

Additional inputs:

resetPin - optional pin for resetting the shift register.

’74hc165’

Additional inputs:

loadPin - load pin to the shift register. clockEnablePin - clock enable pin.

’74hc595’

Additional inputs:

latchPin - latching data to the shift register. resetPin - optional pin for resetting the shift register.

Outputs

register - register object

Properties

The shiftRegister object has the following public properties:

parent

The parent (arduino) for this device

pins

pins used by this object

model

model set for object

See also: arduino.

9.6.6 @shiftRegister/subsref

: val = subsref (dev, sub)

subref for shiftRegister

See also: shiftRegister.

9.6.7 @shiftRegister/write

: write (register, dataIn)
: write (register, dataIn, precision)

Write a value to the shift register.

Inputs

register - shift register created from shiftRegister call.

dataIn - data to clock into the shiftRegister.

precision - optional precision of the data, where precision can be a number in a multiple of 8 (ie: 8,16,32) or can be a named integer type of ’uint8’, ’uint16’, ’uint32’. The default precision is 8.

See also: shiftRegister, read.


9.7 Arduino SPI Functions

9.7.1 @device/delete

: delete (dev)

Free resources of a device object.

Inputs

dev - object to free

See also: device.

9.7.2 @device/disp

: disp (dev)

Display device object.

Inputs

dev - device object to display

See also: device.

9.7.3 @device/subsref

: val = subsref (dev, sub)

subref for device

See also: device.

9.7.4 @device/writeRead

: dataOut = readWrite (spi, dataIn)

Write uint8 data to spi device and return back clocked out response data of same size.

Inputs

spi - connected spi device on arduino

dataIn - uint8 sized data to send to spi device framed between SS frame.

Outputs

dataOut - uint8 data clocked out during send to dataIn.

See also: arduino, device.

9.7.5 @spidev/delete

: delete (dev)

Free resources of a spidev object.

Inputs

dev - spidev object to free

See also: spidev.

9.7.6 @spidev/disp

: disp (dev)

Display spidev object.

Inputs

dev - spidev object to display

See also: spidev.

9.7.7 @spidev/spidev

: dev = spidev (ar, cspin)
: dev = spidev (ar, cspin, propname, propvalue)

spidev is depreciated and will be removed in a future version. Use device instead.

Create an spidev object to communicate to the SPI port on a connected arduino.

Inputs

ar - connected arduino object

cspin - chip select pin for attached spi device.

propname, propvalue - property name/value pair for values to pass to devices.

Currently known properties:

bitrate

bit rate speed in Mbs

bitorder

’msbfirst’ or ’lsbfirst’

mode

SPI mode 0 - 3.

Outputs

dev - created spidev object

Properties

The spidev object has the following public properties:

parent

The parent (arduino) for this device

pins

pins used by this object

mode

mode used for created object

bitrate

Bitrate set for object

bitorder

Bitorder set for object

chipselectpin

Pin used for chipselect

See also: arduino, readWrite.

9.7.8 @spidev/subsref

: val = subsref (dev, sub)

subref for spidev

See also: spidev.

9.7.9 @spidev/writeRead

: dataOut = readWrite (spi, dataIn)

Write uint8 data to spi device and return back clocked out response data of same size.

Inputs

spi - connected spi device on arduino

dataIn - uint8 sized data to send to spi device framed between SS frame.

Outputs

dataOut - uint8 data clocked out during send to dataIn.

See also: arduino, spidev.


9.8 Arduino Serial Functions

9.8.1 @device/delete

: delete (dev)

Free resources of a device object.

Inputs

dev - object to free

See also: device.

9.8.2 @device/device

: dev = device (ar, 'I2CAddress', address)
: dev = device (ar, 'SPIChipSelectPin', pin)
: dev = device (ar, 'Serial', serialid)
: dev = device (..., propname, propvalue)

Create an i2c, spi or serial object to communicate on a connected arduino.

Inputs

ar - connected arduino object

propname, propvalue - property name/value pair for values to pass to devices.

A property of ’i2caddress’, ’spichipselectpin’ or ’serial’ must be specified to denote the device type to create.

i2caddress - address to use for device on I2C bus.

pin - pin to use for device SPI chip select.

serialid - Serial port id to use

Additional properties can also be specified for the device object

Currently known input I2C properties values:

bus

bus number (when arduino board supports multiple I2C buses) with value of 0 or 1.

noprobe

Do not probe the existence of device on creation if set to 1 (default 0)

bitrate

bit rate speed in Mbs - default 100000

Currently known input SPI properties values:

bitrate

bit rate speed in Mbs

bitorder

’msbfirst’ or ’lsbfirst’

spimode

SPI mode 0 - 3.

Currently known input Serial properties values:

baudrate

baudrate value (default 9600)

databits

number of databits (5,6,7,8) (default 8)

stopbits

number of stopbits (1,2) (default 1)

parity

parity of device (’odd’,’even’,’none’) (default ’none’)

Outputs

dev - new created device object.

Properties

The object has the following public properties:

parent

The parent (arduino) for this device

interface

The interface type for this device ("SPI" or "I2C" or "Serial")

In addition, depending on type, the object will have these properties:

I2C Properties

The object has the following public properties:

bus

bus used for created object

i2caddress

I2C address set for object

sclpin

the SCL pin of the device

sdapin

the SDA pin of the device

bitrate

bit rate for the i2c clock

SPI Properties

The object has the following public properties:

spimode

mode used for created object

bitrate

Bitrate set for object

bitorder

Bitorder set for object

spichipselectpin

Pin used for chipselect

mosipin

Pin used for mosi

misopin

Pin used for miso

sckpin

Pin used for sckpin

Serial Properties

The object has the following public properties:

id

serial port id

baudrate

baudrate

databits

number of databits (5,6,7,8)

stopbits

number of stopbits (1,2)

parity

parity of device (’odd’,’even’,’none’)

See also: arduino, i2cdev, spidev.

9.8.3 @device/disp

: disp (dev)

Display device object.

Inputs

dev - device object to display

See also: device.

9.8.4 @device/flush

: data = flush (dev)
: data = flush (dev, "input")
: data = flush (dev, "output")

Flush the serial port buffers

Inputs

dev - connected serial device opened using device

If an additional parameter is provided of "input" or "output", then only the input or output buffer will be flushed

Outputs

None

See also: arduino, device, read.

9.8.5 @device/read

: data = read (dev, numbytes)
: data = read (dev, numbytes, precision)

Read a specified number of bytes from a i2c or serial device object using optional precision for bytesize.

Inputs

dev - connected i2c or serial device opened using device

numbytes - number of bytes to read.

precision - Optional precision for the output data read data. Currently known precision values are uint8 (default), int8, uint16, int16

Outputs

data - data read from the device

See also: arduino, device.

9.8.6 @device/subsref

: val = subsref (dev, sub)

subref for device

See also: device.

9.8.7 @device/write

: write (dev, datain)
: write (dev, datain, precision)

Write data to a I2C or serial device object using optional precision for the data byte used for the data.

Inputs

dev - connected i2c or serial device opened using device

datain - data to write to device. Datasize should not exceed the constraints of the data type specified for the precision.

precision - Optional precision for the input write data. Currently known precision values are uint8 (default), int8, uint16, int16

See also: arduino, device, read.


9.9 Arduino Device Functions

9.9.1 @device/delete

: delete (dev)

Free resources of a device object.

Inputs

dev - object to free

See also: device.

9.9.2 @device/device

: dev = device (ar, 'I2CAddress', address)
: dev = device (ar, 'SPIChipSelectPin', pin)
: dev = device (ar, 'Serial', serialid)
: dev = device (..., propname, propvalue)

Create an i2c, spi or serial object to communicate on a connected arduino.

Inputs

ar - connected arduino object

propname, propvalue - property name/value pair for values to pass to devices.

A property of ’i2caddress’, ’spichipselectpin’ or ’serial’ must be specified to denote the device type to create.

i2caddress - address to use for device on I2C bus.

pin - pin to use for device SPI chip select.

serialid - Serial port id to use

Additional properties can also be specified for the device object

Currently known input I2C properties values:

bus

bus number (when arduino board supports multiple I2C buses) with value of 0 or 1.

noprobe

Do not probe the existence of device on creation if set to 1 (default 0)

bitrate

bit rate speed in Mbs - default 100000

Currently known input SPI properties values:

bitrate

bit rate speed in Mbs

bitorder

’msbfirst’ or ’lsbfirst’

spimode

SPI mode 0 - 3.

Currently known input Serial properties values:

baudrate

baudrate value (default 9600)

databits

number of databits (5,6,7,8) (default 8)

stopbits

number of stopbits (1,2) (default 1)

parity

parity of device (’odd’,’even’,’none’) (default ’none’)

Outputs

dev - new created device object.

Properties

The object has the following public properties:

parent

The parent (arduino) for this device

interface

The interface type for this device ("SPI" or "I2C" or "Serial")

In addition, depending on type, the object will have these properties:

I2C Properties

The object has the following public properties:

bus

bus used for created object

i2caddress

I2C address set for object

sclpin

the SCL pin of the device

sdapin

the SDA pin of the device

bitrate

bit rate for the i2c clock

SPI Properties

The object has the following public properties:

spimode

mode used for created object

bitrate

Bitrate set for object

bitorder

Bitorder set for object

spichipselectpin

Pin used for chipselect

mosipin

Pin used for mosi

misopin

Pin used for miso

sckpin

Pin used for sckpin

Serial Properties

The object has the following public properties:

id

serial port id

baudrate

baudrate

databits

number of databits (5,6,7,8)

stopbits

number of stopbits (1,2)

parity

parity of device (’odd’,’even’,’none’)

See also: arduino, i2cdev, spidev.

9.9.3 @device/disp

: disp (dev)

Display device object.

Inputs

dev - device object to display

See also: device.

9.9.4 @device/flush

: data = flush (dev)
: data = flush (dev, "input")
: data = flush (dev, "output")

Flush the serial port buffers

Inputs

dev - connected serial device opened using device

If an additional parameter is provided of "input" or "output", then only the input or output buffer will be flushed

Outputs

None

See also: arduino, device, read.

9.9.5 @device/read

: data = read (dev, numbytes)
: data = read (dev, numbytes, precision)

Read a specified number of bytes from a i2c or serial device object using optional precision for bytesize.

Inputs

dev - connected i2c or serial device opened using device

numbytes - number of bytes to read.

precision - Optional precision for the output data read data. Currently known precision values are uint8 (default), int8, uint16, int16

Outputs

data - data read from the device

See also: arduino, device.

9.9.6 @device/readRegister

: data = readRegister (dev, reg, numbytes)
: data = readRegister (dev, reg, numbytes, precision)

Read a specified number of bytes from a register of an i2cdev object using optional precision for bytesize.

Inputs

dev - connected i2c device opened using device

reg - registry value number

numbytes - number of bytes to read.

precision - Optional precision for the output data read data. Currently known precision values are uint8 (default), int8, uint16, int16

Output

data - data read from device.

See also: arduino, device.

9.9.7 @device/subsref

: val = subsref (dev, sub)

subref for device

See also: device.

9.9.8 @device/write

: write (dev, datain)
: write (dev, datain, precision)

Write data to a I2C or serial device object using optional precision for the data byte used for the data.

Inputs

dev - connected i2c or serial device opened using device

datain - data to write to device. Datasize should not exceed the constraints of the data type specified for the precision.

precision - Optional precision for the input write data. Currently known precision values are uint8 (default), int8, uint16, int16

See also: arduino, device, read.

9.9.9 @device/writeRead

: dataOut = readWrite (spi, dataIn)

Write uint8 data to spi device and return back clocked out response data of same size.

Inputs

spi - connected spi device on arduino

dataIn - uint8 sized data to send to spi device framed between SS frame.

Outputs

dataOut - uint8 data clocked out during send to dataIn.

See also: arduino, device.

9.9.10 @device/writeRegister

: writeRegister (dev, reg, datain)
: writeRegister (dev, dev, datain, precision)

Write data to i2c device object at a given registry position using optional precision for the data byte used for the data.

Inputs

dev - connected i2c device opened using device

reg - registry position to write to.

datain - data to write to device. Datasize should not exceed the constraints of the data type specified for the precision.

precision - Optional precision for the input write data. Currently known precision values are uint8 (default), int8, uint16, int16

See also: arduino, device, read.


9.10 Arduino Ultrasonic Functions

9.10.1 @ultrasonic/delete

: delete (dev)

Free resources of a ultrasonic object.

Inputs

dev - ultrasonic object to free

See also: ultrasonic.

9.10.2 @ultrasonic/disp

: disp (dev)

Display ultrasonic object.

Inputs

dev - ultrasonic object to display

See also: ultrasonic.

9.10.3 @ultrasonic/readDistance

: distance = readDistance (dev)

Read the distance from a ultrasonic device

Inputs

dev - connected ultrasonic device opened using ultrasonic

Outputs

distance - distance value in meters from the ultrasonic device, or Inf if out of sensor range

See also: arduino, ultrasonic.

9.10.4 @ultrasonic/readEchoTime

: time = readEchoTime (dev)

Measure the time for waves to reflect back to the ultrasonic device

Inputs

dev - connected ultrasonic device opened using ultrasonic()

Outputs

time - time in seconds, or Inf if out of sensor range

See also: arduino, ultrasonic.

9.10.5 @ultrasonic/subsref

: val = subsref (dev, sub)

subref for ultrasonic

See also: ultrasonic.

9.10.6 @ultrasonic/ultrasonic

: dev = ultrasonic (ar, triggerpin)
: dev = ultrasonic (ar, triggerpin, echopin)
: dev = ultrasonic (ar, triggerpin, echopin, propname, propvalue)

Create an ultrasonic object to communicate to a connected ultrasonic device

Inputs

ar - connected arduino object

triggerpin - trigger pin for attached device.

echopin - trigger pin for attached device.

propname, propvalue - property name/value pair for values to pass to devices.

Currently known properties:

outputformat

string designating number format for output (’double’)

Outputs

dev - created ultrasonic object

Properties

The ultrasonic object has the following public properties:

parent

The parent (arduino) for this device

pins

pins used by this object

triggerpin

trigger used for created object

echopin

Echo pin set for object

outputformat

Output format for the created object

See also: arduino, readDistance, readEchoTime.


9.11 Arduino Addons

9.11.1 addon

: retval = addon (ar, addonname)
: retval = addon (ar, addonname, varargs)

Create an addon object using the addon named class.

Inputs

ar - connected arduino object

addonname - the name of the addon to create. The addon name can be a user addon or an inbuilt addon, however must appear in the listArduinoLibraries output and have been programmed onto the arduino.

varargs - optional values that will be provided verbatim to the the addon class constructor.

Outputs

retval - cell array of string library names.

See also: arduino, arduinosetup, listArduinoLibraries.

9.11.2 arduinoioaddons.EEPRomAddon.EEPRom

: arduinoioaddons.EEPRomAddon.EEPRom

EEPROM addon for arduino

Allows read and write of uint8 data to the onboard arduino EEPROM.

Example

Assuming eeprom addon has been programmed into the Arduino:

 a = arduino ();
 e = addon (a, "eepromaddon/eeprom");
 write (e, 0, uint8("hello world"));
 str = uint8( read(e, 0, 11) )

See also: addon.

Properties

length - Size of the EEPROM.

Methods

: eeprom = EEPRom ()

Constructor to create EEPROM device.

Outputs

eeprom - created EEPROM device.

: erase ()

Erase all values in EEPROM (Effectively setting the 0xFF)

: write (address, uintdata)

Write data to EEPROM at the provided address.

Inputs

address - start address to write data to, should be an integer between 0 and the size of the EEPROM.

uintdata a value or array of uint8 data to write to EEPROM.

: data = read (address)
: data = read (address, count)

Read data from starting address of EEPROM.

Inputs

address - start address to read data from, should be an integer between 0 and the size of the EEPROM.

count - Number of uint8 values to read from the EEPROM (default is 1)

Outputs

data a value or array of uint8 data read from the EEPROM.

9.11.3 arduinoioaddons.ExampleAddon.Echo

: arduinoioaddons.ExampleAddon.Echo

Basic Example matlab/octave code to illustrate creating a user addon.

See also: addon.

Properties

Parent - the parent arduino object.

Pins - the pins allocated the addon.

Methods

: obj = Echo(arObj)

Constructor to create Echo addon

Inputs

arObj - the arduino parent object

Outputs

obj - created Echo object

: response = shout(text)

Send text to arduino and receive back the echoed reply

Inputs

text - text to send to arduino

Outputs

response - response from the arduino, which should be the same as the input text.

9.11.4 arduinoioaddons.ExampleLCD.LCD

: arduinoioaddons.LCDAddon.LCD

Basic Example octave addon for LCD

Allows basic manipulation of an LCD as a illustration of using the addon functionality.

Example

Assuming the arduino has been programmed with the lcd addon:

 a = arduino();
 lcd = addon(a, "examplelcd/lcd", "d8", "d9", "d4", "d5", "d6", "d7")
 clearLCD(lcd);
 printLCD(lcd, "Hello");
 # go to next line
 gotoLCD(lcd, 0, 1);
 printLCD(lcd, "World");

See also: addon.

Properties

Pins - the pins allocated the LCD display.

Methods

: lcd = LCD(arObj, rs, enable, d0, d1, d2, d3)

Constructor to create LCD device

Inputs

arObj - the arduino parent object

rs - the pin to use for the rs line.

enable - the pin to use for the enable line.

d0 - the pin to use for the d0 line.

d1 - the pin to use for the d1 line.

d2 - the pin to use for the d2 line.

d3 - the pin to use for the d3 line.

Outputs

lcd - created LCD object

: freeLCD()

Free the LCD

Should be called before discarding the LCD

Inputs

None.

Outputs

None.

: clearLCD()

Clear the LCD display and set the cursor position to the home position.

Inputs

None.

Outputs

None.

: printLCD(text)

Display text on LCD starting at the current cursor position.

Inputs

text - text to display on LCD

Outputs

None.

: gotoLCD(col, row)

Set the cursor position to row, col

Inputs

col - 0 indexed LCD column to position to.

row - 0 indexed LCD row to position to.

Outputs

None.

9.11.5 arduinoioaddons.RTCAddon.DS1307

: arduinoioaddons.RTCAddon.DS1307

DS1307 addon

See also: addon.

Properties

Parent - the parent arduino object.

Pins - the pins allocated the addon.

Methods

: obj = DS1307(arObj)
: obj = DS1307(arObj, propertyname, propertyvalue ....)

Constructor to create DS1307 addon

Inputs

arObj - the arduino parent object

propertyname, propertyvalue - optional property name, value pairs. Current known properties are:

address

I2C address of the DS1307 (default 0x68)

Outputs

obj - created DS1307 object

Example


 a = arduino()
 rtc = addon(a, "rtcaddon/ds1307")
 
: date = clock(dsObj)
: clock(dsObj, date)

Get/set the DS1307 clock

Inputs

dsObj - the ds1307 object

date - a date vector in same format as datevec and clock

Outputs

date - a date vector in same format as datevec and clock

Example


 a = arduino()
 rtc = addon(a, "rtcaddon/ds1307")
 # get and display rtc time as a date string
 datestr(rtc.clock)
 

See also: datevec.

: ctrl = control(dsObj)
: control(dsObj, ctrl)

Get/set the DS1307 clock

Inputs

dsObj - the ds1307 object

ctrl - a structure containing the control bit fields.

Outputs

ctrl - a structure containing the control bit fields.

Control structure fields are: Current properties are:

out

Out bit in the control register

sqwe

Square wave enable bit in control register

rs

The combined RS0, RS1 value

: YN = isstarted(dsObj)

Get whether the RTC clock is currently counting time

Inputs

dsObj - the ds1307 object

Outputs

YN - returns true if the RTC is counting

See also: start, stop.

: start(dsObj)

Start the RTC counting

Inputs

dsObj - the ds1307 object

Outputs

None

See also: datevec.

: stop(dsObj)

Stop the RTC counting

Inputs

dsObj - the ds1307 object

Outputs

None

See also: datevec.

9.11.6 arduinoioaddons.SimpleStepper.SimpleStepper

: arduinoioaddons.SimpleStepper

Stepper class for stepper control using ULN2003 and compatible drivers

Properties

Id

Id of the stepper (Read only)

Speed

Number of steps to do per second.

Status

Status of stepper (Read only). 0 = not moving, 1 = moving, 2 = rotating

Parent

the Arduino parent (read only)

Pins

the pins used for the stepper (read only)

Methods

: obj = SimpleStepper(aObj, pin1, pin2, pin3, pin4)
: obj = SimpleStepper(aObj, pin1, pin2, pin3, pin4, pin5)

Constructor to create a stepper object

Inputs

aObj - The arduino

pin1 - The first pin of the controller

pin2 - The second pin of the controller

pin3 - The third pin of the controller

pin4 - The fourth pin of the controller

pin5 - The fifth pin of the controller

Outputs

s - a simplestepper object

Example


 a = arduino()
 # create stepper object
 s = addon(a, "simplestepper/simplestepper", "d2", "d3", "d4", "d5")
 # start rotating left
 s.rotate(-1);
 

See also: addon.

: move(sObj, steps)

Move the motor the specified number of steps using the configured Speed.

Inputs

sObj - the stepper object

steps - the number of steps to move. steps less than 0 will be moving left.

Outputs

None

See also: rotate.

: rotate(sObj, dir)

Start steppermotor moving in the specified direction using the configured Speed.

Inputs

sObj - the stepper object

dir - Direction to move. -1 = left, 0 = stop, 1 = right.

Outputs

None

See also: move.

: release(sObj)

Release this stepper motor

Inputs

sObj - the stepper object

Outputs

None

9.11.7 arduinoioaddons.adafruit.dcmotorv2

: arduinoioaddons.adafruit.dcmotorv2

DC Motor class for dc motor control on the adafruit motor shield

See also: arduinoioaddons.adafruit.motorshieldv2.

Properties

Speed - The speed value set for the motor

Parent - The parent shield for object (read only)

MotorNumber - The motor number (read only) values 1-4

IsRunning - boolean for if the motor is started (read only)

Methods

: obj = dcmotorv2(mObj, mnum)
: obj = dcmotorv2(mObj, mnum, propertyname, propertyvalue ....)

Constructor to create dcmotor object

Inputs

mObj - the motor shield object

mnum - The motor number (1 - 4)

propertyname, propertyvalue - Optional property name/value pairs to pass to motor object.

Current known properties are:

Speed

Initial speed (default 0). Should be a value between -1 and 1.

Outputs

s - a dcmotorv2 object

Example


 a = arduino()
 ms = addon(a, "adafruit/motorshieldv2")
 mtr = dcmotor(ms, 1)
 
: start(dcObj)

Start the motor moving in previously set speed/direction

Inputs

dcObj - the dcmotor object

Outputs

None

See also: adafruit.motorshieldv2.

: stop(dcObj)

Stop the motor moving

Inputs

dcObj - the dcmotor object

Outputs

None

See also: adafruit.motorshieldv2.

9.11.8 arduinoioaddons.adafruit.motorshieldv2

: arduinoioaddons.adafruit.motorshieldv2

Adafruit motor shield addon

See also: addon.

Properties

Parent - the parent arduino object.

Pins - the pins allocated the addon.

I2CAddress - the i2c address used for accessing this shield.

PWMFrequency - the set PWM frequency for this shield.

Methods

: obj = motorshieldv2(arObj)
: obj = motorshieldv2(arObj, propertyname, propertyvalue ....)

Constructor to create motorshieldv2 addon object

Inputs

arObj - the arduino parent object

propertyname, propertyvalue - optional property name, value pairs. Current known properties are:

address

I2C address of the motor shield (default 0x60)

pwmfrequency

PWM Frequency to set on shield (default 1600)

Outputs

obj - created motorshieldv2 object

Example


 a = arduino()
 mtr = addon(a, "adafruit/motorshieldv2")
 
: s = servo(mObj, mtrnum)
: s = servo(mObj, mtrnum, propertyname, propertyvalue ...)

Create a servo object

Inputs

mObj - the motor shield object

mtrnum - The servo motor number, where 1 is servo on pin "d10" and 2 is a servo on pin "d9"

propertyname, propertyvalue - Optional property name/value pairs to pass to servo object.

Properties are the same as the base servo object.

Outputs

s - a servo object

Example


 a = arduino()
 ms = addon(a, "adafruit/motorshieldv2")
 # get servo 1 (servo on pin D10)
 s = ms.servo(1)
 

The function if the equivalent of calling the arduino.servo with the D9 or D10 pin has the input pin.

See also: servo.

: s = stepper(mObj, mtrnum, stepsperrev)
: s = stepper(mObj, mtrnum, stepsperrev, propertyname, propertyvalue ...)

Create a stepper motor object

Inputs

mObj - the motor shield object

mtrnum - The stepper motor number (1 or 2)

stepsperrev - Number of steps per revolution.

propertyname, propertyvalue - Optional property name/value pairs to pass to stepper object.

Outputs

s - a stepper object

: s = dcmotor(mObj, mtrnum)
: s = dcmotor(mObj, mtrnum, propertyname, propertyvalue ...)

Create a dcmotor motor object

Inputs

mObj - the motor shield object

mtrnum - The motor number (1 - 4)

propertyname, propertyvalue - Optional property name/value pairs to pass to motor object.

Outputs

s - a dcmotorv2 object

9.11.9 arduinoioaddons.adafruit.stepper

: arduinoioaddons.adafruit.stepper

Stepper class for stepper control on the adafruit motor shield

See also: arduinoioaddons.adafruit.motorshieldv2.

Properties

RPM

The rpm value set for the stepper motor

StepType

the StepType for the stepper (string) which can be "single", "double", "interleave" or "microstep"

StepsPerRevolution

the StepsPerRevoluion for the stepper (read only)

MotorNumber

the motor number for the stepper (read only) value will be 1 or 2.

Parent

the parent shield of this stepper (read only)

Methods

: obj = stepper(mObj, mnum, stepsperrev)
: obj = stepper(mObj, mnum, stepsperrev, propertyname, propertyvalue ....)

Constructor to create dcmotor object

Inputs

mObj - the motor shield object

mnum - The motor number (1 or 2)

stepsperrev - Number of steps per revolution.

propertyname, propertyvalue - Optional property name/value pairs to pass to motor object.

Current known properties are:

RPM

the RPM for the stepper (revolutions per minute)

StepType

the StepType for the stepper (string) which can be "single", "double", "interleave" or "microstep"

Outputs

s - a stepper object

Example


 a = arduino()
 ms = addon(a, "adafruit/motorshieldv2")
 mtr = stepper(ms, 1, 200)
 
: move(sObj, steps)

Move the motor moving in the specified steps using the configured RPM.

Inputs

sObj - the stepper object

Outputs

None

See also: adafruit.motorshieldv2.

: release(sObj)

Release this motor

Inputs

sObj - the stepper object

Outputs

None

See also: adafruit.motorshieldv2.


9.12 Arduino Sensors

9.12.1 arduinosensor.DS1307

: arduinosensor.DS1307

DS1307 realtime clock sensor

Methods

: obj = DS1307(arObj)
: obj = DS1307(arObj, propertyname, propertyvalue ....)

Constructor to create DS1307 sensor

Inputs

arObj - the arduino parent object

propertyname, propertyvalue - optional property name, value pairs. Current known properties are: Current properties are:

i2caddress

I2C address of the DS1307 (default 0x68)

Outputs

obj - created DS1307 object

Example


 a = arduino()
 rtc = arduinosensor.DS1307(a)
 
: date = clock(dsObj)
: clock(dsObj, date)

Get/set the DS1307 clock

Inputs

dsObj - the ds1307 object

date - a date vector in same format as datevec and clock

Outputs

date - a date vector in same format as datevec and clock

Example


 a = arduino()
 rtc = arduinosensor.DS1307(a)
 # get and display rtc time as a date string
 datestr(rtc.clock)
 

See also: datevec.

: ctrl = control(dsObj)
: control(dsObj, ctrl)

Get/set the DS1307 clock

Inputs

dsObj - the ds1307 object

ctrl - a structure containing the control bit fields.

Outputs

ctrl - a structure containing the control bit fields.

Control structure fields are: Current properties are:

out

Out bit in the control register

sqwe

Square wave enable bit in control register

rs

The combined RS0, RS1 value

: YN = isstarted(dsObj)

Get whether the RTC clock is currently counting time

Inputs

dsObj - the ds1307 object

Outputs

YN - returns true if the RTC is counting

See also: start, stop.

: start(dsObj)

Start the RTC counting

Inputs

dsObj - the ds1307 object

Outputs

None

See also: datevec.

: stop(dsObj)

Stop the RTC counting

Inputs

dsObj - the ds1307 object

Outputs

None

See also: datevec.

9.12.2 arduinosensor.GUVAS12SD

: arduinosensor.GUVAS12SD

A thin wrapper for the GUVAS12SD analog UV-B sensor

Methods

: obj = GUVAS12SD(arObj, pin)

Constructor to create GUVAS12SD sensor

Inputs

arObj - the arduino parent object

pin - the analog pin that the sensor is connected to

Outputs

obj - created GUVAS12SD object

Example


 a = arduino()
 # create sensor attached to pin a0.
 sensor = arduinosensor.GUVAS12SD(a, "a0")
 
: V = read(dsObj)

Read the voltage of the sensor

Inputs

dsObj - the GUVAS12SD object

Outputs

V - read voltage - effectively equivalent to readAnalogPin(arObj, pin).

Example


 a = arduino()
 s = arduinosensor.GUVAS12SD(a)
 # voltage
 volts = s.read
 

See also: arduinosensor.GUVAS12SD.

: Idx = readIndex(dsObj)

Read the UV index

Inputs

dsObj - the GUVAS12SD object

Outputs

Idx - the sensor reading as a UV index reading

: uA = readuA(dsObj)

Read the uA of the sensor

Inputs

dsObj - the GUVAS12SD object

Outputs

uA - the sensor reading as a uAmp value

9.12.3 arduinosensor.MPC3002

: arduinosensor.MPC3002

MCP3002 ADC sensor

Methods

: obj = MPC3002(arObj, selectPin)
: obj = MPC3002(arObj, selectPin, propertyname, propertyvalue ....)

Constructor to create MPC3002 sensor

Inputs

arObj - the arduino parent object

selectPin - the SPI cs select pin

propertyname, propertyvalue - optional property name, value pairs.

Current properties are:

referenceVoltage

Reference voltage for scaling the ADC inputs (default 5.0)

Outputs

obj - created MCP3002 object

Example


 a = arduino()
 sensor = arduinosensor.MPC3002(a, "d10")
 
: voltage = readVoltage(dsObj, chan)

Read the voltage from a channel

Inputs

dsObj - the MPC3002 object

chan - the channel to read (0 or 1)

Outputs

voltage - read voltage.

Example


 a = arduino()
 s = arduinosensor.MPC3002(a, "d10")
 volts = readVoltage(s, 0)
 

See also: arduinosensor.MPC3002.

9.12.4 arduinosensor.SI7021

: arduinosensor.SI7021

SI7021 temperature and humidity sensor

Methods

: obj = SI7021(arObj)
: obj = SI7021(arObj, propertyname, propertyvalue ....)

Constructor to create SI7021 sensor

Inputs

arObj - the arduino parent object

propertyname, propertyvalue - optional property name, value pairs. Current known properties are: Current properties are:

i2caddress

I2C address of the SI7021 (default 0x40)

Outputs

obj - created SI7020 object

Example


 a = arduino()
 sensor = arduinosensor.SI7021(a)
 
: C = temperature(dsObj)

Read the temperature

Inputs

dsObj - the si7021 object

Outputs

C - read temperature in deg C.

Example


 a = arduino()
 s = arduinosensor.SI7021(a)
 # get temp
 temp = s.temperature
 

See also: arduinosensor.SI7021.

: relH = humidity(dsObj)

Read the relative humidity

Inputs

dsObj - the si7021 object

Outputs

relH - relative humidity as a percentage (0 - 100.0)

: relH = info(dsObj)

Read the sensor info

Inputs

dsObj - the si7021 object

Outputs

inf - structure containing the sensor information.

Structure fields are:

version

Chip firmware version

id

sensor id1,id2 value

type

String for detected chip type


9.13 Arduino I/O package

9.13.1 arduinoio.AddonBase

: arduinoio.AddonBase

Base class used for arduino library sensors

See also: arduinoio.LibraryBase.

Properties

Base properties are expected to be inherited and overwritten in inherited classes. and are constant in order to query through the metaobject mechanism.

Parent - parent librarybase object

Methods

: ab = AddonBase ()

Constructor of base class

Outputs

The return value ab is an object of the arduinio.AddonBase class.

See also: arduino, addon.

: disp ()

Display the addon in a verbose way.

9.13.2 arduinoio.FilePath

: retval = arduinoio.FilePath (fullpathname)

Get the directory component of a pathname.

Inputs

fullpathname filepath to get directory component of.

Outputs

retval the directory part of the filename.

9.13.3 arduinoio.LibFiles

: filelist = arduinoio.LibFiles ()

Get the list of files used for the building arduino library

Outputs

filelist - string cell array of files for the arduino project

9.13.4 arduinoio.LibraryBase

: arduinoio.LibraryBase

Base class used for arduino library plugins

See also: arduino, listArduinoLibraries, addon.

Properties

Base properties are expected to be inherited and overwritten in inherited classes and are constant in order to query through the metaobject mechanism.

LibraryName - name of the addon library

DependentLibraries - array of dependent library names that must be included when installing this plugin.

CppHeaderFile - name (if any) of header file that will be included into the arduino project when adding this library.

CppSourceFile - name (if any) of source file that will be included into the arduino project when adding this library.

CppClassName - name of the cpp class for the addon library. project when adding this library.

Pins - pins allocated to the addon

Parent - parent arduino object.

Methods

: lb = LibraryBase ()

Constructor of base class

The constructor is usually not called but called indirectly from the addon function.

Outputs

The return value lb is an object of the arduinio.LibraryBase class.

See also: arduino, listArduinoLibraries, addon.

: disp ()

Display the addon in a verbose way.

9.13.5 arduinoio.getBoardConfig

: retval = arduinoio.getBoardConfig (boardname)

Return the configuration for a known arduino board type

Function is used to get the expected pin/board configuration for a named board type which is used to verify and identify the functionality of the board.

Inputs

boardname - name of board to get configuration of ie: "uno"

Outputs

retval configuration struct.


9.14 Matlab Compatibility Classes

9.14.1 matlabshared.addon.LibraryBase

: matlabshared.addon.LibraryBase

Compatability class used for arduino library plugins using matlabshared.addons.LibraryBase

See also: arduinoio.LibraryBase, arduino, listArduinoLibraries, addon.

Properties

Base properties are expected to be inherited and overwritten in inherited classes and are constant in order to query through the metaobject mechanism.

LibraryName - name of the addon library

DependentLibraries - array of dependent library names that must be included when installing this plugin.

CppHeaderFile - name (if any) of header file that will be included into the arduino project when adding this library.

CppSourceFile - name (if any) of source file that will be included into the arduino project when adding this library.

CppClassName - name of the cpp class for the addon library. project when adding this library.

Pins - pins allocated to the addon

Parent - parent arduino object.

Methods

: lb = LibraryBase ()

Constructor of base class

The constructor is usually not called but called indirectly from the addon function.

Outputs

The return value lb is an object of the matlabshare.addons.LibraryBase class.

See also: arduino, listArduinoLibraries, addon.

: disp ()

Display the addon in a verbose way.


9.15 Sensors

9.15.1 bme280

: bme280

BME280 pressure, temperature and humidity sensor

Methods

: obj = bme280(arObj)
: obj = bme280(arObj, propertyname, propertyvalue ....)

Constructor to create BME280 sensor

Inputs

arObj - the arduino parent object

propertyname, propertyvalue - optional property name, value pairs. Current known properties are: Current properties are:

I2CAddress

I2C address of the sensor (default 0x40)

Bus

I2C bus - 0 or 1 (default 0)

Outputs

obj - created object

Example


 a = arduino()
 sensor = bme280(a)
 
: [C, timestamp] = readTemperature(obj)

Read the temperature

Inputs

obj - the sensor object

Outputs

C - read temperature in deg C.

timestamp - timestamp when read

Example


 a = arduino()
 s = bme280(a)
 # get temp
 temp = s.readTemperature
 

See also: bme280.

: [relH, timestamp] = readHumidity(obj)

Read the relative humidity

Inputs

obj - the sensor object

Outputs

relH - relative humidity as a percentage (0 - 100.0)

timestamp - timestamp when read

: [P, timestamp] = readPressure(obj)

Read the pressure

Inputs

obj - the sensor object

Outputs

P - pressure reading from sensor.

timestamp - timestamp when read

: [readings, overrun] = read(obj)
: [P, H, C, timestamp, overrun] = read(obj)

Read the sensor data

Inputs

obj - the sensor object

Outputs

P - pressure reading from sensor.

H - humidity reading from sensor.

C - temperature reading from sensor.

timestamp - timestamp when read

overrun - overrun flag.

readings - table structure with fields for Timestamp, Pressure, Temperature and Humidity.

: inf = info(obj)

Read the sensor info

Inputs

obj - the sensor object

Outputs

inf - structure containing the sensor information.

Structure fields are:

Version

Chip firmware version

SensorId

sensor id value

Type

sensor type ’bme280’

Status

Status value read from sensor

: flush(obj)

Flush sensor data

Inputs

obj - the sensor object

Outputs

None

: release(obj)

Release the resources of the sensor

Inputs

obj - the sensor object

Outputs

None

9.15.2 bno055

: bno055

BNO055 9 axis orientation sensor

Methods

: obj = bno055(arObj)
: obj = bno055(arObj, propertyname, propertyvalue ....)

Constructor to create BME280 sensor

Inputs

arObj - the arduino parent object

propertyname, propertyvalue - optional property name, value pairs. Current known properties are: Current properties are:

I2CAddress

I2C address of the sensor (default 0x40)

Bus

I2C bus - 0 or 1 (default 0)

OperatingMode

Operating mode ’ndof’ or ’amg’

Outputs

obj - created object

Example


 a = arduino()
 sensor = bno055(a)
 
: [C, timestamp] = readTemperature(obj)

Read the temperature

Inputs

obj - the sensor object

Outputs

C - read temperature in deg C.

timestamp - timestamp when read

Example


 a = arduino()
 s = bno055(a)
 # get temp
 temp = s.readTemperature
 

See also: bno055.

: [readVal, timestamp] = readAcceleration(obj)

Read the acceleration rate

Inputs

obj - the sensor object

Outputs

readVal - the 3 acceleration values

timestamp - timestamp when read

: [readVal, timestamp] = readAngularVelocity(obj)

Read the angular velocity

Inputs

obj - the sensor object

Outputs

readVal - the 3 angular velocity values

timestamp - timestamp when read

: [readVal, timestamp] = readMagneticField(obj)

Read the magnetic field components

Inputs

obj - the sensor object

Outputs

readVal - the 3 magnetic field values

timestamp - timestamp when read

: [readVal, timestamp] = readOrientation(obj)

Read the oriientation components

Inputs

obj - the sensor object

Outputs

readVal - the 3 orientation values

timestamp - timestamp when read

: [readings, overrun] = read(obj)
: [accel, gyro, mag, timestamp, overrun] = read(obj)
: [accel, gyro, mag, orientation, timestamp, overrun] = read(obj)

Read the sensor data

Inputs

obj - the sensor object

Outputs

accel - acceleration reading from sensor.

gyro - angular acceleration reading from sensor.

mag - magnetic field reading from sensor.

orientation - orientation reading from sensor.

timestamp - timestamp when read

overrun - overrun flag.

readings - table structure with fields for Timestamp, Acceleration, AngularVelocity, MagneticField, Orientation.

: inf = readCalibrationStatus(obj)

Read the sensor calibration status

Inputs

obj - the sensor object

Outputs

status - structure containing the calibration information.

Structure fields are:

System

System calibrarion

Accelerometer

Accelerometer calibration status

Gyroscope

Gyroscope calibration status

Magnetometer

Magnetometer calibration status

Values for each will be either ’uncalibrated’, ’partial’ or ’full’.

: inf = info(obj)

Read the sensor info

Inputs

obj - the sensor object

Outputs

inf - structure containing the sensor information.

Structure fields are:

Version

Software firmware version

SensorId

sensor id value

Type

sensor type ’bno055’

: flush(obj)

Flush sensor data

Inputs

obj - the sensor object

Outputs

None

: release(obj)

Release the resources of the sensor

Inputs

obj - the sensor object

Outputs

None

9.15.3 lis3dh

: lis3dh

LIS3DH 3 degrees sensor

Methods

: obj = lis3dh(arObj)
: obj = lis3dh(arObj, propertyname, propertyvalue ....)

Constructor to create LIS3DH sensor

Inputs

arObj - the arduino parent object

propertyname, propertyvalue - optional property name, value pairs. Current known properties are: Current properties are:

I2CAddress

I2C address of the sensor (default 0x40)

Bus

I2C bus - 0 or 1 (default 0)

Outputs

obj - created object

Example


 a = arduino()
 sensor = lis3dh(a)
 
: [readVal, timestamp] = readAcceleration(obj)

Read the acceleration rate

Inputs

obj - the sensor object

Outputs

readVal - the 3 acceleration values

timestamp - timestamp when read

: [readings, overrun] = read(obj)
: [accel, timestamp, overrun] = read(obj)

Read the sensor data

Inputs

obj - the sensor object

Outputs

accel - acceleration reading from sensor.

timestamp - timestamp when read

overrun - overrun flag.

readings - table structure with fields for Timestamp, Acceleration.

: inf = info(obj)

Read the sensor info

Inputs

obj - the sensor object

Outputs

inf - structure containing the sensor information.

Structure fields are:

SensorId

sensor id value

Type

sensor type ’lis3dh’

Status

sensor status value

: flush(obj)

Flush sensor data

Inputs

obj - the sensor object

Outputs

None

: release(obj)

Release the resources of the sensor

Inputs

obj - the sensor object

Outputs

None

9.15.4 lps22hb

: lps22hb

LPS22HB absolute pressure and temperature sensor

Methods

: obj = lps22hb(arObj)
: obj = lps22hb(arObj, propertyname, propertyvalue ....)

Constructor to create LPS22HB sensor

Inputs

arObj - the arduino parent object

propertyname, propertyvalue - optional property name, value pairs. Current known properties are: Current properties are:

I2CAddress

I2C address of the sensor (default 0x5C)

Bus

I2C bus - 0 or 1 (default 0)

Outputs

obj - created object

Example


 a = arduino()
 sensor = lps22hb(a)
 
: [C, timestamp] = readTemperature(obj)

Read the temperature

Inputs

obj - the sensor object

Outputs

C - read temperature in deg C.

timestamp - timestamp when read

Example


 a = arduino()
 s = lps22hb(a)
 # get temp
 temp = s.readTemperature
 

See also: lps22hb.

: [P, timestamp] = readPressure(obj)

Read the pressure

Inputs

obj - the sensor object

Outputs

P - pressure reading from sensor.

timestamp - timestamp when read

: [readings, overrun] = read(obj)
: [P, C, timestamp, overrun] = read(obj)

Read the sensor data

Inputs

obj - the sensor object

Outputs

P - pressure reading from sensor.

C - temperature reading from sensor.

timestamp - timestamp when read

overrun - overrun flag.

readings - table structure with fields for Timestamp, Pressure, Temperature and Humidity.

: inf = info(obj)

Read the sensor info

Inputs

obj - the sensor object

Outputs

inf - structure containing the sensor information.

Structure fields are:

Version

Chip firmware version

SensorId

sensor id value

Type

sensor type ’lps22hb’

Status

Status value read from sensor

: flush(obj)

Flush sensor data

Inputs

obj - the sensor object

Outputs

None

: release(obj)

Release the resources of the sensor

Inputs

obj - the sensor object

Outputs

None

9.15.5 lsm6dso

: lsm6dso

LSM6DSO 6 degrees sensor

Methods

: obj = lsm6dso(arObj)
: obj = lsm6dso(arObj, propertyname, propertyvalue ....)

Constructor to create LSM6DSO sensor

Inputs

arObj - the arduino parent object

propertyname, propertyvalue - optional property name, value pairs. Current known properties are: Current properties are:

I2CAddress

I2C address of the sensor (default 0x40)

Bus

I2C bus - 0 or 1 (default 0)

Outputs

obj - created object

Example


 a = arduino()
 sensor = lsm6dso(a)
 
: [C, timestamp] = readTemperature(obj)

Read the temperature

Inputs

obj - the sensor object

Outputs

C - read temperature in deg C.

timestamp - timestamp when read

Example


 a = arduino()
 s = lsm6dso(a)
 # get temp
 temp = s.readTemperature
 

See also: lsm6dso.

: [readVal, timestamp] = readAcceleration(obj)

Read the acceleration rate

Inputs

obj - the sensor object

Outputs

readVal - the 3 acceleration values

timestamp - timestamp when read

: [readVal, timestamp] = readAngularVelocity(obj)

Read the angular velocity

Inputs

obj - the sensor object

Outputs

readVal - the 3 angular velocity values

timestamp - timestamp when read

: [readings, overrun] = read(obj)
: [accel, gyro, mag, timestamp, overrun] = read(obj)

Read the sensor data

Inputs

obj - the sensor object

Outputs

accel - acceleration reading from sensor.

gyro - angular acceleration reading from sensor.

timestamp - timestamp when read

overrun - overrun flag.

readings - table structure with fields for Timestamp, Acceleration, AngularVelocity.

: inf = info(obj)

Read the sensor info

Inputs

obj - the sensor object

Outputs

inf - structure containing the sensor information.

Structure fields are:

SensorId

sensor id value

Type

sensor type ’lsm6dso’

: flush(obj)

Flush sensor data

Inputs

obj - the sensor object

Outputs

None

: release(obj)

Release the resources of the sensor

Inputs

obj - the sensor object

Outputs

None

9.15.6 mpu6050

: mpu6050

MPU-6050 6 degrees sensor

Methods

: obj = mpu6050(arObj)
: obj = mpu6050(arObj, propertyname, propertyvalue ....)

Constructor to create MPU-6050 sensor

Inputs

arObj - the arduino parent object

propertyname, propertyvalue - optional property name, value pairs. Current known properties are: Current properties are:

I2CAddress

I2C address of the sensor (default 0x40)

Bus

I2C bus - 0 or 1 (default 0)

Outputs

obj - created object

Example


 a = arduino()
 sensor = mpu6050(a)
 
: [C, timestamp] = readTemperature(obj)

Read the temperature

Inputs

obj - the sensor object

Outputs

C - read temperature in deg C.

timestamp - timestamp when read

Example


 a = arduino()
 s = mpu6050(a)
 # get temp
 temp = s.readTemperature
 

See also: mpu6050.

: [readVal, timestamp] = readAcceleration(obj)

Read the acceleration rate

Inputs

obj - the sensor object

Outputs

readVal - the 3 acceleration values

timestamp - timestamp when read

: [readVal, timestamp] = readAngularVelocity(obj)

Read the angular velocity

Inputs

obj - the sensor object

Outputs

readVal - the 3 angular velocity values

timestamp - timestamp when read

: [readings, overrun] = read(obj)
: [accel, gyro, mag, timestamp, overrun] = read(obj)

Read the sensor data

Inputs

obj - the sensor object

Outputs

accel - acceleration reading from sensor.

gyro - angular acceleration reading from sensor.

timestamp - timestamp when read

overrun - overrun flag.

readings - table structure with fields for Timestamp, Acceleration, AngularVelocity.

: inf = info(obj)

Read the sensor info

Inputs

obj - the sensor object

Outputs

inf - structure containing the sensor information.

Structure fields are:

SensorId

sensor id value

Type

sensor type ’mpu6050’

: flush(obj)

Flush sensor data

Inputs

obj - the sensor object

Outputs

None

: release(obj)

Release the resources of the sensor

Inputs

obj - the sensor object

Outputs

None

9.15.7 si7021

: si7021

SI7021 temperature and humidity sensor

Methods

: obj = si7021(arObj)
: obj = si7021(arObj, propertyname, propertyvalue ....)

Constructor to create si7021 sensor

Inputs

arObj - the arduino parent object

propertyname, propertyvalue - optional property name, value pairs. Current known properties are: Current properties are:

I2Caddress

I2C address of the si7021 (default 0x40)

Bus

I2C bus (default 0)

Outputs

obj - created SI7020 object

Example


 a = arduino()
 sensor = si7021(a)
 
: [C, timestamp] = readTemperature(obj)

Read the temperature

Inputs

obj - the si7021 object

Outputs

C - read temperature in deg C.

timestamp - timestamp when read

Example


 a = arduino()
 s = si7021(a)
 # get temp
 temp = s.readTemperature()
 

See also: si7021.

: [relH, timestamp] = readHumidity(obj)

Read the relative humidity

Inputs

obj - the si7021 object

Outputs

relH - relative humidity as a percentage (0 - 100.0)

timestamp - timestamp when read

: [readings, overrun] = read(obj)
: [H, C, timestamp, overrun] = read(obj)

Read the sensor data

Inputs

obj - the si2071 sensor object

Outputs

H - humidity reading from sensor.

C - temperature reading from sensor.

timestamp - timestamp when read

overrun - overrun flag.

readings - table structure with fields for Timestamp, Temperature and Humidity.

: relH = info(dsObj)

Read the sensor info

Inputs

dsObj - the si7021 object

Outputs

inf - structure containing the sensor information.

Structure fields are:

Version

Chip firmware version

SensorDd

sensor id value

Type

String for detected chip type

: flush(obj)

Flush sensor data

Inputs

obj - the sensor object

Outputs

None

: release(obj)

Release the resources of the sensor

Inputs

obj - the sensor object

Outputs

None


9.16 Test Functions

9.16.1 arduino_bistsetup

: retval = arduino_bistsetup ()
: retval = arduino_bistsetup (propertyname, propertyvalue)

Install on an arduino the required core libraries to run the BIST tests

As part of the setup, the arduino IDE will be opened to allow programming the arduino board.

Inputs

propertyname, propertyvalue - A sequence of property name/value pairs can be given to set defaults while programming.

Currently the following properties can be set:

arduinobinary

The value should be the name/path of the arduino IDE binary for programming. If not specified, the function will attempt to find the binary itself.

debug

Set the debug flag when checking the arduino

Outputs

retval - return 1 if everything installed ok

See also: arduino, arduinosetup.


Appendix A GNU General Public License

Version 3, 29 June 2007
Copyright © 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

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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:

    1. The work must carry prominent notices stating that you modified it, and giving a relevant date.
    2. 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”.
    3. 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.
    4. 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.

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

    1. 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.
    2. 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.
    3. 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.
    4. 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.
    5. 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.

  8. 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:

    1. Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or
    2. 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
    3. 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
    4. Limiting the use for publicity purposes of names of licensors or authors of the material; or
    5. Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or
    6. 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.

  9. 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.

  10. 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.

  11. 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.

  12. 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.

  13. 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.

  14. 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.

  15. 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.

  16. 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.

  17. 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.

  18. 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.


Index

Jump to:   A   B   C   D   E   F   G   H   I   K   L   M   O   P   Q   R   S   T   U   V   W  
Index Entry  Section

A
addon: Arduino Addons
Addon Introduction: Addons Overview
Addon package .m file: Addons Overview
Addon package directory: Addons Overview
Addon package header file: Addons Overview
AddonBase: Arduino I/O package
Addons Overview: Addons Overview
arduino: Arduino Functions
Arduino Addons: Arduino Addons
Arduino Device Functions: Arduino Device Functions
Arduino Functions: Arduino Functions
Arduino I/O package: Arduino I/O package
Arduino I2C Functions: Arduino I2C Functions
Arduino Rotary Encoder Functions: Arduino Rotary Encoder Functions
Arduino Sensor: Sensors Overview
Arduino Sensors: Arduino Sensors
Arduino Serial Functions: Arduino Serial Functions
Arduino Servo Functions: Arduino Servo Functions
Arduino Shiftregister Functions: Arduino Shiftregister Functions
Arduino SPI Functions: Arduino SPI Functions
Arduino Ultrasonic Functions: Arduino Ultrasonic Functions
arduinosetup: General Functions
arduino_bistsetup: Test Functions
Available Sensors: Sensors Overview
Available Sensors: Sensors Overview

B
Basic Input and Output Overview: Basic Input and Output Overview
Blinking an LED: Examples
bme280: Sensors
bno055: Sensors

C
checkI2CAddress: Arduino Functions
configurePin: Arduino Functions
configurePinResource: Arduino Functions
Connecting to a single arduino: Connecting to an arduino
Connecting to a specific arduino: Connecting to an arduino
Connecting to an arduino: Connecting to an arduino
copyright: Copying
Creating a addon object: Addons Overview
Creating an addon: Addons Overview

D
dcmotorv2: Arduino Addons
decrementResourceCount: Arduino Functions
delete: Arduino Functions
delete: Arduino I2C Functions
delete: Arduino I2C Functions
delete: Arduino Rotary Encoder Functions
delete: Arduino Servo Functions
delete: Arduino Shiftregister Functions
delete: Arduino SPI Functions
delete: Arduino SPI Functions
delete: Arduino Serial Functions
delete: Arduino Device Functions
delete: Arduino Ultrasonic Functions
device: Arduino Serial Functions
device: Arduino Device Functions
disp: Arduino Functions
disp: Arduino I2C Functions
disp: Arduino I2C Functions
disp: Arduino Rotary Encoder Functions
disp: Arduino Servo Functions
disp: Arduino Shiftregister Functions
disp: Arduino SPI Functions
disp: Arduino SPI Functions
disp: Arduino Serial Functions
disp: Arduino Device Functions
disp: Arduino Ultrasonic Functions
DS1307: Arduino Addons
DS1307: Arduino Sensors

E
Echo: Arduino Addons
EEPRom: Arduino Addons
Examples: Examples

F
FilePath: Arduino I/O package
flush: Arduino Serial Functions
flush: Arduino Device Functions
Function Reference: Function Reference

G
General Functions: General Functions
getBoardConfig: Arduino I/O package
getEndian: Arduino Functions
getI2CTerminals: Arduino Functions
getInterruptTerminals: Arduino Functions
getLEDTerminals: Arduino Functions
getMCU: Arduino Functions
getPinAlias: Arduino Functions
getPinInfo: Arduino Functions
getPinsFromTerminals: Arduino Functions
getPWMTerminals: Arduino Functions
getResourceCount: Arduino Functions
getResourceOwner: Arduino Functions
getServoTerminals: Arduino Functions
getSharedResourceProperty: Arduino Functions
getSPITerminals: Arduino Functions
getTerminalMode: Arduino Functions
getTerminalsFromPins: Arduino Functions
GUVAS12SD: Arduino Sensors

H
Hardware setup: Hardware setup

I
I2C communication: Protocol based I/O Overview
i2cdev: Arduino I2C Functions
incrementResourceCount: Arduino Functions
Installing and loading: Installing and loading
isarduino: General Functions
isTerminalAnalog: Arduino Functions
isTerminalDigital: Arduino Functions

K
Known Arduino Board Types: Hardware setup

L
LCD: Arduino Addons
LibFiles: Arduino I/O package
LibraryBase: Arduino I/O package
LibraryBase: Matlab Compatibility Classes
lis3dh: Sensors
listArduinoLibraries: General Functions
Loading: Installing and loading
lps22hb: Sensors
lsm6dso: Sensors

M
Matlab Compatibility Classes: Matlab Compatibility Classes
Matlab Compatible Sensor: Sensors Overview
motorshieldv2: Arduino Addons
MPC3002: Arduino Sensors
mpu6050: Sensors

O
Off-line install: Installing and loading
Online install: Installing and loading

P
Performing Analog Input: Basic Input and Output Overview
Performing Digital I/O: Basic Input and Output Overview
playTone: Arduino Functions
Programming the Arduino: Hardware setup
Programming the arduino with the addon: Addons Overview
Protocol based I/O Overview: Protocol based I/O Overview

Q
Querying available arduinos: Connecting to an arduino

R
read: Arduino I2C Functions
read: Arduino I2C Functions
read: Arduino Shiftregister Functions
read: Arduino Serial Functions
read: Arduino Device Functions
readAnalogPin: Arduino Functions
readCount: Arduino Rotary Encoder Functions
readDigitalPin: Arduino Functions
readDistance: Arduino Ultrasonic Functions
readEchoTime: Arduino Ultrasonic Functions
readPosition: Arduino Servo Functions
readRegister: Arduino I2C Functions
readRegister: Arduino I2C Functions
readRegister: Arduino Device Functions
readSpeed: Arduino Rotary Encoder Functions
readVoltage: Arduino Functions
reset: Arduino Functions
reset: Arduino Shiftregister Functions
resetCount: Arduino Rotary Encoder Functions
Rotary Encoder: Protocol based I/O Overview
rotaryEncoder: Arduino Rotary Encoder Functions

S
scanForArduinos: General Functions
scanI2Cbus: Arduino I2C Functions
sendCommand: Arduino Functions
Sensors: Sensors
Sensors Overview: Sensors Overview
Serial communication: Protocol based I/O Overview
servo: Arduino Servo Functions
Servo communication: Protocol based I/O Overview
setSharedResourceProperty: Arduino Functions
Shift Registers: Protocol based I/O Overview
shiftRegister: Arduino Shiftregister Functions
SI7021: Arduino Sensors
si7021: Sensors
SimpleStepper: Arduino Addons
SPI communication: Protocol based I/O Overview
spidev: Arduino SPI Functions
stepper: Arduino Addons
subsref: Arduino I2C Functions
subsref: Arduino I2C Functions
subsref: Arduino Rotary Encoder Functions
subsref: Arduino Servo Functions
subsref: Arduino Shiftregister Functions
subsref: Arduino SPI Functions
subsref: Arduino SPI Functions
subsref: Arduino Serial Functions
subsref: Arduino Device Functions
subsref: Arduino Ultrasonic Functions

T
Test Functions: Test Functions

U
ultrasonic: Arduino Ultrasonic Functions
Ultrasonic Sensors: Protocol based I/O Overview
uptime: Arduino Functions
Using Addons: Addons Overview
Using I2C to communicate with an EEPROM: Examples
Using SPI to communicate with a mcp3002 10 bit ADC: Examples

V
validatePin: Arduino Functions
Verify octave can see the addon: Addons Overview
version: Arduino Functions

W
warranty: Copying
write: Arduino I2C Functions
write: Arduino I2C Functions
write: Arduino Shiftregister Functions
write: Arduino Serial Functions
write: Arduino Device Functions
writeDigitalPin: Arduino Functions
writePosition: Arduino Servo Functions
writePWMDutyCycle: Arduino Functions
writePWMVoltage: Arduino Functions
writeRead: Arduino SPI Functions
writeRead: Arduino SPI Functions
writeRead: Arduino Device Functions
writeRegister: Arduino I2C Functions
writeRegister: Arduino I2C Functions
writeRegister: Arduino Device Functions

arduino-0.12.1/doc/arduino.pdf0000644000000000000000000142126614545566645013123 0ustar00%PDF-1.5 % 1 0 obj << /Length 587 /Filter /FlateDecode >> stream xmTM@+z&?tBL$d4*.<_fW_wիrc;`GUOV&ʮ[v6W7TvbuYt/N.5=S> stream xmTM@+z&?tBL0d4*.<̿~UfW_uvc;Z̫MfG} I]/ޭmޯo⣩0^'^x]fkn{EK{*ʇupg6;ލ$4;gZ8, M[TPRJGeWxmE7 "/7j;{Yʋ"1tm|oirI ɑc׺>[TқEnn#bBSEV嶭mzsg)gR133w xAb;aGL6K&0+}&"?(Ҧa/ c,!-f3*Ix {asIC%hS7}H=ŤIY(jŧ Z4{SO5Z ekxvKǬ@2a> stream xmSn0+$z"aKU^CvF^p=!94gB˥0pދ s#P~k@hZ+vQڦ(A,Rf5Ħq8>K_X NH3$Ǟ{<0*5c~Pʯ5W42^!0^#rqxƘE3x z)cgl1BҰ?Xq!NAWA*d1)iȧΰО 9璆NVfkVaUJ?%͚5ػbTW=ј52f&p2pjV^cHMcVYxLS7E=1j g endstream endobj 6 0 obj << /Length 333 /Filter /FlateDecode >> stream xڅN0E /Ee+RCB,B>D[CHcZ@Hؾ32+u,m 1vKI: X) gh+k<889wIF;E3 9n_BYռ.F6Oe|(ˇzZ0^%w;FصlQd cf)@k3M݈kض&y◣)^_y? _?nڬ*]"t{4A#`<;C ]ҫEL B ߥ8 ]4rUƀiZG!_ي endstream endobj 13 0 obj << /Length 664 /Filter /FlateDecode >> stream x}TM0+r M81~l=U,1$FN^ xx^(>eQ)dqU3 ~|[WId% /l#MRn$eVl[llwf.5W_g#9 dOuVh~$m۲jԣxQ /x!g{0/v4YIJV+aeU0.Eyk7y6W͌On]턈Ew[,aߤS;utf^y9/Bv1#edLh{r-Gjwn,/&&|+ad/ް .f.?2>7dBprzea(L퇞Tɼl}A9^|YQ$&P|57 #·_UFP6~Gy괋 g:*jea*lxpU:'ڢ'00StW{rli <Čq!œ 5W ֽ+7,l9MU[Zk`)AN"S2v~fB\Ǩc`ƺOj"yhId눷N񽩣-0S?pOLԁ(C6vq7Q9MLi]}ݭR endstream endobj 19 0 obj << /Length 1136 /Filter /FlateDecode >> stream xڕV[o6 ~V%҃ 6 yp%1؁/GRc DG$Yi.w<)-VeZhMvas~"IUdnEr.TCW?C6_Z'JDK0Ss?C6}Z2uL*Owcݴڢ?+m>+q'd^w݀ ZF׷1<#̪sl)Ӈ)n!RJ=cEJj\GvOp c;#]{F g ـI2&fL,Oh( 6j|vMV͎ϗŏO#!$-&ECF6G4(]Ѩhs{mܷB9+D7SyI3 ZEz/KtZo]7Tu\ͮ!RqK(!-iIJ猛uOI!:jLRL2U"kS%ش=͎m(.|q 2ЋzKK $dٯy@ GHDvU'êl}I6aߡ$b Ǟnrd |BE2ݹ>4TQ35H*-<קIBI BuE3Ϩ8p@LYJ""N.苒i##r-.]:`e}XW i=};,C1:X>CM#,K4q1Ҧ[,$ #< zD}\ڼݰ|/CWðgEN:&R6.FQIM` ~޼>'bFW-|z0 X Ƹod ޿E)Y8O3_'9|ƹDȴ̗!Y.g!z 7/ٛ[IP ^V7E ·s8-7v>Fmf C I58OuP%S&PqixK7:a߯A}2m%:ЌY Yxrks> tx0mo,hgolg?x endstream endobj 69 0 obj << /Length 2596 /Filter /FlateDecode >> stream xM۸:JaOM2ɦسds%zD#(] Ѥcbmѐ=6 WRJ%E퓤Y7-8 '(K2~ iozoO~ qg4ҫ=̵$+"9k](ij^o2͖|]կϫuSS6eՖ0-cWSFʏ{PN$e"֟-1)ù}ccTD VB2J:TWCIQ ?c=`lDcْr4MZ`U[ DO6ʔ)E4{H=3d~(A7?Hbcȯe`ue,H͵~W`TmO3rY5RUg~k_|hgE,>NWj ^~^g@< 0tz2 @afs6۪v˛~ӋG-u?Ecvzq@ GLDz LԲO?=Ơe)@Xa>@wwL #V$z˺jx&?h3|d%iz9m._`3P oFeBZ+$w톤vG[[gu޴oD'4g|_B5O@(B*7`bjеb׃]ބTeG--%e d0+L ® REG{*A'9AdH \a> BKI&FAV"xWm4d8He8[KI&F"AV"j^"HU'_[+{td\֊%g44 W i][iP5P$4~;4u~Y3]OGX]te )C|)8!)@ RH!JPU (J\+O2r20W3RdѯL F:$$Fwَǜ"">Vdzvf@a0 2/M@¾m~ǒ xN^rsZLQj"&b5q{U2r#oIWUb5X`*턬:vUw<ӥpS +l q_A415軯0AqwcuHT.l5ׅ3d3 M.. ;Y*6\ l"yzh7(̆ݝ`GAzбqԴ2=_˛w>Ѩբdo:-ڝuб)A2a=KY5Uaf"E@0B"څmN"b+l!o@^t{ endstream endobj 135 0 obj << /Length 2841 /Filter /FlateDecode >> stream x[s6 =JFpN2$8f pd0V$e(HQfБb#9\}W{ߑyxϗ^ 1).?-H+r6c\U]+I0AD#wlDssɚ`d"oLO?]u3iQ!SfſRrS{[wid)UeC;ʶFv_m r7̶؇j~wދH42)H*;,?ϫ_zr9Oӓ֯(jy*#rן!+m w[Cmlbm4vd!I.m k ]S8g͓|Y/\ eu5ݔ/?WOM}_ m/!M>Po@X&B3# N}}.}X\,c4kgi_xsrk SvTcWc``Rt'T NE7=qrVM}U;(o %U#I[%#IP2ܩyC#IMHnދK̻[tn$K,j&[ޡL*P#:NIz :^t/&EcӌH2nrЮ!0gr.77}AP: j& d4ML@c&`^5hHZwϿ69WulhaߨQtb/k&(@61m(tt(޼Zo޴mg=pM.쇍m=6(+LfAhP-=.Uq3 ¤zCj>!tLgǗ4IY/儎9l#? [`}XA hlD0Y-=+fNFpB,{apWW}GHv$\ip|{zba@e0,~AkWH}RA AvH)ڤAz;-Mʷ[f<5.)>4rXg#(Ț}fez7Y0 ^# aƶ,yI2cY-̫i?\C|{W[ɌAJa0xlXq\7&/?/+Ĝt̾ 3``Fc;2#A̲+ԫ\/\ӭnY^ hlg53C!ieww_?Tz9V`Q_f:a*hdcm6 ,b}sW>MrfwfrĔ/e3 kth"Y(ѶSam0mxlMS7 /͓<1⻕qdz24y:1}S[n}[hq qvnI&vȼ^-KyG:UZ:K=@PTbLbI!HN(7T-| 5Z9촓unuς7İCc;w9ƻۛգO*4ݬ/3 fA61f,+Ь|ٓLh骇{c!UDsM h2ZPvN-&-ۡUMR'O3]7C`1}v N7 CG@/>E)u0Pdtה9ΫtVh5̝=)0ʐBdCm)..%=Y t\}$ d~{74ƃ7DF[:'98 >զ,I6=AZ[LR%aj*Jmg%zռ\Mm|`="/BvhnYAc]}ѯ=U endstream endobj 9 0 obj << /Type /ObjStm /N 100 /First 830 /Length 2268 /Filter /FlateDecode >> stream xڽZێ}`*mAA0$H"z5Qv԰w;۝ TR78X )5jd $4HՐK!` k0@_3eECn{{h,"] Ն{@UY l1@8&Uq_BVwh½B@7@@c6@T l){ kѝ0xW'V0@j MpY$APKzfJp(d/BKU|G 6]r7ߜ^4x0{%>p{zs Wa}xV@ gbWI+,`gh_X͙Cqsg2>o 羆󴆻˞OdbOMWtK_QJG)tQpG; w(QpG"E:t(QHG"E;v(+bFcbZ;o̩ShOئ‘@d7,O3%ظmB8b2e& yʼb9ۺ'cySjL) ]V0wi`ˇ+䕴,9۬%cY7$ʌ6ٔ^c/ 4X:2 y'hbQ<`dSJViAtۖG+Ap֌2QM#VS oC9cfJr)*i]i]i]mzuj] Z ZUu(QXGG1S[v*|':mj'L%ɶRŲpgB=G`g]j[Oi[q"ȳ!=p*:XpU6D6ԓL5-8Ji8@"R"+6Pm8"OVLo#ltZgm8B#?Z$'|y?VZ m#`~'<51'2$'w Zg ^~uD;.rJj OyW endstream endobj 210 0 obj << /Length 2498 /Filter /FlateDecode >> stream xo{ CoHOouޢ})k a "){?pHΌʫ+_׫7B{/^JN"NQ^~ c)m eƼ_HƤ_ljɚ}(K9M_6O뇏7/o7on~z{\||iTj+xJќq?-?e3F8M$v̄MOL1!ճW͟,?L,E*zVM z[NRT5] 9jH9o'Q=ܳjZٽQxܫc%sE > 4ǹ4q"fb?:7_F} s>>]{4$7 ߭~]oW}H{ Fga[3@9(mY5-aMBO =¼}eY}Xt,3P?sOxgմxㅴf];Y5BMao5{yRZģ"Hx8`1ZH9f"O XM)2)i[E̪iQ sj0!3^$ ӌZ3~{VM{p1x>|jaۧ>jZپ&ݳ٩ў$83n,~.W .҃:rHzmF]NV567$SӮUӢ.]8^-ǧFhoxn~1cVM c06 lNQ#p=X :rkg)BΡ䬚0wAn#7Gy:uj?jg )i_Ϫis* oI[T̫is %YVF^o?6mA7FwMkn fմkdk \f_|Jn~\Ľbta,T~ 5s{,gȲjZ܅"Dk qxjI]:}{-G`Ji W nWvxϮۤ[+@Z9\Y5-^aViaC ݽ. ٳm͐&@6`Ub.6kF3D6-??i)R%Ŭ0<*qviG5xX!T˭`83հjI2˞8Kl^"dp}'GpjZz]zOB]"Ec9;YGR;@U`A[ ΰz7Y^C#P={?m hs^66]hTC0D|N|xw"8:~S줿+P8GX5-].]AKa5 v+ɥqX2~gմ؇}?ǎ4ę6@/`Ub3S:yeC[&_Dи18{n~刀_VM_;UTb MFk_ЄBy:*sSwkfQuͼ8wќQKҬ*+REh_6@.Y5-a"Y˰IøAڹ]3zyĚ(q1mU*Ljy矞ƌޏ|fj*5J\P(.>v@gh[kn~1ZSVM THUiؘUii>qs)r-:x5-aXj!/;߽FR5VΏL o 0ͪi1 sjJ*boLFP✯e$SY5-a| Ie[ϙE{?Wwϫips^ qg3~L50w-dN̡_<@: U".FoT[ ªqÙyFwMkn fմkm\u㛌0w֚Q=ܳjZŽzxjg)0w?y"Kڞe| >ʼnWAIU-\ĭg9VgJiPgA x'~v'swV]4+A4Lhy*JO'ڕa,el<,>Rg 4 endstream endobj 279 0 obj << /Length 2731 /Filter /FlateDecode >> stream xs Ƀ`|T[3$S@SJԐ(-^P$) q,@,\#cG+ >>}q??<ś:b8#41?Gݗ.E"J´ٿQFф*%||(Ng__~b?# v{_{ >X?3M}LI6ĈFc|km=t 4[7RgjJ#xc"w!a;g~~ هՔGs6 ؗJzX X?ب J)&_=⿜Mi݆kQo?C}PM}4wo%j9<83F5˙SL4-b|,Vtrqlj-V}Av~ 9|deyRJtc.qEބ=Yr&6?~#ߣ7`=D==;X ܷUWJ4ԃO0TSSC |[oK5[=z)fS4kTSb+'MV*}2ب *)-#m [=z)fCjJ죹}m :fj=[kd[9rsǜ`!(33;bVi-|rzM[NC))%#Nm9-`} hȞ[bL̴׍fȹu נh)Mt62~mrs֭`!"00@QN~޽~⮻}ql~EҶmM\8CIJdjJ(,#B8m?D?w>;!/ef  tej d㹣l s C3;S"-kK$"CNyO^y )堚h\ B%T.oO4zrEomw] MY5B1VPMV4w*f=a܎nms;j<s LS)%JT (ŶW ip,ǹoz)BDjJHi.ӗ6mLto-4o ) )Wf `6n:-mVν3)F#jJ:; ­I=!M6JL~U8? chj ;+ 7ٽVtmGY>-nƘwCKMz}~zD)6RYDDhBD"迓l;fŒn8#N6SۡZ Q͍PՔPCsGj+&qj?gvV-ڢ[ qMwՔpCsGn`%26w/8َl jiX)UBKcK0lUvlhMx^blfh;_t| _ƵK޻~RlC}2;a+3N>/[bX~ṗHG{_"&W``[k`5%QU u[sn6f J,MJ0]uQXM.4w'B]@j=ݏ7bh'Z%܃fx~wKHWݕʏp%ҷW`=rXMIO@sY+?vWv}a0gF||U1B8R"K+ ~ǘ16zwi(Tķjozx'PJ)%<#8S Ӊ5usv1a }{sM0ήbjJĢ#YpN ɞh(gs}~eo^s itvMVSN LpЩޏo~Xzڙvg=UԻO0VSGquKAm?ܹHSL1(Ք(Fshmc7}ڼjɽg[kN{CW{Lv VSuA \vG~.7ס}W|IxS 8DՔGsGFrr-? 1a^Zp h\O.$׳dq+e:wIw Y5B3&{+_.NF۟'rqnޭ7vu2VMLA&G`$11;tqu,gSlwOD>f}L0bTSbR٘tZxG. ҆Vê:)u_령$<]\}y;c[5jE:fWR :8 ˈ6Oe˻ݽIUt>ѫxO@&{(O2nnDXw+1Lڍ=ڭ8n |c8Ƥ?|=QHqGDh:GXə߯8٬\f&RZ{z:#%?)_vT endstream endobj 154 0 obj << /Type /ObjStm /N 100 /First 909 /Length 2079 /Filter /FlateDecode >> stream xڽ[ W\"ER`,ù$aE3=6nNWM c6T]%GQ(=D<$%1PTQT;%.#ICJi ԭvjhEV@b T6J`4 l'2I|0XڽyKEd= ,q+*78в˹rT+yeEΩx喪aem onj/I kHʚDW6wWnI:+EQ AI-R%5)A:4isS%[ˁFOV7ɘ8yoN*L)ϥ&38N` M6R+jRk> ux6`*uΧ#1gDM.uC/q;JQ* øRZ[ |4PYf R2?ҽİJ% \ub`` !6nxj "f!Z= $7a0QUUcgLG^I->+0xQ/^tp|OwLp|s>WlG ~U֬&Z?/m:]:L>FY md+j)hl05 ߤ_eȘ_CWw'W~ =lH>G(~`?Ooo`j:~*v><9/z7/w_?rW?vv͌e fπH'W~/n/Чx.[=q.D,ڡsR(^xCk^ x=z^x=z7ox#Fg<_s%EQ(%3އ-{"̺Z s;(d %S.]wrgiyԝ9{yY^e_Vre8 ˸ՍIڲZF{3H^qb)嬔}/yXIͩ8gbZ8ydl9,G[qwԁLlaDؗl3x6E+f9sE^pZE}9ȌDžS}MDf+j913LUH/g)f"ۈ>SeNA6U}9[bK&.wݗ[ZSV|}9e_8v欒 --NyFV8nK 24F+J$S])+feҾ2{<)KV8WrbNvϏN }9qDgE6frrϽ,glh&qz&')v+ri5=+q"ʼn]8>n'뗬Ȧcc)#ٴˉ]^'ΜYY░MurұɓeL/%fFec$S+uWNdd4Ql%pD6e#LI mˊٴΜXƓMؾrF뾜ձdeg΢W2G22BHekzNl=i뾌. !Fκ8\ETͺ)Bj_+?gysV@YYI?֞TZGF ##5sF x5j ɋC␼8$/ɋC␼8$/ɋC␼8$/ɋC␼8$/8$)Ou1]5ڏ~?3 g4N1[Vڍe/LBtG˳K?J/LBy4+iy=~:뾜2ꓤ/LBy3 g4ΧK?:D.~aV#駐y3oٴF<7\q_{{Sٸ[VHd}3-~$P ͒,¬וyl\.4G3~I?{A#Ɲ,㤹R Lunt ?Um_J5t޸q6KDiS6n},XtGvNm-! endstream endobj 316 0 obj << /Length 681 /Filter /FlateDecode >> stream xn@~Y_KjTUUEbhdc7mMʖ%ÜE~ip G£b|By>LLJD R|EZ!~LoɛN$RG)W0BԧoTj.fZc%Q @bG=SW84#XqQ&3#p l4YNV22 Déf5wP%NI0ۗKƙRb4x XphD' N5CXծXP:tY% i ]`͙CT Iĭf Fa+@SSý(N}ι7ˎvb 7BoV'?*cףvT3^h{>0- wq^KP0Y " A!{!4\!氷D'[0Pnq46m Qxf/ESi'5SMN5Ch:6 oT )1WfzQwc%/> stream xڵWRF}W#y4KUnA`7dÃePH$9=򍵌TYL>===ci%LZń0h5J5Li29i3.s;΂ļLpIR-I\:̈́x΄ q 4S`&@CYX&2N;P*)bN XB)b+@*-B q !мaK3Pc0:%XỌk1$@&hx%)JDlE'L+k w5rCkI@5RSb#|iO$CyϡYbjREh5RP@#x YEV:2^NE#m'p$`~zYzPU;H/WmP_aU}؞rÖ}1B'Ti bl,T9{n+)9O8]pr Do)M9_jiL?I.Ho)B ỏ} 0SK2A~SJ 떔>$8n'VGl? Q/L#I;b_Pyҿ!pIpҔr.v\mtl w2!"I,=;:f[.zv]=e0:'_jZ&^|TdշaLB.OYVCݎ:t?#HZVY+f*_TℯTFaGlu~%PDzGBB'nW_iQE>0]iQE|#JeÝjнP&aZlk3±A pmA^Y;c䯛u.N<5ll2)Y9fRe#D<+읖$yTԈNfxM&߲zBGJu]Cvt{1hZFePR)u(ۚu( {̉.=cl]Sկ~ MשˇŸDӼ~g}VL'=:̚NIy7mWRtN:5J3KW<)u/٤^رBհj&ehEk$pqvBrvZì-r|r 0W? ~SEuϲwyf#Rs'm5U٭E^630VsQU6aO)n.ںMt3u߄߮.~ōXyP-$)|3&ϰ<`gEO~W};<_``-ϖ%ho^deџu,Sȭ$9$u{%; n`Ǭ|n9prU߇}݁ ?ߕW endstream endobj 445 0 obj << /Type /ObjStm /N 100 /First 856 /Length 1054 /Filter /FlateDecode >> stream xڕVMo6W=_CQbQ7$Hbbeʐvb"=zoXVHaJaX,BX;,F(P %/TRhg)N cx%a q!qX|/niAc%A" 'Ț- PJ8= WjE€W*Q@-(Y`$Aݲ%L DiEQ:[Q%dЌEIxFJbDAR0M)5e9s Yk8JZay4ڹi !VT(j G@72~gEJY gŀQ3B aؠ(M)39c=8x:" D4%G@E"&E&cXT8-Y*T3גecggD2h'̎V}axZpV+ZP aB5& oÅGbL"rt(jGMZma6a4LDc4I=;y K f?{q}h8Qev2bS=6/i}H}cj݄~74NM;ML?bZ2J|vq>{^3^vڤ8<:uJk#歒|}/qMZ J O ivK| )tUq~zSۇa~=}Ha}]1;te N_wxy]w0.Ɣ#з.w*sn0؄aRد'aHur1V>nSi]YQA ?1b7JOtYpٵc2_+*(xlUdxߴغghğؿ.?D98Tκ~>)@yBUp9^H`dG 2LBu5ׇT]:V#q񨊫0R5-/ z|Zc9z$ endstream endobj 600 0 obj << /Type /ObjStm /N 100 /First 852 /Length 888 /Filter /FlateDecode >> stream xڕUnG+h80IC K.4vҁ>$ yUuTwb)(9&)VEp AŬTWT Rl(SAOq߱~׏Ň|o-?;ǏΟ^a|,w6ۮ~NPGpt5vMޢtiiuoׁ{%+X]He F[s\]3a)!du&g趐z l Y]HO.z0g]n+cx$ۀכ\[wv_4S74(W7yՓn1\n[&bp &7[t dSo+(>E9ܯ569 wۖWup+7OVͪ_|Ev+Or<3X tz/op )04qFJ3 endstream endobj 756 0 obj << /Type /ObjStm /N 100 /First 852 /Length 1005 /Filter /FlateDecode >> stream xڕUMo7W\$r5԰zYKk{QI+ZHj+o2{37OV^i}T$匊A UVX2 `'EH"pc8` j䉬,E(+8&eGvi+Gzrdww{YQ-{VH37kB0VBJX[%-`Uw' =I*r%h4 h+'PN{@D@ ABbk d [mnz :C>Cc\FDfb,!3^b, }gcBF+(ʉGހ%`0LakmS>{fK5TjPo޿,Ыf}veTFݪ]yp,ժMٕcpdpW _6uX5, ̋xYt)s'cdf̧9mX]d4r(datۦkU#b~2GǚA4xa[׫ڎd Н%Zs +r>3-3Uuk7OzbߔG2PEbOybib[v~_6/wI')CszN.SUnY{unעH=nPsOZZf8Gz3Z4H9sd.wY<{YOfP9IMyStOc_{#MhoDzPc;w9km{b^oEWWl-_> stream xڭXKo6W,ߏZ$  nC+ۋh%Gp}R+M ^>fb?+&.hm3l|x}#_7?T(qԱls)N no>lifHqEOԚH7&䶱=rb,{>nߖ۾UDž/WM{]$CX&Jtȍ|@;v lxƛwWO.h/A7A1!FNٚ B[e1ia'`mqi yȤd9hVٟ -<{Ta3I-]Pa/ig[ji&1\*3Qi1{yukZKgTDޖ_n`<0A79F` af:27izB v"q%X6|KҏX•%N XҴhr6mqx~[v!:< )*=9gbTiLZ*f=3bOr8g1ofS%L<{ 1Qj*ˉP9O&Hub#T9Ma㤦[?88٧}|nȄ گ 6ڦb>q]W`ˣA!,֘ӄ Z2twqcR)G=@~y}? `:) τR|%Q&U\~/ᦃp(ҰM)]vSohhvHH&2Bf,FRQ&`#+/TQՌ' C%WzÎE=++XzZ4 4 5{P9y<  ˧6ݮ@K-PѰ'M}e#2%2`_U"hR;Iۨ25פ颰&;]*J8g;vto܁?r`''\q]z*=wݤ OwC^jPY]W}R[Veѥlx2o&[ fg拉|pp#dвS 7J,!8:=0L,;e bEՖ;ӳ{b0'}cۖH>кiqNa=0($j v/fl'gW,O$?E'sPS,30c.xnP;G@}ęo |3"b?`Dß"G!\!Ř h_gqhX{چNG^W,¢ y0w8^8d23 0O:-bok)3gSp[, 'b 9l endstream endobj 963 0 obj << /Length 1857 /Filter /FlateDecode >> stream xڽXKs6WjB$pڴy5Q/Ms$aCw H$ęLvݥ8(Q)4θm"ZLsK8|:{̘Hpf223=6zŇg=## 3Z}pLF"eR 0H$*-o7 %-K+U+/$6eID0{^,v[?t7KcA; q(kOˇs7eѳ7LT狥".{"@:k[ms]3ܦ+4#2͌vÅnw^Бgз)H 2w-\Y,EXx++r1GGLYxUaqJ1Tzs ɅeNe>T=mڼ/_jz-4]^o$c#0|j*3-36QmSzG(=hRow]"){CŦ,h{y_lωvօcFHd`UtYs]CMgypDYk,g7O/hLqs]5Ŧ!M ,$1|W85x{/4Dع>y| mxM_ҹ˦ DLh]%Zȱ躙u䞾i g9lT"hy<{ Բu y]t )}2|=@t\kx*B{.Fy?ISkZa*ܼ/:~s{HԤvb]nđMo .PyIg$0e&(V|)#Hl~ L#<Ji&i I@~5𤅓?%ba6ʑw!VYXE-K3m¨! Y'@5гR3#*>eƣdq+1Nӝ/G )s1Tuc4ecݾ>h"!t6UU6L*1_e5Ɠڇ rS*uf艔Ѻ}o Q2»z%om[Dzu,`1 dB cbph>Hwcx%:,s:~{; GR!.>44y!cЭ0/Jm!R-𘓲KF)}0*ޔa*f ]xwƿwF 5Zu@(X'3Ŋc^( cSxz:$Y|RäLGv:j>3b=&} AM4NnPچlPz lFTR,L KwD*Ǣ q;d&OateSƓm }}=wol/$ : _ A Ƞ1S FZPcWg'?eq?HS*ߕN߭.;">~q䚓'>'O(M<|ӆx)n ڴ'EEqۜ4Nm? E]X' endstream endobj 966 0 obj << /Length 685 /Filter /FlateDecode >> stream xڽUKS0WhԪޖzaʣĝ(aibǁ߳@e:9Dvm("(e(k|6"msv &ˏl( t}y[6q9؇8BF_lSLG)ˢl8a(<;ek\$?3ɕLf($$0"dԃ?26.UH}shDHz*Ly NS,]Unz7_!īIDMyB92(|XSZOz=cL5Rb̈́9A 足!AT8Ox-iЏ |4p\Scb D.AB`!L2 ")GbBU K ԑ/t4gæS|s4]4jls~p)zיߚzvh4@AcDn[WW`˩ʶS^W`*]vZz[VYVVD %&B :4*I/춮6&a "y.5[Y &F,}}1V)MMlCW9s_V]{26A <:qoPśw2,-o:'327(Wa dp*4SbOz[e/.`ǚGŤv`79P7@uD{ω^: endstream endobj 969 0 obj << /Length 1191 /Filter /FlateDecode >> stream xڭVߏ6 ~ 4:{->!3۹Ce;iᐓ,Q#)p-+M6 C&|#HnO7$"Y'FrƋrҷ>޼^O4hLQ ӅLeR 3_hUe+U߻:;MZicά8S%ؕ%i]gJQRgHǾ:a#{l6% ]-9cM]h6:UzWheOYޣƤ]E4S:lQJ QH6v¬w2Or]2wplɏ^dֲJkG԰K> stream xڥXmo6_a&1+^EסbeƖdH$"Ht$֋Cx-~{QəF" 3ҩɭQ]NsCꊺjyX7Kk&U)xbEket/*"sH5.H-0`8NEM_evD&peN %j6h˦>8man;VIojT1us< %v =7=~gX 4%_)ۚ .}|?ްm:laؙo.E튼}A"-d,$眅t ~)4!ʟȓC ih錏..XiG;%m%O {d7 T6-tJ@ ^ ˠ£,Rliy ]N,d8xsɈ6*6J?M"]?=9Z~MTVdc@dŶlIca^=wH%"7#Z(J65W%Бb [6PђF`Lq"∙V*Pb@48 j2˔īaz8XZ!4կUNOGum-~&,A(D^_:xx)m[@>Fr-2ŭ\u x): Z߀{]n#Ǝʙ cQt*gp2ǖȁ2Q!ANl/9t_G(4ɀ#&@O᭫|[AUH1 QTGN,lȢ0tKL{0{B޳_n_u]wG.3jSu|hb8rcf؎*qg'cnOadƻ*@FAa"ǻ0.eGő5sEhvg*bZ'F$2ӣdc` "];nC@k-ZnR̥$9%zQS,Z|_?~@kǿS#Y&wT4eqg}7|K3iЧ {>m2du_Կ.B)*};O !ҧӥu1;K#>xɡ znR.{x$@7mQW~#ɱtg 2~Zr:%9b :ꇱ( zl{+BU}7Gt g۫Yzl*9W tK)&oas̶83Q Zk{:yt0_s* ltHTz|p93{-OL |Q>ɺ \4Ht ;- endstream endobj 977 0 obj << /Length 1893 /Filter /FlateDecode >> stream xn6_a$1W|բm[HICEbmmɕ$ %qC"@L y?)W1UVYEU{;hŇH>o$+".vXy1ỮWD_x=!JT"_I՟~F:W+ %Q j$.n-oD7`kZ{AV .U8KZGe_h!5Ef$p ֏v]wn' v` ruyܖQ5"ڵʣw"cm=$jmRrbi S@Gs-ڦ*(В*50iVd1qA*[ڿU(Bу>vh3:ό~&R}h*K&&doL* x R+fRqJu"IǾ[֤C[P߰zP=eږ)%%mf.}G?g\` ľiYI`gG 9~NOl7C5x[ @J qdSK#,Β3Gv!t2U@\jP:!QIqd'PEFwK!KqZ*ɔȼs-rǛQKP@0笶Fd:s»BNg:ѓԅ#S,ap^KXI!R_v\sOL$˱\Ğ NpC/Dī`+jer) nJ9 at`g8Ho!0GMۓ39Nhl7r<4p4\f' )rWpĪP]vN &&P 0řq@TbU &ӉjlDd>8隀BnMa\Ǭڋc;K9CZ=@m+ t_zN;Y3WV1?rə99ԋ4ua+q89% ^=OA:2ʍ nQ&/e*92}秅rRv8Bfyx;9Iq{Ü{q(.=}{t+Qӹ蔃=X.t0\邯5`y,H ,N H`3p18win0=#m3b,a)fE UH&VK1RM3q,01=s- Z2UR ͯ ԎL&BD5a oo('F#džГ*Rp'& ~ތfޒ x Mp*hbZK2X FFCNWH۵#S]^xa21U9{cd`~No.ye.ym}Ҝeg2l9C9 B d澒e0MK+N/rgNY[SoQR,;R<7d1˘)9k/%텻CBFE|cR endstream endobj 980 0 obj << /Length 1103 /Filter /FlateDecode >> stream xڭWMo6W>Q@%%R)zi^xOm\%CCJM"B3yo (OHiQuavp`,ܼMʈ3ZGmjSG_w8>^iJ]B}7v:I͒ ՠkc0s_:e yϛ͔L$"~H".h*ģH2ʤ@enT1'W2LI9u? iY3*ּ<)0{D \( X62A*բg/ƏjD M_ pW;)%0餤M:a@$ao&oqeU'i!/X.4LxƝvS/PmjQ S\4<'gZptiR@&co!`K(C }ڏP?PK10Nm.F9F*p>@*s3N8[]#13'H j@4alס oNGx~}cQuC A12n.EFSϵY D= -8otJ=jTzpԈ鈧0uo{0 i%eDYR̕${ݵM}U)A?Df tʔ(\E2%HV=9.!QIFCD|=e%iK%.\%i" %ġ[t=*ǖU{o< !"QLSi0\>u87X2w{A8pUξu!Anʞ*sEh:t)}oFVM g7`S0 +9]xF>uN3GB~1}/.pMG~o,I_8Dγs~m|݂;3}eDVX- qtrzkǝ$+h˥Q͹V]bh0_e~;UaxCS,[pmmn>-\r iiP z 8_= endstream endobj 983 0 obj << /Length 1934 /Filter /FlateDecode >> stream xڝXnF+\́=m79Hĺ9>8+TuUs k}2O LLAqz>n n^=O/ZX6b8 rz!MbnHQ۾_gV p5RtlUn4W^./} ']X25s!3OPٴ+Eje^"*:TTqk'̀E>q. gu;=x.ѡg7Go){qK~N_<|)QL~1HIRk1gx .8{H̑ a1+uWdmg0a&ɄRrnk(A֡ϵeJgR)r΋Dq4_?ЏmWk;ҭjLk8s&r!9jA#u2E 92r,RC5TqycOwp.t;! Q\{H 0)cu֕&[aI{G.=+"_1(2Q #`芑Ծiە6&hs]8UQ UQL^bh5\<'#А+т R#&귖3sVg0mB9RU3ZZA1jBYCqh+/<1cF+7'Z(qJf̜{?Wn(.!enJút>(w>ŲC>uJB➋{1q=&?/~蠎xZEF$OAŌ`p9oQp(r !y~Sx,Q cDS-T:_&d1) -1'_0xwHq# gW EX X#do*09)JnK i*ffέXB- i^zPzwh͵CO}CXGUSO˕Tr9`]hwB Ŭ.,("i%5R@&g~tIlZB&NX \zcZgfs/閒֠z?fj8shxFwsnɦuC?*z4:f;PKF#D< )(7GA5ŒVjVB!kQ^~> stream xڵXYo6~-eDI(iP4M[*Uv_ëi°E s}3Ñwb߉%AdՕݭC?_q÷+!Ks8-Er,Au}ntۇpo{B~Mw\t _0_i050lDhL-eF-A֙"sZtꏱykBhpyֲȋKX; Ψ!A%BuZ)4@oGT-I~$jfRs2]XMѰ_c'otVw,`)h*szF>'R GëãۉȕH;@;"\-E;E}jJES3p =0vCUQHE#ĄBa; -Snx>':|޾g@gQ>z»2 ?ɰbQy~Řm,M"y8? [-[KyٶU(rNcYN#;9Zv 5Vor 8d.<[8߀@–%m(Rgy`4XVũ)1OcJɫuuYKBW}1[+1l! .ve2K~qBoک};@!I- j6M$j[?=Cr,ˇGrs0%>6Sp4ӑ##DU <E.llZ{ Uq8!ɼߛԶyuo[,7A`sW]17caȚ''v()?Q bY{)k[_RRlaGeMSeMm貮?`i:#hIc@cZtʐ ;ER _ͧ Dn&ux=>p& 'wn(ve[4D>t!جނHI}6f5,%+G QsYySn޳u zC@ދCdoP#K vՀE`Cj%1)cX`u1cn ogUS0շ= }=eFJs9=%5 ~[_??7cigGe=b+rГ1eu=ׁ"PhA`FA>3dnw䆫rROk.(wh|k/={h=4&nvlwVd2^t)ӓv`|kva0lfv6ZhELZ:ޖ-@5,h%\a}tXu64ϫu[b oh|'Hzk ןV$ 1a^hfJW6.5:s7m>=WXYSURcF~c77a1{ uk endstream endobj 990 0 obj << /Length 1493 /Filter /FlateDecode >> stream xڭWOF_a_ϻVwU~P 1uvB"ٙ߼gO8tHHN;fwO-p9<_,pwcV̹qWdzTJ|,˪{׏ ~b)P W^/}{0;X1V! y}f(,bͥ:{dOttfD4i4MݧH:pXʈERLu\WH }Pm2W·[C6+s<3y\7_T;GS6k'$m} +bŭ[f:E`]\AJy@ ^DB5EsX{C-Y1Ըc{SufM%L1yIN輼KHl_ q7fEb5fl?d(Gv{L ]~? %,k`]V\%;=iq/B-ߡ>&hH  UA.F> stream xڵWYo6~\ 6^ԹǩS )ֱu C lNZ-ùfĞ/|c'-h{Z8x{s8|<8CQЄ9P2s~w7|E=F'yYU³[Iq7{q3˟~\C/$alIB09"4 ^QDF}\]nF.%_\̼m <gp;jD _jܚ{%ۺ$]%E 89gbuFjS5yf &^ȝ/p򶬌)wZuChi0he15^4߫8/  {=P83kċm.PKҭ#UqLbpgGQ救}wbZ kSG,Ӽ1 ง6^q%&(.>e!kYo;{}\BhH]> }dxu ٔ4JYZlU.S\쟲3jR/>jԾUNN5߉:չj@efa_ 6^V:"+'ʤMo2VLyjU~pW4J,#sI#\[3eL؟A2Nt"^JN<7U?O3  JW/v7ٰudL f7SۭF-lHDc'Zж^=϶=̀{nS^yY"UwϷ_t. ov^#A0Jq;1#ev&ýl &0m'=!jaxEHU endstream endobj 998 0 obj << /Length 1125 /Filter /FlateDecode >> stream xVKFﯠ|3/aJRI9#bZPF>=tV[c[f^{I$K]4v>r\Cۻ?kQʽuͽOcv.~&}Mk<",P#EeOf-4J~#3dEZ!֘ P+H%*@i‡! h+pc58XHjcY$v؏KC^`Ppiߕ+7m]gMN-F:G7ـ;1@0n,v!t @2.(PpMk/|58L*w݈lA2.n!(iaMeَ]'T+f߽FD J50eu HˮmGTGd1b%N` ~XԤ+Bμ('j TНq)'c?B żB2~WsuX[;,i] TLXL{p%vD~Q5 `ƌ{k L!NlUad Kj c@$8:L };ӴQY3s89AuA9PbҺ¹%/mb R!PeW@ѤO\ͮ+avIXkw+TfQzy& votu,)_ ƊZa0/DwWSZr}u[Qv@LLSϏ~sO_6˟#h'|_Ӏm/vʝ qL$gqd<)' ܎ڥqz'LP7ؾtyw,ܦXfqٵnŧepSI/?U}<XKt-EʆrA$@KϨ,/j[5m_ e,3"+#,&0U߾fYG6*/d:iH֡L`;}{A-_Ĕ3icZ/X =ɡ1efzN,iR{INHۇ5e}]b^-#W|e}?B endstream endobj 1003 0 obj << /Length 1803 /Filter /FlateDecode >> stream xڕXYo8~0/2`$uP*=Y$b>}e:+ g(vz,X9~3IS3g& EYQ?n{{;Ju,(E~TϔZF7t"$~Z3_IlUv|8p?U`>].,3PB%)0 rza~&=[Ճd ~'A^V/ЎY"BΖ*Qe&`!*z%l"cY;x(<۶8}e65\i6ruI8$7"T׬fSeʻ[{"O#ۚ,pǮ3,efy7i'j*<́HQ]bE9xF(6DaMzW(:E6]iR(J xb bkip; @{vɇnW"Hn =\5)%;Z) 8YЗDĩ!;Ye8D"SrㄸqPO ř;&|dv >O|qYr)8/)8@|؞ER" 2@4a'(a!~Y֧ J^^@(>40";&j 8R* EB1Bcӑ)d>Tee'fBgfC10$'n.?TL(7F֛&'+AAvL[ֵթe ^ݼu(b|8tv%۾?FcC]gQQnZ)E,x,(l*L;}l: 0 6J C6; *2f\jyi. 9{XkA?ɦTz$oVsQÈo60OS! 04 ֐N\b+#5+bK M3E3:rvy絗i& ׅW?-c1C52|%3m2<9m5)uUiOq'C2&z|$/$thP:Z c*dSxc?):d:2X{6('᥾O^MHEA|TarSh5Z?M3]YP @Tk"s-~M{<)z$[z4~T g_(= |@2;HZo`G9{5g}nm,<#N?]pˆɵS?=]Wuve?%Gm?LOvDSL=. ]_! 6tCMAAF0eS*QP-]:lTDs@(:'<5V ĸ )_\ ȔB"/tM3l|}/NM?=9J7AWgԑ!!BeǮŐ۞βrkǽI*bׇ 4PaF4~.G_UEuVFܴcsauB `ld:Ɣ*>OB:@S*=nxJ2M0d endstream endobj 1006 0 obj << /Length 560 /Filter /FlateDecode >> stream xڍSn0+x$咢(8mAH%Ai[-_>$U0 sٝ?@Z HH݌v~Z @_BYS@TDox)i Rb}Ch)k.l~?`+Pc{m%?Q+&dܪŊq &UsBI,qQm[crn90h(ky"򝭝oLwu˾jU͉)Jg&lw(Tp۪2@:ښiM]OS/NA){d}ӿw.9 \1!~dUrۼ] `oy\T1C} Շ^4=6#:Ÿ?&\8Շ]zsJ]y"YlA OTŶzxyS"7{'C endstream endobj 1010 0 obj << /Length 1390 /Filter /FlateDecode >> stream xڵXo6~_!P(ZR=IuX׬pu(ʒMaxG[J6E6#yE#4LL$vQ͏'`l4 <y oq)s-J_'狝&P%ۺwbOa,T{>Ѧ#Zk^ӳnk饹q4Ҵ=u-QRvtKg1섬Gv7ZOfCono3Iؚq<9΢Pr gH&gS9arl4"6i1W=2<`5M-Q򻃡:;a'eR I?f7mVm,*SFS~ե/6yJ@BSU?E{TrZ9zzf>Nܳu`*^Bo ^WO/LMW28lj=g}Rcld^t%&:18%0;Wk"{dCY1 ^^yAt5'R9ܹ+]$I mz=a?"=6F#7=NF[Eu `s/rMd[UC;%Q2YYJ뵩*fmf^_@ѥctkt[EllOn } 2Bi2J<4^kb4zO:-guI/ʲ07nm/ic jx}PA͡ȡ2*/ׯ0m>yUf@L ilb&\h"/4Y٠P Z;kW#W7)R g*ٿqܮc &ޏw /M|5TGf? endstream endobj 1013 0 obj << /Length 1392 /Filter /FlateDecode >> stream xڕWmo6_! تH!KvhBX-\'~GQ/:?;>^KOe図;+o8͛`oG̹X]md&d, #vymk@/axS9 qG!ObbVYK||+4j8X Jx "So>)"fސW,2f_(剬|I|oo1{0;l2>qM֮0bVW5HıULl=`Rִl1Crv=q-6Kg.@-5\IY21F ̕3'SO P9z(ts\l>-!!7e1+ǫ*NpC6,: ;b ɀp>H;hbdOcGv {p1)鴥,7S> ΊB橳u!IȗGGr`|k\̻n;kr2+f=tpdz)2/RN!ӥT?F<"܏\ݺD ~pF8ĉOD:܀wnZ콵9* 0upQWeV6"4UOG9<.:k[&jhu"w1& ܄8"%۴n)4J aر`!s<^ÐegpD Bbb{d8Xp#9*#RB[oR[0dAhqПqDp9y(7yD'L*>Rg%J[/69I:`doǃwr8|EG.H<}<䕺o~] (7^d yM} p{)`oOGs\HXl  `y[ҝt⩷3T9JBȁ)xo*} d{fLv#0>boޮ%='xk%_A@%}9rݮա҂ІBSgUXdΘѼf[~uNW  endstream endobj 1016 0 obj << /Length 1749 /Filter /FlateDecode >> stream xڕXYs6~T*1x;cE$Ċ4 [)RCBLLkۅ?: $;tI#j=@8P_]zބ;"V:Z[q+<]׳><ěmkإ ,L/W}X5<ٞR-CHMk;όn̷nUz?uWT kpswܱ\WOOǙω/ᰈib m(z:z)n'U[ ٧i[h\@HR1lw wNS>"}nx\. >؁W:okء` `QB5z\@Ycv_ObL.=E=kvs[?q.ֱ\M 4֦Lz},Vy:Q~\#4zd?t-OJ23:U)ԺdjC^}/78U՜.K={O?v:rqWdI9D`gb%Ա&`+(n,Ygۚd9H)WY1K262|2fKUeРVe[\%0qeArXqѸlGu7+.Fx5:t@F0d ڠ.V*{XmȴD,xnc=I~p9 d5,wb٤hƺZDo z,Ejܸ)S~LvbU&jh#$ϧq)S3Qvcdm҅tumd?dps4/OMCګpCF # `-h0D l`DyYrcs8U*EdWqr{%ϵ0RpZhuE3ݗ\v=xc~-tԽ<+wB:mꂪIDOd(,~l|:|+wzu,BS֨`(#O"TP.T@VJD 3NLjW/+1Ta(~&> stream xڽXKo8W{_"բn[d@omMjeգAɡ,9JvEXy73Q4R,RU_$n-rtœWRF4!Yh$$bDcW]\ $D H=ޚETF,%]Yb)SZd"uWbɕߚiL6VS b{J[ڥ}tL]yOvu!ee~]Ţ򿝧$fA㾨j.?1)὎᪬-g^kAHU$&&,~m*7ǃb%NTRlƪК?(%, o6 \AI%w/'cWep&¥LɱDfPD7x8thi*ߛ99$=ʈ^RS"3>x$3V{4K1!x ]Lz]W*n'DipE?.e<7a'V amW}ۢY%#zRҫԅ  sz`:ZS)%cGw4p_8Քxݘ3~7[{M=0MYw~oʭ՟/r%_CQ"!IhT教lQovmݹAuh $A 4Uu;$iMeMR" pMg|MN)]cO% VgCMa![~ 2wzj]5Tvb¹,rz*$I \M:vI%BPvZuߍ >Ln@i/ Z(’j-ޙsmtNp!aȂ(L#\GÈNHfj5wh>d,O``lJM+?d.2|?9STL wt"v>e~>-ڑpzJz2f)|,¡%H}v^[R` -.jg>\ \؞zv -2ӲZhO;P3mk{9U :DO}ph{~ >`G,*Y=:o Su&l%$ Nu1? aCIOQ\Nc(6n`$PlvZ!+Ob?҄$Ę>h߶e/1C-|g/,N`׉u 1aL,1@>MT|k`2O8i1fazn7LinǏ}n~ r/\ؕ endstream endobj 1026 0 obj << /Length 1858 /Filter /FlateDecode >> stream xYK60rY))@M-HAkklУ}R&ez@%~7\H]dl<[7=.Ï7[ĕ7͋R.hJ_f{z[[8IrB&oHf=mGDzYWRU$Xq͛is$!R7 nj"4LT Ss^orbE3%˓PIZRdhZrz}TSJK$Z]sAIհ28cWx+`E%QC=-꥙ s;(;mg1>l6Z/@;Y${fwtzC['}}S" ִ`K0mg ŭW6ힻ/l_:m}!aY| Pe1b٠*P{XUßK {b-`,֪Bh+w]SP+Mᫎ7=yg{ewėWVذ-+VHӢf+w}~X/)Y@IRCmƺie9 Ǐ ]߾VIr1V+9jQT fgD,WR_e}oe))d4c$6jOUDI'͂nsnrAeJ~Je i HyR LL_۱bdJv H7f}+2fl1&Ss6 ҂IR<߮Cdp.bo_߁L#FHaYۦ0 k=a#i~:3t&Gl̼pwD>^m2>{qjV?zP<-}nj~gZR]UϮui@tn!7=ItjC ů2w-X=iL lgyZ~6va=uX?m+7yȱB9m^k b!mnq@t>5Vg]q$t䅧f^\8]`CZ09thER> ;ƥ$S|vu&_ԲfTA^cQH.Ext7ʡ5$tA˸Fann`-0i=).VvsǬZVp}5eR~i~@ǸJm:`b5P^}'KȥЫ"6A[E*wcjŁSY> 5[n_ͮjftәn\C YGlAen#7(IT VךW$|e=Z7۳wF/<,0mC@{VrwAfldgLC &t8׉Pu"q[w endstream endobj 1029 0 obj << /Length 1671 /Filter /FlateDecode >> stream xX[kF~طh5.B[7) -) idi֫"KFo{沒BJ(h4:o}m(M7q"H"M~wFvc9c.pBk6ls*6}vv !6R :˦/2xwu!in?^={u+ :'paqG*i঄oCmȂʺ̩p;fD B(nBDCf]ا c$U;nA" w2*JAR~~' !J?[2Hǰ Ii5Q\FpUt&qp$7 [% 4qJXd-?5 aM/t$Xms_gwzM3C^C""yd߭:<&<PZYQčf(}KjJuzd[VO V> IT"h|Xиtm ZRkn=887t*>G;_j.5؏<T_]UOJ./#|cYgLDּ^w EC[TrGl"oFC]晹R7 H_AOAe҈;6D$iʛ6kԀO2}8QX]g7Ց͌˰q3;Y<Ctp4bV@@ezc4YXA\X3;d4F` ! -^ݹ3á4#܌73cɶ]?BkTW w.Vݘβ.܄UhTl0B Ten_M-"w,I7m2t6]lOmܠGi[ڵV,RDUxʄ#=bb:(k\~e?Qpylnf&9q=105mBp)N8umӖd4?{Zv!/H ~96ɉe'e_¸8mi2KKICxǭjD}K endstream endobj 914 0 obj << /Type /ObjStm /N 100 /First 871 /Length 1416 /Filter /FlateDecode >> stream xYn6}W1y1H #vQE%cjc'+؇h8⨴"*+S JbP0Z腲c,j)TD,I u ^{A((Dl!E19`ˢqB{^BG03Z)G|GL+5!?4iVgQriJg8ĸ'+Hp1,a/ VQOa#.`J%vpӃ@qIx`2$3$H8,,J Ã; fD IKHU^tG'%2,||uD >CzF$2G (Y< i~hciq:Yڡ& )3,z0\H̄0ѲW@4U2Y؁%-hj 0m,p 㪗a6Rbކ,ɇ(S\Yڲj"1+>MY/&u4k\[q&1a #x!!woFij1#3dpsZϊz,]Ly/Zq"UKi{w)·U/-Owh既ɷdEQVES 6Cq}-~Os]4Qm./ϟvBSFG;#t5y˷R8^׋@#QC&jtOC&jrSHOR(G2=&ߪ45]_MO4;#}~`'txV˟œ[syȓw s=N?{S}/0øᔇ~?f*vT S7Xk6kgʎOhb4hBīzOQ`= }ȃ*O>ǣp{>|g<}GFY9u9s%[xr'iP7  S*  aNWr@0ͤos>CѫT^h5pՓ4CpH\@AODёLwg(^> 3t,U3 #ki7ѵÇ;g+Ը endstream endobj 1032 0 obj << /Length 1577 /Filter /FlateDecode >> stream xX[o6~ϯ0")CuE[t/ڼ{P,*K.{Hʢ"P` ?bR*O->(D۫BhL8Tm3z}{ݮ7IDًs]+ /ڼӭzai,_]L'"*Ih :$rU޵y[΁y6uWxhDJXV*Sp{@C 6꫓8;]{ݸ WtnQQ=t3T0wjnv>*},k] ^{=MCGAH^™ :1 |/=t| ުk^ ) gGV5$,ܾjꦻF'UÑ8]Y2&1aD8a7Bp]'4{UQN fQ 3X"Vyȩ OHg!/צ*-xJ!M, |/ EzIaBk|A34Lgy]qwòu(=uX(_CC~-,}'wtK[zIVG3~[{bMa8ށ$) E,rBy꽳A̮9ޙ[~5|8Fzu}4͞,!*I*RJ`(x:k Ȏ^r`<4B]4dBv](32CQ 2i(]2h Pnm2r2ODˣ~\'->s2s,zC$0%}K]F7ܣ3_IJ(Ulm)\.%&ԗ\p 1VF*&O(߇u`bQK9K1};R E`i66@A0ɹ6ALv:1 ZTO8"ڭ/\!;>4 4IdV3uNCcG}MДHrRGh^Z2+ҽ4d /)0,wH>RuԹY?BNWHl-Q0X(W1\QػqAr1,N蛿#Efc5"?<4&# N$;ôQnIK]Iީ]Zb\ }`7&=g@;$A> stream xY]o6}ϯ D ?%uZd u,;dǺ]L*rP`ETs/y%?" I/6ۅ~}wALNVWoXjZo}7ː1$!"x<諬+Jƒ|7yː8JJ~a5.@֏J ala5nwK\"$1i ֹi10X@iho%sk{a_TH6D¨.% ҲXO=K+aҘ#bNl;$sPѽUZ ӣ쯾X{:3\[x36MM9hP#| mѥ<:WXtkşO! *o΄knig _ 􎁪Z[c'c6j<3,ȊWQ`"0c?2r 74@~_^[wj4L93wyb̸ yh\?C w4fW{C4Ů&@7u;UhLmn'3_?>*4J437rŠHjܥo R+'a뎅TJojku㗚ѵVk/uS e02c}IOxY=)A&®|lWsTs$OlTͺ/ژXj2)IE|ߚWY]m7Eu;$V7c'(F %v"f$,jS{al\sp8NGF`@0'rd4sH>"$M@dn4`\" &bH:gУdLO};'ة?̚b%p*$(HO}Moȟ AڜۇL#ARivW_Zf6~Ĭ-V&#&(88MU0'Fq>r`0%/ ${jbe~|H1cAG5^o mQAGuNrl횆/K"ǹ9o aR cfC.+ Xd WCZ6y~j~J48*ѿX2`nWe޶z(p9$FB6zz6HӪ.]E4pC UӎNv>ԌžNN99P`o gWݥP#}!qy/{X/7&G(zR@+:>nģ 1VJ0O\/xfn?I˾aga$O?n|ànp/m endstream endobj 1039 0 obj << /Length 1287 /Filter /FlateDecode >> stream xXKo6W(CR u4pUzͿPj%Y~l0oy~̡Ü;Q8xEfw O$\y/(Ihœnj;7ԩ p/t{p*늺NTLy>hLSG0eEe4Bw?3ьXzYhL֢Y9#!)Ge[]K5b)mjDVWP!XB1wX@(lPԬ9cY‰|rG&WYvٺo2uS0Hɵj:(<1J3E9N~4̔5CgXT5o႟Ӵ \\i4ۚ[+V=PBXj¤٦Z3P:nQAV_gHxˆg>*?թ4)i Ƞ܁Xa0#+u"[мRkF}TMG2\ݢt-Γ>M|Y=[hn_9<#b%PL{ km`:3fDlDf}H$_Ge{5a,IW.ϕSk` /O筯ɂ)W"HN(H!Új¡^C{3oPi6Щ 2 HA=˾WKt0kSvXkyP룇/jnk?h@&-t[wW> stream xXn6}W1 P.lH7OI]Vw$RkQ4jں %hphiDF)RͱiݟaŇwg%`L,_o^2g$nj>К:N8({'BH6uv胹3[',%*CLĿm~9K&|%fV)Lpwk>>dM#QBS4vWeS~K\M[%\CmccQW9jӮ1;z[ ׻hIk%HBfT:8zor8/eѶe9},`Jïv!5w^6ի Ɗ<{\|pE0a 8=a8]l POn3 UreѴZJ#吏2@R`Kg"`Xİ|.90UYZ!0K^Bnƚe .\e>Y3W[SnapUݹnj׌}ByQ#}WyizUYlw6]TJSHg*5W .RͶK!.КބW١5'c쾾׾חoqm>(1#Z8ؼ-ceOj,Y [ hz< JOlvJo%<%ꔾ7GפJ$6i5<_s{JJ^yG_ۈ'^75mn[M*xv:?} endstream endobj 1046 0 obj << /Length 1352 /Filter /FlateDecode >> stream xXn6}W,$ë. 4ME}hrmZХNËkoE 93#dU3l_`ݮ͛ b0L˟/^ " uޮ^ݕ1Wq¹^9f3Tm~эN6'4iQ| D:Y0d n qp½^%$C)h<( Qb]ܚv򾓽lbG]ep'~'$c/2l<̶e,0ia Y\+#Z|<}{(t{=g3I1rrV@'"Ov[9u\Hvi *se~@SR`D $Io׋{AB!Dnrz!"!㈄MHQ@087r0!Ⱥ6 ݙ߀pM4EU]~mPwp`B>c]7gj`"¿"lrC1Zw +D ἲ$cdKiҼ yMTCQN%Ρg%B.7X^)n׵{:8yX*tuڧajN. ykN~*|B˶p̥A9JC2:t)z)KT!CuiT/h5+iNӂ7?~.:B Y^(fWv qRʸVFm Vd! +sl)o[,z3;2OPy.A2RLIǰAJ}ߎ}#v6PAyP.&B)[s#UͮQF?+ȆԶ`{ ~q.|ESL["ۗK+sl\ ?Nۯ,X2ܧF K#L!/)Jb&4!.C5 ƷMǤLm =N#0gHr;(7/*L Ixz!8"2l*$.' &,f%&;s,C#37?oT2B[x=e`@M ݼtJ彊99yaKyϢǰK=\QӴѫaI fTh->-O͔xI> stream xXKo6W{W|@AH/x}ȴ–JJߡHJL'NӢ-"9o bW)YEMW*J?\a/lOO7p8ǫn.j]\?aD) anŒ}]vUSNHQ"H'y@/W?oFpR܌0E1ثSIsMw}*]>.^E8E 5;wā`d_vc9U2$ 鎌'`u,8Tm糂cˆRڄB"$Y^hvce^%G8C Z7!6}02[{ hj1f^^e)^tZH 7QB C,6)A8 #GM@6M@cUZrbsNLA&8 d'euP1x(tD>s"1>30A2lt/:fa_vr1JPAt N{_:BW6UP1Nz 9 vp[_Xc Y(m-Nl 5L9+úhiXORRBVY`%6_!M]5>cf AB ZfP qKki1;#?sSg耡z?s (JK*n5qpktJ9$yPm1:\+\)^>W@ Aa9LMzsaNfhujmv3}Û j݄&fGe@ޒ 3:r0(R~c+IO[Z(7ZphhPM_'Fl.ZDmj 26iL6Fz!@T:i}5mSUk)Q[0k{&|7P\ͥQwcfĝ0wbz7!SMh-Duzӷr}el[_ 4,]]TեG-VM\U0}O5Ӿ\aF%m{SUq84C.q|j`l,H!wUm-T7e9{Rs(/%qxvU`:Mn0Fzz"MJ|F`#YЛ>mޥ6c2t>|f#d9(΅ϛ0o]2F.OF}xŽ+LxvD\„dɄ I%/0gdJ/ա^B ѣ滭Ξ' \ endstream endobj 1052 0 obj << /Length 1220 /Filter /FlateDecode >> stream xX[kH~ϯ$A4.e˦PM A'Y%%~hFF;NP(Kvss>H X,7g?Z3bb0'/\r`q7uXwŶu3ms.‹(aW-۵^;Yj)8CF_XHpv"znFn O ,|Ym!|bYâFNG`&ADzխnXol4qkO]Wi}83:ùeiԝ_T,6çcRc$Tⶔpsui~t "MYS`E `WQ6/.P!Sgiԭi(7{{1bЯE3tqnr!-=8,>Z (!_#=.c # 1{BB#+* S /WI$fуi6-|~qiC!Ǩ+^Essꯏ(ۑR E-WײQ]WB0 זfDy=yr9],.}^\{^Np=0ܛgv~]cw'\ZJ7*ʏÉC`ZsUtdtao~ǡByQڨ}~< OhcB&ZvpX>KjH>)&t,+DQ{n@4~=uQ WElV^Ac+b1wd8;+^!g(%?*3g5PK}a((/WW8 endstream endobj 1055 0 obj << /Length 1281 /Filter /FlateDecode >> stream xX[o6~ϯУDxӥm:t/+R{PdQg%-ȿߡHʤ$^ux#(8*HTU6m/n~F.ԑqu=PU8Zm\Uu{>B&)4&)c<~,fhzRtHRRdy2cϫ8'qF/J[S2G$Ggqze(ʩ2¬I&Ց7 :ZǶ;g$<CFS0Ujmׇ Q;-F{aKBRƢIRvVFt#훟8~qx4٨))S1y:rd3n4C*Srrxe( \:<uqs=@hU/{MNAݵbe Eh.tFxNQDӕ=l6Q], ⤀nD_e9+b4~'? 㨄,+Lؾ֛biƣ֋p%o%۬f0=Joyz#vY=c}[` sb69ǣ%2Z/ !l o|#~ rV:e{` 9PDp61SPfz#^Й>DSme.@::Fů ux߂j&Ƽwnoܽ^LCzSoy{s@qW7 Љȇ-Yt&</+ m/ OF' Ƌ(9W0U;D#mӐ*Qt̓i) sEA|>$4 endstream endobj 1058 0 obj << /Length 1112 /Filter /FlateDecode >> stream xWێ6}߯$+.@fӦ@h>(U`K,EB.6hCaq8sf!M /4H%CAv/_ka) ;u({cUy9dPm#5?< 1[k[:nɫIHZ Cݙŷd;P'mW@8p#! 3 :Wum6oI g2!|PI| 59's;b(F:Ҫy %,0@|NQi"!ټyqM~@if3@`~hG Ԝ[[vXiܽneD /MN-D]@J9 ;t>r )Sg83e٬j7=lHhgx""nG'll*u<|) XQ(9Ð~P=?4\rݙlmf۳my}U8u.XԧHg ̌;eoW@gr]NLW~6H0”hїnT:z- ctdbWJ |z)՗r8$Թ.d6;=',|}u3NO+D*:=чxeP=iwIim& յοTt٘^H$R퉸1q}hNMOd endstream endobj 1062 0 obj << /Length 1415 /Filter /FlateDecode >> stream xXIoFW9Q9KMH/-19RJRI_Y.h˛GA GYN@N_AF+dIx߮nn,PUszW !$.^JY|i|l˱Zwb#zіb ELWo֓p`<>%^2j):a)}uiUkF mE1(`d| Y2(JMJ9mgܝy\@~I8€1h$]r !SipĬm&x˛nkasg^X"^FF?cwn8LჁ H '@(@4sz%Aٵ(GQ$6(2H3d ,E| asU:W8U&heCb|\~ŐQg뽐[{)rn)@pu^OaR5qg]VP_d QiAyli=N\[sx9MH(Qn =ajV)Y%ݚ2LܸO] r;;zn{'u{"Q63$@m0Wإ EEpTésIՄZ:QPK*G`PkخJjuǦ2|,?wCm{k3SwD,^4];]hD߻X7yi6sSá noLChua) 3[HF I'y/]ЎxKό[|B^- t .FpkJ #_eˊl %dVZ,(Jr(8w:Zdk#3s4 Nx04^Ǿv۹:~L헝>śt~(?Ex#+¯ rD se4SOA+E) @ 6E & [0UUAu3|5D_]9S-zi -)./#r endstream endobj 1065 0 obj << /Length 1360 /Filter /FlateDecode >> stream xXmO6ί Y8WUz;Ѫ-/w'v Mlǿ8q KNgC" ?$hI$ˢoqX G rfr}ME7s_Hղ+JQj yG.Hpv Rg\I#.ME-]eUުh\m]n7U-B$҈ Ak% 9۹)F#c lͲQNQцP`$7i-3%cUl:gźWq)'#51#2\|_)JtkekSqY>ZϘKYi3і_nTK3Ċ#A L1}m-Y8|v)FRދދAWt#_j #QxNNBl^gW"2OW>8I7"IEP4V[o*+\;3+^)Uv,G˾]C(cTִN0^Maxl\`S Sf a}HETjAqx#ܟ7DE=;rpM6 tt@p SQ\.wfP-WтjC2ICފX4 wzk_MѩU1hNsM":ˊj#0* Пm4ϭ}8ri!ƒ/=6A5{v"_<d粿nea=Pah (+{Z{Ac`fXJ[2waGAfy c1!ؕ!qh4/"?V]. Zʧ($4G $΂(#S81v}^ endstream endobj 1068 0 obj << /Length 1118 /Filter /FlateDecode >> stream xW[o6~ϯP ^%CaM[@Ѡ1vTv4ؒ'Kw(țݵs?xL< ċK$3^_+`ؓy~qJ`xe<~_ܧZUAAȹ_MoA-U B( ~x9 *Hp#7 QG nBIS#EpԳwόdhB#Γlު!/H,Ytmx`@{t+OI*kEY@X|T&/Q# ao}Fa S zME, BQ'k!`WN) OP"Նpk2bL<hFp䢽 iٞU.UNg,oA( A`=CdL@Dת6ń9]A4*]ϔi^!V9![aK_TQomSl&I?Ng(%46v]%&Z`9hP=mN':=6AĄ[VPYK$b*/V9g˲ڤ?O4 g(ł+@x}P02~I! &_͡!4gSV" ܒ&gyH׍J$G ^D.l|]=fn?S3QYX뤹y=?!XTO 6')9qK9r~!tqAtZYHh 4Pb KEQiޢKu. T;eS1 d`IftgNa<YuQqskaz5`7"D'c/L7۵:Eb0@ HT5{]@"Q93-ΠZ4x3-ֲJ!3]NQ͝^+]7uq/%j=YOr!Iy^""`-uka1QzxI+Շ0+= rk:۰uSwGw}sO"k ? 4`v+G^@G6k/+7n~`vNݕ endstream endobj 1071 0 obj << /Length 1111 /Filter /FlateDecode >> stream xW[oF~ϯp2W`6j+URkY*,ɦg36:ժ[UQb9;o4 Ci!iPl.Hm؇/Q0H2Q4XPe>o;D1r7c@_nM%@.~7۵61d YĜ@9<2oG,weU /ƠG1ڤZ/|^_6B4/ Q}H>ģqiUk|oW!! ]N[7/л(aG V { ůW}Cb"uS JJf@19CʥwSLCQ BPLT:;g22s(ȶfq2ȘzGSPoMIJp;m*\WlMm>w'sw=WN~oߵehB-Bx[mw]"PL c0*!5]UN/]؈20 շg]*DՓѱ] 6-~6πfqN:}s[G4+\vJ1ܠUFEkWXb?b+N+FTmh{2 HO Hd-S~oqToٵy0؞2FH~>Z!ܩQ_ųK4d-I2wJj5wM[GXSxY \'/ScdX2 W8M_*=۶0x5΁ʹQn?Dλ_x};bOW ~ a_F&&@|( [5͉&o$Rjt+a]>g</FXS6/n缒eǭz@s*+>svFekr/Lw> ѽ%cԺ79O b%%n7۪߱7VP࡟ˮUSo<ؒN))=ߜ{oV&~ROqU7.8:$Dgσ0u endstream endobj 1074 0 obj << /Length 1381 /Filter /FlateDecode >> stream xXKo6WQ,oR u"pAjmBίP6u( x)3f8QdᏬ])͐fj;l}rψ_l٫7BF9jZoW&7š5u1ƒuq.7IWmr_7<4;SjcҌ*,Og?Hpv#s5]0k:DXpgеUF/ܚ{*D̹Wٴf-=4ֽEDtb*'ɒ)k7"fކHuT)(5M~#J ½E^WއvkSlQKk,8sZlG™,a "Bak3ɻMUx4y7 ]{HIҵq[Y9ds&] kno?}JC>2c`,i. E+& 5maHݢaLF%-{"q\ 'E(v8/ .x8anW>Cܗ0ѐ*pIF4Ru4ܴTqB124*G 4&nʺwiƖ^ ʅD(A ~ڊDt{9CAJ(TF,b#P15"!F=~=Uww5U=%dx` Dq{Ce!'([TE$u/ 軲/jp?}=&uI])߮TخXF^ UTڷxek@;tw71vhx7u x PZV;hLǾ"g1OP`z`考S2}`$ja]6}3^WŠ8Hڂ) *: L^* /OQ%񥨒8JMw@4k;(C# yY&jHjhnn*fQ lAY!O k$zeO g6}?ekb.>[d?!hOb: БHfDHtO9Y(>"j9T|$r]%@-=i T-ӻ㋚1Q;P;t*K'^;31O75e2FFy: #ͷ,{1 LQ2GcVD<|ظDQ,PSC˸ є[9}?7y9enZx>фq`ߧG. ޒ|r :1~f1fp 5mn%p@™3`,W:؈ϵvJ}D+AʹNxA ~r? (%RJz݆<|I?#c;_\)>2? endstream endobj 1077 0 obj << /Length 1603 /Filter /FlateDecode >> stream xXKo6W(çH-Ph[l/)zL֖ =n_(˛Z3<>I$MbH1wخ{rfn.  \nf^?^1oV"}R<u_5N^UF%΋7?^|3.@gZOU4! a7Ksw!DNo7` IZ_=U?3wyB*FN2ʑ ©YMJ"l^JNrD9 B}X:(h.`AgSeU/]Ibr9t`F $A< {5=Ūb=Cվ3Y*#B%S4J$QluhjyJ=/ӊ'mR=7CzyX%6FGpwipݛ롅)wgݘzv}yZnݹeiN|siA}WޔK^ =$M2Kޕr^% o?k)k, :vG6p,V, cyHy6z{Ah,oG;qhFk2 =` D a53]3,=iomo_l+6 h6Nz Y/2 0j=Dl=AœbBomi+1Mc&BN"&^59Oy(W ;Sx;c^gt`Xfea)Ggs"h0Oc+7CݙY0qX]F|6--"M;.wK`f82&$(WyDAUjʑ6P7FNkq0u+U=wF~hkhKW0cK&H3'8V Xe6'D@z$@K-y i]3W0G1GJʚ7cazQ`̛q5ޚBjkqؠ>bv~舁z-̟aaqyeuP4 CVDZ) tSUOFc,hYa'#n_v]<9u>?pE?a>1Oll;ۼ eSH2u0 lUzpR8H9W) Mr=3 {i=aW$X;[Ec?X{uHm#JGaHk_?hA endstream endobj 1081 0 obj << /Length 1278 /Filter /FlateDecode >> stream xXn6}WQ,7EH_R8AjBw(Rj4iMI3gÙ#  dH2[vqqv13˟6^'I@0RX`Cmv]vluŌP]E1I:<ʼ-+i@Е)"0ip-]{<:D9˝~pV^(AI0b{myV݂_W(NO\cSHB-ouuI#|s%썻V`*2|,[kt춇"=xl\:䞥ʺ?fQ.gĠ ]W +"j# qP@K( WbXu {5,6ۍmḡnN#V=vZ7E1zm$XZy]CS] Oj\jS0~1/DDʊb>4,H Ry5-SfU:7c1X0cS>k9|DHh ȬIo (3Vd /&UƠ}AIBikkIN4ɋvHI~oLp421Ѐ+gw޺"ؾb"=gzО\gG3'bM trGzpdߔaUYB$C@I+ qnԕ|K`fe9RLڼq~?0**{ۜ8@#Nfp}W (!aTp5"`ag7,*5ڮ}[W}wF&>ѯrC dz@E Ƽ+:Ӽ}Zs/Jq6wDؒNgT x)ǥBV2y[N,ts|ڰ{Fa/vb?gdg,^0fj}|TJi _VcJ-U7 ajFN> @#8d甆pIImgDᆷtX1giꩄo=&C)S{SphvnvdY-mh%RpLX^6_Zbɞ?5K%v*nvz [2(|t6 lph'XoOf7Zc'A_I|Y&UV r2m?f endstream endobj 1084 0 obj << /Length 1490 /Filter /FlateDecode >> stream xYn6}WX R(&E 1M]v-v;iEl47Egf$CEU0T0nΰ7xrXOVtq %I.6SSuu;.ci89Y uۘ7<}7Jg9UX)S=T ىG4! a7K%‚;wKY.$Mj t讫m<ʄT A! vdS\^`-دRSkQNâ/H T2,:_2C(vEx^L"KR_EcSEO0uUݛ\KESF߲;[e7ZW ލKz5]_7Wݭ)j6vImzMoˌήk758it|ޣRNQz! 桏Q6";VmC@;J8@T7a 5 h<*K9(HCFb7bA*j^+_J0㔻$vڽv ܩX߯>f@@v3[\m6x -2 ݍzpUńÏ =9OEY%F'4ڜ;^NDL,N3EZusclD+I"}mYtܖ<5;+ *t˽[Y( ·pJ]Mz}J5羐3I*3T,h߶_k_Pնo/Aύ#;Wlϧ:]y#aJ=sLxWuoĉ8^xgS|c/ Rd֡d>R(?RPS ŊPIUnff4A,X&‚W>=v6Н.Gm_5W~.pWILݦ'hܟ Ϲ"rjq,UK/ՌD' VJ$h7'/oĤBBV 1A ϥD IUռO/wRCIN{Bs`|%97{"4{v@`P506N4\h&: =FCFLH5KpS.">{ߞFn8[_hYG9f]7ha-+yb !03{[Nx>5[sEwF}F𜻞sw} vc4$ z[]n]TMDc|^Gn%,O?bO/wÉ eu8ARV]gzlgtoYI(jm0T##|@5߼Y4Pt;=B^?nLV-8`3g@QWйL7 WAظxxz4khhtbF`26֔Z۝8QumͿ'\)y endstream endobj 1087 0 obj << /Length 1268 /Filter /FlateDecode >> stream xXKo6W,Ћ%J 4u"^d*]K =A{/=vi{Hip|34^YUqwʼ[W'o.8_eqWWsUW:8^aD) 0baʂ.u!È8~99#葖:CsH 93A37Ug2/6歔,zY0/yYҹ{G׷UIyF"̱91kđ Š/ƈx?c'Q(D$E*ajp)YSiiQ2ЖCU7k R{6i;r )Ya(K$QLgѝ!%$xF80jQ MxpB `HSkV/lD\7LQ !%G"lv)@`#d"7LE!1~M@J1DqBV& +¾1_=0|9U/shev7Y W֮o/ʂ>]_y u(vkDD .@W4EYZa8˦]-{R*P*F8d1o#4a#|c|9B"}j 4%תYP;B'N7w7iVB ٣o@5=(b锌ds Ų̈́#_2?_RX-a"`,g(2ԗ$12ħ,E"N0h'E^i˫3`2g0V\y^t8-\4y+O UdԠJ:2@p@>&s5zkݴ:C*Ϋ};ȩl{1|2Ǔ{&Sˆ6bKwnۃҒsjEfyd϶NM]uzN `wzJ_yJXٟxlfϏ;S:Ϟ(GcI1}|s)n(C&qY:5K|7 endstream endobj 1090 0 obj << /Length 1237 /Filter /FlateDecode >> stream xXKo6W{ˇ$J) td[d^+p$U;|ɢddoHisrƃV@/>xA\ Lzuc$XPmGx/AtQ (N4I8֛jj% ?DQL9Ί_/nW(MؙL ݜ! |%G f(/3UZ/fT Ca)$MPe@ J8hbjHЌ"M`f1Jdvqv"a`Y`Ir:PDJ,G2DR:/}8XMm\yܗyL"j+ mhw66Z!J3HQ4nTYZIxR:ႼIZni'1 f dAԺ[##N$VVwyG1T:*":4r|lU5sb[?Y+ ά1;*8b;Q(ՅTkP)' UL0}Yh{R(9'0@X.^L303?3{kϯkV;کib۪oPpPL/50cZ|ű-UI {-v&$|Lr $Uv۱Mǜه\#\. $W.2[{Zz\?%psѸ)S] {;=6%㡷c[`4geWt͋Y,@6:LP{E(2g~oyı5^%0TS3ݷMjN|[ t:2$p= )l5y?= 0؟30r:#@(?kZdxљ+ޏ1)t Oɿ՛2ai endstream endobj 1093 0 obj << /Length 1257 /Filter /FlateDecode >> stream xX]o6}ϯУD,/$[ AFE,~E[ !@"QG^?,)JNJ^$u_ra^޼2J4ՐܯPcٚ.9穾r!d.+EkۺmޙL0Y t*hoW?ߏK&B#%K@.2E&2˥bYiM 7s!uz 6mRQ}Z)uDњ{;kc dgE!v |4>eN3kWsDWM^!-0 [ڵ?Pas( ;Ggc=y(PKE nGc4Em.>d=`)UDH3Y[3eU)MK߮_bYI\o2~8>MFg5O??.Pv:;TL:2M|@Pnw RnGDE_)E]{zknM/L](uWY|i.]aTEJ|Q|ybH0z rKn IFP!Oqba.ڍ_j=ۘ.GhW|EA(qzr"}gn>2OfQ aM__E8mcڐ l 7cprP ȓPcv9E4@gD%ҾCDVd9u<ɊXte7i +4S1 ;mn_bJ6êaėAw=x5VUDA8:04f _؍[i{ f\IC#xrUCH||=z{ AA0 r{yjCǮ"՗#qp| endstream endobj 1096 0 obj << /Length 1302 /Filter /FlateDecode >> stream xڵWn6}W ^uI@/K>}m:VaK%%!)YiEV8<39\Q<.pv &O˫;l܆P]y촉!DTƉ*sAoZ hZD/<9W\%#/ B!^n&O UC}Z"]$,#*NTMG` &`mt )yAqGL8c q?})ǽaB3@bK髺M]k, եAQE}?dYf{( >8>->u91x76ŇaxjMi7>L0Bu"NVY+DHm#@9)$1vÎ2gSui+ݑPN/3!νi@=iU#qB(ĘCK%,778aѺA efo~cWk?vn1>!c ap83':wX3DW87ZSCwUmmd C0[<"ZY_ 9)0q/| Ρ:;Lӂ@װp:_Fo%1R(}Cd,O,g+E^@1p)Ԋ9ppX;S`'Jp 8^TM$_}m c|己ʧGuc\'\*PpC͜o;{P^qHΊqs8Z:d|ps 2 Kłq~x=Rl u>b-隕t6Ɗ)rB!A"T"%<[Qf3ح,zUsximAӈ!n#?+ uoۡ.>y{\s`TTjXvi`X Lѭ[W0CXZfILX2RY^~"]u52 OB ^)|6"vz{7bh8 :Ļ.xU1cs5Z{4y `sp}z sWT‹Hhиsgg YQN/ endstream endobj 1100 0 obj << /Length 1419 /Filter /FlateDecode >> stream xYo6F&Rn^Zs0 ]0Ygl& jV9~^؋ pvg^–.`D#Q&Ƭ6[/n/VիR'1\ BaکZZ$gd淫A8'qF"_K"rf&(Bd?6lޯǬYafMޑ1J8'QLc} yh1/ D-8Í`V>h{5 YaP?i.*x2Upsm-_6VdE͙Uқ$0`^3YoYQ j@d: Y$cv %QbOe#󦼝SqpV+0'5b($5cz.A\a{KO2wFQByN8ՉS Ƙ. {8˰waCb/\ٮF9^ fIZY}"ĄXpA%S$!+d~q˃{R\oi)sRY',s4 3dDpL=v!e7qю7cJ_nIҝ#,Vrm־졋.JiK$BAWk9BS-<:cfU0VLm'¨%.M2gHb5%]tv_< RxPi]ߊkm1 TDUD5N6{dvl`( 115l-h MpLM¤뢧_u|3rޮխmۭVmQm{'k..SZ!38]FT_0[v8ɉdD~Ɖwb^΃1sA:| !b$gM !48N90d)3/tZǗ !G/ Mt뵻nԹ0p~M=/\eNkvJIQsO]y?L= y91YyP wlvEn}y膠Aխ'"tў71@edLˢPigNwwzr4x\[vbi:+ }Ru|yw#rkĈFlʬ0`VܔGCD#Ӂ*~>!u0VG`kӪSʹRew. endstream endobj 1103 0 obj << /Length 1482 /Filter /FlateDecode >> stream xXKo6WS-6 kŢceH.;P(t1EofyPt]lkN4Mga] V7o\Ќj3*%?ncge9Oe*LZ$ú{#G=2eyL"7WI"%~jEh2"n2)x⠴G{(a UAxRpnM>W &I: , bJ>D,+gbU&AA3VPD-RHiv!!Q*~ecMst&^fapӓ))+=wuQ^S3#TnDŮn 0f"l Cdֻy|c"fx;o|}9=c_iҾ0y.*8!jbw.:k{Eh?D]!9ug1NyR]>L\j…~)"{Vff8FtO= :5dF%^ idAL2B ;uG1 J`=}6@ssCɰ2]wЂCSC4MWv4#*U~b[;@-ӮZ\B&F>sDqg{&rv5~ɬhp&5UBآ Ȧ#%n7P e\θ7'Ɓ}yrhJ}E7\LET/ t{)gy9n f{s~f] ] c]v&9o|ί834z{CIb&ܘuvn}Gg4HapF  ; oSXohܺIjS&8%=(!ЃȡtHi ]6r2\Qja*;Gl@N.n>/ ￲r"ދ%4xוоb 5h..(k߽O>V5~!$iKOR i endstream endobj 1106 0 obj << /Length 950 /Filter /FlateDecode >> stream xWˎ0+tABB<i,E&q!P*|=ױ̃n"{oiDGEX,*,ȴ}uq &ȧ陔%8'9yeE>Awq9G8BX 46Py#й^N74GB/%X ~Ckp(*4,D UlH VZ(f\A۫8). |SAi,'K\*MyQQX| p֥6Я?I & XeKl|3 \T4iUYQs) |Tvۅd 9H$.(<@9诟tL4ԂX} TKs.bw*6}7C]Zɉ`߳%" V@|H@Ծ QdTXCj2Y= 3&;k_v'4a)wy=K9)~!snv6b Hq!'uuQ}gPtF><.MP3E.o~ WM \s\Ɗډ±n7S5+).vz>_Iن2X}ӎ: >obڦwCi_|qGXDp-@f{ޙi6 C:8Rti-EmD'4Sb~s;O~DZ~A] \pb>G ɛ^pFLľ|A.w[ BƮn>tI8JpVtPcV$\FIl܊;⧕^뭝f@uUaBlmO-ڱ+utPg endstream endobj 1109 0 obj << /Length 1466 /Filter /FlateDecode >> stream xXMo6W hQ$@.\aA+qJBlCԒZ9j5~y8 < 򂠂Ap̿ bW8AeR~kC7]uń|Ŕ**h8u|C[jideHY/?/!F+35'i J _nQnrG1Gqh8$uyƨd,I)9QK('A?D2Pؠ#c(˘ ķ4E)QUo]"Ɩ>9$5!5$R"X)aX)F,͘5)C4Aa]}`,A)>OVhQKySV"L K7Y[ᇁm5Fr5S߫oh"a}c$ӱm>+i*n`H lIvܻel#$#d@r!j~8Og-؃H?Mpi~{YrSm~ik 0Q=6=x}d|hګpʝ(ݼ0BRڤ@ QFȪq0E憹l,fX5öl)ԍڃz| VWj NnZ jgWJ/țZYec'O#EreNP<ȃ @ xn/ ||U]`BVӰ\:BEݶ(=E=[V*kP'ӛ|rA%q~ΤAcUbe~樂io!Z?zt@P]B0昑FʙBte=s#Ch= ׍դG4S/o%#g-K;%<)g%Pv_g=^ڿr]gl1S!ڄZ#]Wʽߋ*hy6t揨/ȽNg J2y)wi#}%W ֙!&⬉>.Pgܐ/#ǚj]e si#X2l' DSU'P)$et z%+8Wy;,U<]P_@fe:(`NWѥ)[(Ú0Gkᮢg/*?Ϩ_N?gBf}brTjm;Iet],wևx~0CB:"=>ڵ^רQj-qvkUR$ƹ#wwVu;9z AENg}"Ԛ\Gi9a iSW螗U'F endstream endobj 1112 0 obj << /Length 1630 /Filter /FlateDecode >> stream xXY6~_7ɀň((t)P4[Dwڒ!ɻͿʢ-@ 7LW)+V*$jUoR}.xCQ.d&͋RhJ\}5}, <.^!dzVcӵ捈u[uTֿtd\2I驗p7g+*R8w :q_tߔ;sm/0~:QЪ 9i%FSSQ2[QJ )?ωH;?9܂J9[LQJ B~ZDsi_AvVR J%uMZz}no*\2gM{8,^ U$,wF 㹏0qX2{0vιoS P[,w:<n^. $E1{%YLitL@6fީo֦v@i@)IϡD_Kr8vECYRLӔ6tWjҡ a9!ucsPo ^SдתJ " ˶e$*bMdJJ'L&Bb؜OtC[Q2ԍrw\!#"?9jXdP.GdquhXqOC]w?g~m::ΰ5S0A L6`9VQ(අ21<*$}(!+%sI E=)5zW8 ]kOG H0˷K3̝n 2aA'l'˸qݻ{5 PU>QsF;yF+DLl $fC)^`\%u|/8 [_觵O {pKbH{?J.'*`f~c0}qMjwڀ ә P S覙EvLkYM`"Q!45wya6*i=̙DS~*YYVg+Pus{`;>SBxѧ݀QYx9:`a ]u\.)^,nM38ZmtҎg̣D{1tǃRnl;`Lx;Xs3>_JR2NZPSˡrR S$4S%{L>dP1&3cW3xYn_ Jz K?ZoK=Hafg ӺIkd~}>V߂/8+Չh -!3UJ~x0Ec*v7z`;k~f=9{aS#c8g[!ڡV68z~E^c`]%kEll C<41&7Fmr_ (~΄>baް4L}(/v,˲n`GH:Dme\oZ](ݶߞ~9O~PB;M=˕_ endstream endobj 1115 0 obj << /Length 1113 /Filter /FlateDecode >> stream xWMoFW Ki 9nmHEJ$AR ;([pWo̼]S/SS1'1Wxv7||Z ')=$Lٍ6O6WOV*. E_]^6_LQ M\2IW2ugtcQNBtP,"S]VyA("6DYlD:]y8+?tlU^QI!q,<5&1GU iC$ńb/w(ôN@pXQ+muڽnWPΥqG7mzb9;HB]2fodi33Θ a,OG䗥HX,pbWa#, &,2L7Ɉ+@`W} b+%>5y6i~l3x,]ɑm@ A(a{m X9hf@lX-tG~tJY飉3C!D Gk=STz]OJpVFz ju»xt&1+^WM~#I rBur1yfZcN4# M uS^ƋQ9^AXq䵷:ǭP"bu'I8 67^݃t_,1m3<:Zu_ee}L>w7fspڿV*F׼'᭝'67|EYHC !^X/=4ݒ7L7\dIATOHL8JA,!nFI4tfQ8C熧}7Gj% ,'Dd:>Co\ &W\}Euj]'BۻbJQx4 ^c@iFQ,(H"QdG+P endstream endobj 1119 0 obj << /Length 1520 /Filter /FlateDecode >> stream xXIoFW9sY9 PhZR=4=(f+ɯ#šh[j -|05|![V _%FP#U~wxC w/ZqV۩76۷^GBZGR*r6teUHnmmܮ#:%ҬQ*)Nt>24{sܔ*בҜ|c/r}T:^^dMNBi"MfL)`TS}v 4FQ@c/HKO%%I!J.\K7}Q}Yi*ywS!_rڇ|ל&ZvkR0W?}Ƕ7hc"=4!U7u5 >EqBBNMBP-<Q.ƔFހ*Kvsl*)r+o-= ]S<ҁ(3 )1;ֱ)֌Y3h`}$=Y $1Pb),S0q7c@KpN Q=BQ9gyZdəuUS2=WYbJtuSi'DAo1GTh0/}h!_Η千C- t6sUZ$Kd)b]SZ+UklͬtEY]N6%"1ɸE003/%7v^@S tݭ 6~'qm]b #2P/G(tAR@M0@!Uʸ 3aRrh5tr[XɈƖ8u=z=Ar{ sC#ؘY㢓I¨c6tsoޗEpC[Y,D mhO!y!`v6ǚ=:HJ` GOُg]9ypWtN=?KXR\TxViqP 9z%f_o6vfvLڏLJ60\pΎ銿 S7fg[ Rt7 ^ =~pEY' I> oZ|KޓVsiD:?} TF(Y1~qH/\.u ]4Dϴ͜Fן!PaĀ4l <}<j$[b<6(waDXv E2(pJ ^]tAxIF],@㚦<8u| <|}x*T=FMN#L_$ !> stream xXK62`1Khm(d]dHCYe$Mٽp^%[Unx Ew7/^Kљ9zkrTFoRy_nR!dzSVcӵD$̣M[MTDo?p? L)'j/sux U$bu ڜ:L9%v` -wv%g,cM{8~Cߌ[ohRnR,c^۰"w+]@4g0bK0r>]x =/ %7?i)I ] yFʉf߰Wu (%4ˈ`KO{%64L_޾}jwm^q/HVpдŸ;K e-HI© 7GԋJfQq71x)fyh5t-w/eEN̞mhBNDQ|0HBjPǐeiX~84ֱOM;ϓmrl7ԣ(SmT*{4qGS#oZ6!< 42TRVu-hڈv_j08+)3~g8Us<؞ZPi[ͩʳ5]NG]ۋEҲ֚_t0% [qU@/~ehP ,qii{t/sx+mo]EV,䐡Ȥ4>yݽ>?{G:jgTx(h4nDJ8Y9x.Io ?V$l!}0DjTT}vUS_ɧN>ER8dz+*.ٴF1!IjwjӋ3OLͻ) LhlM'AkB ֱk/kNlhvj]9r`O!<{YT@s1s?+iбheS:Ќg8^!)xurt~ 5SD82;p}:uP~v׺ endstream endobj 1125 0 obj << /Length 1114 /Filter /FlateDecode >> stream xWMo6WD,%J9vl|k{-y֖Iޠ~gDR_V_H<μTI̕;݄n3_.`dyEJ$ mcM?ҪU9U b់]|yWSa2\M\2IW2utcQNBtP,": %ۅ^@jF 1wF{ƝP%Lieڥ z5zǣ+Sՠ38䮜ZRZwp0aW4xݞ[)aq}Q4Nmdq195@S_4cҢXmSgZhNlv(_a՞m X9hf@l!tLJtTd.5_p~[+ܻ^;}GрUOw/]WKAWM~I XrBB1zN1LGSN4# WknMy=/VnfSjR2wE 4V`l<]Qj@g8 7@dY[`AS2YڦK'=ȷ0uVwϒۖu3..Mot.i?j(&]'[Mmn<e:g 5^ƉKMy%!aIlcFrwtdPXB1&SJ? +v2TFIs0, tyH0ٱ9Rc,`!3꿭@4HwQh_n>M0q? endstream endobj 1128 0 obj << /Length 1405 /Filter /FlateDecode >> stream xYKoFW9sO2@A]p}kzEf+):p}g9++ђlA 9\kg3̈ZifV>\r\H򧛋WZ8 Kf9Vu$6瑔$R\ͭ"mU(r/:/< |o?ƵT+y;wqIܵ1t2_Mmy.f74^0T;CE炭n|Ņm兊fJ’G،G^s" #qsjS(MJv#dD1L I5Q> Uo,ȏq6&79M>K@d6nc1ɩޭr5(eA HA|fMVT 5qKkS"Πn\AK,0KpnʲtPR{n >0["U< _utm]upqc˒m !2׫LEU0]aIRyMQ/g`?XPYn%is;d:8`IrCpԣƅ#[7Bayc$?˒rVjoi+SBװꏚ2C2j. qWϷů{v${7X_ kֱ#TYm&%Q̧02M-rz  CvJAy '7C.ϙ-==y]>nf\|D ަESBNNYQo+&`bw_ F~~l VK z_|׸ZmG]벮ցB,?ßpgU ?vA.+?F^r_0MY߂`A#;:\U4 O?.;WqĘ=Kc;ޕEj4gr @wuaC%Bbi("x4vX) #P:n/A!C&1;,˗iںAl's9wQ!ha c:!NXcL3ȏXxZtM;}G#_<Ӝ:+G_"T Vw_EIO  = 4KyߖS7a4< /pI{a Vƃ s^N/O~ްowёcٌI %1\*9Wi>ÿn\o7q$]<,f MѧRל/!Oo:iMe:sr]i8 endstream endobj 1033 0 obj << /Type /ObjStm /N 100 /First 948 /Length 1165 /Filter /FlateDecode >> stream xݙn7z >ȡ |+95r!(؅*N-Bdk@ƈ;3RLb́b'f5K 7䐩["͵:cͲ7P0k.{' ܜ18Y%*>sU[><ܫִ@QJ~מ-pKͪ09/,q 8\̗XR;Q* UCjKLJ)5YB_ڦ 3Ư)>11bQhr˚ 斏X FO%d# Ì_z,, Ɋ|'^oɁQS 1*-Ԃe\Jc E9R*8T,ԆI.x"b(3D!L>X#H_PIMz0 Ѽ%iR_b b)X. 0hCe`ip1#b#jÀ^[pdU]?_+Ê^A_EHXnb5sjZRԛ2]-VWo?_Ww^bX.ַןnޭo7~[/ןå7@KhRc`#2M2\f? p

~|swE:Gu~MW^@|oAz1w<wvS/SM9)%ҩ<^AYgKtA%)4_"C$%"rZNH&"Us wt"4NU#V{9g:NxI_2׾$OUsx/0/DCDƉ/0Ãj endstream endobj 1131 0 obj << /Length 1460 /Filter /FlateDecode >> stream xXKOF+peWd#rA=ds0plTli`E(@_UxU&(4[7m/Wfqt13_>||'9^o7?⶗:Fu>쫦V',:[ʺdIG:qN8)~$ +LQ*qEp> stream xXn6}W,W P i)PpOMdkٕw(RZQ8[Mp.P$,HNJ'A 6?_Pga4qs⭔%8%) 69Ԧ@oC0✣e !P WyW֕y#еFW#8En~LK&LOGSwӹprFŘ&bL6{pl2b)# 4ۙ;9^n^twա쳇"( #:sM"z7)K>Vpn݇2Fٮ׭}5DE((/۬upI/-hsi54߃(1\./AD̨Mk ZJnϚ/sn"(PAb FJ,P) #3$P"ﻮں*ssoXq bpԂ'NRJFiin/Sd 9d'0l4!Qjѵ܃0G,M|Yut;L–IlzgR@ETe擰>'kN& GY>G/Vq, p&3 `XwbgIS,~vi%G>]o<,oCC{B\Rf>dChf4Zr̙rJJ 5hg89<6~Ik3 G0t]}[V'X52wǵ}x*qb4^58kҝ~0/vYp\rtt6VWm편MVݮORW:Of::CN])jAus8 sVt~{O3M9ͯ:kF/h2j94e6~o~@MOw-L1exkgw qBA?0ŲaU;BE?>Tm6z{uE%L|XO<  |J9W(9o ˳#s3Rq endstream endobj 1139 0 obj << /Length 1546 /Filter /FlateDecode >> stream xXˎ6Whqė((4MZ޵]6V*K{EY8},<r_ Mz$߸.j޾fb J8W0 h?̷$'K0"'5nw[[P6G@; aVj J8GTUxNaBCB'}8LH9In0 r9Fۘ Ӡ?ݼaN$ٝ'b &b҈:Y/1-Zq٩~FϟJiz|" 8b]S )@qW_U׼\,ͺ\gYg彝k-^m2yӺ< ˬ\R(6dza{zewen59?RO֪iP-2 gG\ceMw133vOB@a-]vnlcVV<OKc(ך7j!3+rf$>9ME"_Y6|UU>[9J9j3L"-NV&I_f:-!JŽTNnh)ȑOPʫ endstream endobj 1142 0 obj << /Length 1463 /Filter /FlateDecode >> stream xXo6_aIbI}tC[8t-{XZt,@N;N0)5m]:gLi:Gesq'qPaSũs<&?u78 L'm.ܖ Xm@>tk*ݑ|*Q̑k79E@^%[c|aM"X<7C6NᒔMD1C\R@^W唣65M(I~yȳiH`! =MO^=!^ =Zy`yˢ`?P?]@"XynNρ+W.NgɥQP%tD}~{ BC~3K;m@C̲o77|J6i"YF'{>D8RjHO[E;XxP#D0Z<^Hn<-MUˡ 2z,qPKչR2ڬ;S4 CM^msKۊ㯭i`Em;{s} J = v0qV=~p2O)glG "WކU.}ZdP2urhg&GfTȔT}&6x'8]|TM\9]`?6I1W9f!/4n{3K9 *PZ`zaID>_JV0DyßNĘVWӁD25$IKS: 8$i{Un8 ^Rfj$)UFI=I+7=GRZ,/!)FNʡȎZ;KDiBgݔĀ4fc\bSԛPSHF_+#Xz ;E1xO?E>e'WlCҁmDa:qm^DA뻢s;[wakqTjOQijSG+).?N endstream endobj 1145 0 obj << /Length 1151 /Filter /FlateDecode >> stream xڵWMo6WE"H}q~A@mZjEAɿP$-iM'Xڝy8 2dy$ o v1+7W'r \zU^4IY3÷QC_V~b}%f8-BF_zryS8KY?Ӏ$^sf~H(FՊIc u8IyD4K:l(IIB5d>,X^bRȇ%{$G'`ɞġ *7fc]bRc`>/,wB5r&, SK.Tsӵ:?Deȿ0~w 9d@%CեjEi/vDBP'qlSf_᠞ RW5bhD~t-|A=܇6WЭ<R8t><_ @© 1dEO |Zm4 ".zw3 Jz{FQ.Yh+g  A< ?tKXvQ€|_o'1PZ 3+l`32|,ҭ׌zu+vߴTcSu6ٝ)Q&Kr6Nv 5Alyom@L(PrnTNv#OGx:{= ,ʷޔcکoҲ׋*x9%5g/1bX(PAlUqṵ/v8t5\f|Z]wky#;Ixm'k9ʓ[EZ'_wq~>M.pָܬ&:f,{ל[鵫Um嬮*[ R;^VK\Og+ũ0Ԁk|Y˒-K,e6 :Q =x^-vnIٍ4Oe5k{Au#| 'VȱPl;W2iSwSMXAȬp btk vy;;> stream xW]o0}ϯu4RmBć]cbdk*-{|q"D!"'}ZmO b|"?,9wF1\ZfwrlZY{>c̍{~pەiW [,S4a.)G<`'" 0UpEH9i04k<D(d&0o=s`QSP_Ю7./=V&=*VV*q>ʴur(^nl(EaH`lҼ߮1#2)r]JdedJQ8'ά?:ވ [i= kư"g2¢{[Xk$, nD+)Z@I i-Vf˫9BP9DUUU-%$9]qAo>TJ v %2 D[W]gӤ(*@J` ˛<2/LcGΏi'>3N:0P߁I}N ̩MUp)u/vBg@uUoR"iIڢ{LugSek'$$İ=[bzp!M> stream xW]6}_ןDC;MTm.3f}a`l6QV}cߏsI i C ?\aqv13_oF)NICmps5n1sUޗueVxxwUJPooSrA=ha.MM!HDHhűΊ:t,n~6OOai0BR! 2ıEFXԐpD$@DYe"9G9wD!LSIk׾L\ SP\nY8;>uI۾ԝ(ayDTAAte~{ &(mYҜ|lmC[x.vLGz~,·rUUvQXz:z(h0%GĚ_n}0qL'8 JN,h?#3lÙA0 BQ*Œ2WH0lZl"?TA@ƩlԾ$D $' syKfqݖsRA݀qbѷǼ`j`[ц%l?ٳTa(oJekmb3"aoYzT99Wɠ\8vp6 :"l ]Nr>Gkvb%57l,6TX79Oag8 9a%-  !؞b@ _s҉l@Ϊ(J<( R&mou)<|O7]9zw&`'bq[\xm`]_upɻ 2E\3َ(,yK<ٙh off?k9TBb$x[p%S,fzŴqȜaV^-WȠ/2|S]|_wb%Dw +W 0@L u?ģ79%5xNg7'^>'Ef=@UӲ5ƾ q.ޜf$;sR)s+ޔDwvC&so[yxncMlڴl kك})`ع_g>[TY]@X50! >Lc_YSE7* endstream endobj 1155 0 obj << /Length 986 /Filter /FlateDecode >> stream xWMo6W(+.?Ei^vECAD[GTEJd%8E 'DH$i$sr&gm RLO"\~+DD0*pAiM_ޕt2Mr.Iٺm WFiTR"E7# ^X}Vn&#BP!ʥ‚rwV0+;cB>wmcu{3dƇ=yԐ(%4CDP#JgBZCLGZ2|m(l^\)Q!Q|𕲯^Ny& K?۷<%O28J)tW>O͡&TPVD#1,T.(C +sV д)BSng;=pw[MΪA+~e[cվ2hOX}8xS/{й#> uٹH08t{W^3vnW22Y7n>uVnk4yXcW>K0@vՔ[b(G/DqTxs7vmBp1*ZWÈC"D\;dB)H0qJp]/9QN?R[U=eR F:sþ,NAwgTśE-1A5pU m}M>93'}FaL r]:| ͨofgXwD2MZro7Krr>*n+ƶ4S:Ƨ΀.+ Ss,xQK_'3D_+#Ù\7,L-[eV C;4NM[eUAWkE) I/ wx&}r0VٿΆkiߴzx}E]rM1f;1Ub@JG endstream endobj 1159 0 obj << /Length 1199 /Filter /FlateDecode >> stream xXK66X1|R )R Xځ-6Hek CD g|3\@7Y-p rrz-oa,@0ErW̃?WD!abQ7uR[Y/4kQb%0N.>/yl3L^nDx=\ȨT[Q ô! " Obma`ZK4˵Um]8hk8 }>AE7zM J.$~% l{xUesi?mЂb%c8Q"LS޾tr44VXHeҸm[<d^N~!!a)50qhvf:+_m κmt#Ƒrl&,wnu%\0){[@7iL&. M.c Rư' %_$RlLXav8A(~kwyK4Vc_h(DI~u?qj;"vI FD׽QRd^ɢReR-ް̣5es %uaqU)NrPt!*wux6@EwKS-P h̎cМOѲR- 6M$&kbRL}l >x9_xUTRPfE0gc]>717[h$i]F {C{}3azI~g!1^lkŕjk]8Nl ̫[]5>.θ#ݏ8I7Ec?p'qĘ]h H83 .ȴj;]IԛQ6JE;8㻫WV`ɭK'8Sn}UM+tK)gWz@S%J,ΪuvArҵ ,^SS؛tq5'jЊfS5Njmݲ endstream endobj 1163 0 obj << /Length 1206 /Filter /FlateDecode >> stream xXKoFWH:M[Z\Yt)R ;w$Eڀ`qggA _I$6X>7XE Yo޼41*뭭j]_»]ulXE|ҔWEN݆7}'Nm [EIge_?n~[iBMɕH " 0A1p t&i yp(#ZpZE4 _XHHwp_Ħh6g:"\2g0 YzW(>Rى:EIloՓ9yXV}/phw$9RݨGp*OK~V酸;XtpSXvԦ`]ɍQIi"Qg1ЗZVϘNwh ̋O3pǙ]70i S% xa/ypx15 ?N%S  FTvꍌ1%UE5ՉZ[ww*Ve6e07m5ס7loH:ouM/ؙJѠlt~"X̑4  JRD0О7?2a0IP\syyl jj'#"7sXڪE*2^0r|> stream xWM6rOQZt)fAX[[REJm*p5)͛>$4 C A~h90~!v^7oF)NI-EkxϚ^1ws$</JSrqtil\PgW2f_Mh@WMbD$`a _csP>x/c *a$;=hcw+kX`'E`b;wEQԕ4/"۵Cn}}׷`4䱳dZl<"(j" GL ^gmW\g" "ۣ v¸#HpڼKWFCfXoh>g jZTCwx6㝲 ]JBۢlHƕD2$۪βNu! bAG!N@Dg~٭27 {9LQR&Yi)v2CWp@ O'&"G+#L2i\ݬ?]*}E3Z5CL5^p EvN2!?O2f(I-orra];Ih.cq.7€}E@n1HھTAgE[^C"nNk_&F>.Ŏ@)e*FP"zU8Ә3.޿*Vu^F"Z1*i>Clv> stream xXKoFW>4h]zh{%b R*I9Ϳ,gXl6ЁX@ǂD$X[x "0F-/o %,7c:=|MMV-"!Dh,")Ux2<&ߗ ?dUxBcbNj~qQR,NMgN; WobMU=~9cW3l#QFLNF=gբ&`x@@Р48~>:7W \<6c9g}{gJwOOyX3rЍۓ6(d&{FfEy5/]dלF׬]3H 9),]"2v[rN ʘC|4/ TÜ.MYI0ի%CϋR\>&eR_YoU|0_'( ۑT앆\ۧ}_ 0G6 :۵!}Il endstream endobj 1173 0 obj << /Length 1601 /Filter /FlateDecode >> stream xYYoF~D{R)Z--QSHF}gz(5;\g 3If2(r$myf~V.ؑaq=3,lvU-VO&wE3)Qv7yʢCʺR߰XMQ-yLd"H_n~\ 93z!^ ܔ0E UpSD3áV2׻dc4I-se0?qdR?cΣ/Ų3a2Ή 7aҷ,\I D淄'! )XfKH3' )GIk%nx(ďX84fJ1x 99kk7hU+B %G TK=5BPpR;bTxo+jwd9S~B 2ɍ⟫ n aNݔvuo?Jc,I,ݜ5aiY:'}UY=Μ1Zk#s*v7 =B Fm7 MBOd=,ɇָC4(Ft^6F>o[{;WB}&IwO[3/ćq8u!U8fu(ժZus(;d%*MԢv*3LO`Y|srLvq:RueʫV2"ztl]rzc)™cѫڶ][Gb7!mX~! JuSR,I`؄|z|!吉=Ef3A"TtM%&g`-vhi$bP-9 NHۮ)Ϻwrme^> wB0qPH]wimObή4Tְ ۓvpD^k"jU8a0y1XԨd8SC̕v$Cj;UfR4"WO/sI±ZZc%ɒT7AqY Hayە˦VRƀ[ay*`X`>4OE=h\ϙ;'wR?x4ɶṴ@{W/4ej>N63 QU':Z *wkylp,½=3> stream xWMs6WprgBZ73;nMt$Cj @)Wɡx_))ͱ*ZH߮hK0YzVʈFjBymM's!$zkrmtO3[Әrm)f(WoVGI,0IEcpuLb"ug[ّ( ֚v"ȓJ)NDfm=4&cJ}%;ܧc\`Tp'ɛMW" Q'2ͦ*}xomվU>f9Om&x=q6@peOLJ3!4v Հ\s ı%P %`r >*N@|(|J&O# |T1/`:z1HP{Qk}q 9]{\|\vkKJ$S+/m[=.)1˅|l3QCWfބ件z+$8vv"O & ,s`!LޞU$Q}J?ϔb*Tw ͘_<˿%\3hL43L]JzXd F/ƿ%98Y6q{Dp1a\~ȭ,- c-h.,v ;lZܜis,PL)qquSoބ=uwYrBJ ~6>I0WF&B/_Wekn}lm򳡁Ǫ<|b? 3~nVs8Lӄt4gLs8SmbaZ:@5838C_1R88KFU^V]ۣ8>I Dֺ᥃gkN՟a*eX2ʲ0}":c#8"9~8Ùf[1-i;v w ng±] o6v[/>Y{vg6faLu)tL-5 endstream endobj 1180 0 obj << /Length 969 /Filter /FlateDecode >> stream xWn6+t#ͧMDJ4҄s)Ri,'YA`#{`!AJ4c(ciPnp}uF] (9 6wsM^<;#U3es.(aߖZky'lK4I&I~\PgG2h@DR ‚;ʯ-F]2ώq$h 4EdBU}vK,!$9(ShNW7#e\jYjLEy*3 KQ"EpQggϰٖDSnnݺ.S¸B5=F[[[moϐe9{{}jk/)mC?PyE}Ca<4xO<+ݽ\ .PnUO0”㙗Jㅼk5(MRnPHCt{!$sDÿ|R٠- 4Fukܒ vnk_wpTD1rW~稤c%!G4 }Нv|Jej9wG)z등 8֙菗*y_k?BOƁ!%yx/j>Z<l[ gX +mp0upko ^/iHUu&|n0WZS3sFm62zN*SY'S&޻Fy{|[*bR]G 7b:8j=X-cH+TѪN endstream endobj 1184 0 obj << /Length 944 /Filter /FlateDecode >> stream xWKo0WDpIxC[ m%®ݪ |ƱMd(hyg?R'Om֗9}s.Føgy8xZ(ibwXÓ2by?b!d:D-fKEjjU.U&yŻW]p$?ig}n"^ 7K%J ܚjk $[~%`@PgkeuٸlMUfJB,Næq_z[F, ͦ~؇!# $.1F?*$DmLQC1"~I\JFJ( #1a&z+PI݊$X/uAVoS9~W4tSc)Hcl!Hx|C`W <-~L$BMF4\5i^ ¥B{C=`?RMq>5¨ﶸjȎ0ˀȈ_t. ]Fwt 0l,,vSFɛ ΀k=-GTHil&ɦTk|o [RWї">b,ԯ{e4.8u~i|/"}̍j* ݪ~ШNy۔CgRay4$Í8۽P\*Mwi?gV7OU +gU9prUGV :EuX3f,oy-ƛ/;4pծ|w0HؾJ=j 9Ȱr@ؠ}ԌzWW?F FقH)͞A/Wv;·Y4驳lﻺ)W6)diomϔ `d,YqLXn6bJ+P#!Vs$8ɹ[Dž$)F).tu'=1X>6 endstream endobj 1187 0 obj << /Length 1101 /Filter /FlateDecode >> stream xWKo6WE"QzH`ͥۃjӉGr~ɢBwSt/Aa% I&6}d?n>'`:uu#Q SUMG|(j1Ie<,u+7jUUR"e귳rN9{#A\I#B}bjR"PΜW<~tž'E2጑Me ]B޾GBk4!JO}Fw!Dk3*7sBe\^٭ԮϘ0@3j{X ʽN献&!1("1˫r__Ϙ\yn:AAG8_ʧ^9+s/T0[2fZ#ѷj% '߆[Uu 6ƒW gπi ILmJ'FYũܷE(G2+2cBIn%[s0՞'./7/Ge!  \V]ApxJgcH9#ɑ֦d|=F,4Og8CI1"8ҒX9vս`kJb[8 ׀lDS49ʤ^4+(bMzm؇vwcT$]x:/יzug-@"Hgz0!QT@{ Xonf&iϹZ^in-W{)B0[!X̝5r,Hٱ׼)CS02j<Mb;-D 5t_ozX*CST}'un2РO( NNw^p"s`YWmna~\Cwn2GI٩d}(o]aK$Sn.AQq]Y@qpj045u~i{5=Wl #f:f~19^;wMkHie1vHgȲoL?u1eԝn]"Y<9g>Z 5ޮ˽k`ꊳQ[(}g8/$ endstream endobj 1190 0 obj << /Length 1046 /Filter /FlateDecode >> stream xW[o6~ϯ$˫HˌfȀEjekѵ;[d)kHȖT uvH/$bH1m7{Z—nȥN0Hyu+DD0XhBx3Uc$eur.D-6;, ֶ$g:tq͛Y ή\E#vzsUt4CX`۶;;Dd)IED#A2 ljkW4Pv)"@|5`A{68TF)H*$a,#s!"Hpũntn=ex|uɈ\!oEdAcyhi%g p;^%ӗ9tFSr_%;ٙjhgq:RD|H ?8oB YP)ɶ.@y gLasIrW\̞tv1SY6IѐT>͜R" _sR%CFI>k` A7"XM x+0sL*D.N FguNMu)1ܤO$sqk`[(s8x){g}'<IծB'P$dĜY06$Qxtu{TM= S{{ g' {o/)\VηqWzjㇸi)Fz겲uT=C;;;t-,.0K xUn7MNCg<]NN,Oq5 /!1]}hֱ!H+4aXIvAI1,) :1q _jg#er#۴9x`)NwYv#-xRc]{,"cV(~F=S¼|?@$4=ݘ<)J; .Y8} vkCWËzًoniz >H0" endstream endobj 1193 0 obj << /Length 954 /Filter /FlateDecode >> stream xVMo6W*d $HZ 8{Kz`$Z鮴䮴% vq{$iB&%*Wdjw튆 YՋwR&4lP:`lqQyfBH.-jh"НkʤS$/"_?nNK&G*RX.1"VyeXJSԁa#- yu<'x!jAlF9P>s;O+̱"0K $I41n8ar8Ns+B>U~FF.jX+/ H"okU^rQReq68'ϏmZWxW zǽ9~F)h`UHȴǦ..g zo.[?JٿΪ^[2[3B=Eyo'Pzm>BB<^ZL bsp㡩)3%&y^f2]bЀ/)+P=JSPwq\=>@=2@${n [ z8 +P;BĜɠJ?Tٴ)E K.$K)˿zx+OR`.vH=5mbbMT]%a7s-f_G)[swr4}7c4+Zs\?_Dr"$;^SkPKqצf@ٴZ7bϹk-0$.0 0UTYSK"vgta%ܩWui:oO t=HtU);(> stream xXY6~_GXQ"uC&m#HAYrud3Rln $r8fHM|ś,OXd.ң^>F.Б|"*fwtUSyU $ P"Xw-Έ:^ ,J ۿv?}7dR$ϴJߘ) s,Z hõ;qr& _&.=XfVyېhx蹧IڈAn |ڢlji50A-jY0ߵXuD7|q3-$3rn)]_Qb6THP$xVcفRaTpf&*曐,->G_~k,KMqӦ=B#\ajF3QƂܘOFNePfY!el<q@7F YeUuFiVl iW/ aV0.hpDNx?;Rdhm/%L&򌥉djzS>m!e3)rhN\NL=Q;vF'HTuǖ/AV9+&+>Cd3MvߘE7#L#Ph"Y$b9f%yFڔȕGp]][HZP jD{t%ey0/8#K֠Ȃ n-0O_S)V$nW,[^%Ђqj k˳^9*ي)tSU^!M5>tg9]𥭐d{lTk뷎]JSVdNQ(o<{=9_MT](I7*N"@u#N Ik\EGkaQDO$E6E@мt(x U(^MOtphټt? Tn 3nsC v ^\OTئԻp]ZW)E CHր]ܦFkg1L_9&4=Ln_)I#4\<,d/#\Խ$ru!IN(\Het2΅Bo&x,j\HH(r#}Cc_HrʔAOukn1Ԟ4!hKqZ[KP, v0&o4 T[a[̂q&E,Zhȱ[S[f3_ka/T3'MQf4qG`FM2'Ǔ\(͙4חPa8Prwt:gZ&Xi.ڏ'Svi`"O&`0PSo;a LD.6BN_/d3%*@Ӵĉͳ=6囪 endstream endobj 1200 0 obj << /Length 1740 /Filter /FlateDecode >> stream xXKs6Whzf"xc6@QĖ"Y>wA,@'u|0 -&?&N8Ix/7ڞ67v $_ݼrCC)}Uwos8AjBDCE]_D^U\mw,4nsL)3-榾$^XDB)6wmz|6WE5K_T\N;UvQ)~eXjVmY<5 5Ѝ(YYo4O{W@QpP݌PTyoZxQʭ2páN&SY۬}&< y7;*I FӼ)Eg%qDîQzga#)0XŃi/j֎u;t9^4.„b2wwEխyAXxhaczYֺ:D#$f*Ҧi=X<nw41, PNBP;jwoU*hpDRJ> {47hBZsj~6Izu(]Lb:J0v)%CNDU׷C[``?g9R.$ܡ95lV@AaGbQlv֗U_5)F^MZ%סo~ϘD/lU?Տ[`dAa%|%MKP0-jdʚ-x+Ge5]jT!I"6f^Xo̊1P /Gd ($!ÎQ%C5k(!9| JllW;J-,Y H:Fě xԽAN]+ԡgPcVETproZiHP?k B{r]pPFD$>9I>K{Wg^1LC ̦u 2t9KYs 1͸::=Zss|̣7Xu33.2U꼷_.Xz}udt.-_SNL-_,'@q~rn1@YY^]:Wʣ髉L34NꑙLƄ'g+pK]WSmzQI~jk`uEx,hf>,{=FM/Tj eV."CDO$hQZ|5끪N%'t )pYw7=Zj_}w@LcjM}+ex sFˌ{SŸ3*Y@L&?4pvB;Qhk48kf]f(c|`y1#)w#ńwm݌sjBu"!UMZ>U{9 ,I>DPOgUaH+{xvq,6JX *sV13g ?S=OT;u\hgWPsV#56#c'(&>}P#LVF GBMLU_U568WyOCi2i!Yۺa^Gcf}pc [ H]73(ݫ uGY꫁%6"ؘn ìgsVE)HTz&]DAlJ^CP yPrJz{(i$lo^b~z BI__y?W}Re}K/=d endstream endobj 1203 0 obj << /Length 1391 /Filter /FlateDecode >> stream xWK6QV(!nMSl}Ks-:VjKIw!Z zij7ߌ&l#SNR.7]d޶6v!3ˇoxC#EOsWb!؝W6٫m(D٦"c_֕^:VUG ,|q~<NR5A gE|D ZFoߢyD`xSiNqO근9y-pߵW#@lP2FJO18>qBD*'n{f,>g!m ljLjg=#L햽Kp}5A/\9͍L %y{sђmoY'Xhxl:(i͈.s{9#A!YjG41`^),^m;2UgG2hP\p9 ׍+q1lqX] 6Yg8LgJ ([@i,ςNIѻ |}YWPBWYJ8 1:.kO^ C[{]Zj X Q>v8cՖfQWtNpobldQGdЕǃv06v,}Zֻ꠷N_o>VwVE[r=,=~˯eC"$fҴ[E j`"IٮIl-}2¦Ol(;'m!YQlrsQE{綕j4T2nt0Uۙ5Fg + Or_$ endstream endobj 1206 0 obj << /Length 959 /Filter /FlateDecode >> stream xX]o6}ϯ 8~T,heA淶*l)v#M%efN5@!BG{s%T@ .<\ׅ[t<6:B c-*1bU-6A !e)eJr/u7Zު{5~sش%/ 3(yҀ>+pF+ :?{=fsm9XԈxpWլ)?xhj5^@FNoJ`QKRg1 ^?QUV\IōJ:v6ޏ^s;J מF n&- mF 4x!#9Js鼨e(exR%x3i2 n j1h|kvLfڎ%W]'qع@p Foʞo0>q9.J@KXjL1)'3 5H3\$[fS|:3qYI-ŬfgDf7v$M0{ *W>9?0@jK=(8`'A7IFD'-L̢6 } brߴgII`dnJD4|(ʏK9dof ;p ‹?r endstream endobj 1210 0 obj << /Length 1029 /Filter /FlateDecode >> stream xWK6-2|dlF/IZڒAIIg(7.C=fI0I"i"CdS)^ `6^^t+DB0XdC-Cz)17s.OzUM5,2*qS).z<T مL \& -tinU]*9 B?/m>b3 9TY$&$CIF"xS>ngc)0r@ }zlD9?x8D1x*U7G. H}w!c"' +?M<`#W+\"g x䈩} mzš7*kX(A19`w *ӯgsdR;("(HHmo 88+ t^!w*jNWt=Dr-7DI Pk&I題@HsJQNB{}9ך F59Eik:ۧS]_lIMm.Ι5[S\F F&8RDuI6]P:?9lLV%M 1<.8548}2¤VŜʄ 77i n| gygM $-۹RkuvNq%Jav,#"-Wp}=:oS]kO$> e /? TCihᦩNq8ZiօIq-N 7 1C FeFa˾rHarf<# kʇv! ;1Cn(BڿqCG[mXOeJ5zw&) BT6, *#/+3$,!Ө(0 <5Xh?G[/e g( B2O3[kҬ~o~p_d~X endstream endobj 1213 0 obj << /Length 853 /Filter /FlateDecode >> stream xWMo@WXP[~DJ ppmʱ#3YGv٪B9޼ya K O v'tXm7 ^:a0 _,O)0J Zdy5 \'u\BxR,2UmjLݕk]rY Ejti\qEd:k5abrMHER5_ a .rK u1\H]:\|)hj1Ż=iSזݶ޼m| PeNr&S10F5lnOusAiۜO,O (}9EݾVT%`.@e+LPV ̑Ūue֨Ұ[7nESj/}B>='$Q$ XOWٮmÙD^ɦ˺J= 33R(H,)<ⴙ4F,b<ŒDZ;w@X0hfU1nV[ˋgv\1 }5b&"gf>ڡ+:5tܳe,1Й7^ʵGn? Q~½oE'VڠT8[}J235 b4P]euh䗊XYc$:4%{#B̓g~QVRB:cjw)s*0>;Ȝ*'$6z")s/eջ(9u,Q0"uQ髲pUvl$Etyl/x—Z`oM|7 endstream endobj 1217 0 obj << /Length 1037 /Filter /FlateDecode >> stream xXo6~_G 8&5`]0H}PQaK,HْLG5ִPtxwHaHHi4SQf RL/.~""e8#b9Tǯ4I_s_%ǻh˺_x|c1Ua*,Xϋ7qA}%^a^ WKDa]k>.G)QH2/٘D8_{/8F\œN6u.h[1syڭsDŽجkp_c"$ٙ ԙ`[n̶7!h#~FgNEFLڙ ̣M@콓j()U{Wtnۻl31 ^T`t#mB"u/1Y,Ueڲ*8hiW)Y/H)0Eg)#Nƺw̽ m 3 }3wQt&RS=~H譩O^)k";ޟD{]7'if7l8$4$bl ?a4g\DZm|:ϮHhfW3[5Y|hhFI^&0gl7/MRdc`_7^ZV.>DPBd`x./SeϖaA*װ\fnd ,L NRw&oa?Bz䄗Mq#ގ+cL@DʧWcA?ɢ 35Hi0Dğv31B3mnB dd~AE,M:5+`[YgRBOa]1ןD .F_>LI(lbvxDvmp6As޻Ϩ{Z Ο_ 8qqkq|n" 4,I^xD>%S]"RV;(#uyl'u ۅf ?}UY)8=:/L endstream endobj 1222 0 obj << /Length 875 /Filter /FlateDecode >> stream xV]o0}ϯ- C=]}HIu8 ȘVƦ6iҔ0{=vG9ɴ~D7a_C7Icyd)oՍեb"Q⻸ЖhU֜C4uVTEueCVڇ<+K:TTuk$BƐ±#fa&,׍Eɔ5!uaS)O1P'SE NMǚ3^pVWeܑbj#JE8Tźm%Uyԛ>dgU3e㣕e}+;Mˈ:/Sv~(pbh/Kᓭ9+%{*¿/ endstream endobj 1225 0 obj << /Length 1194 /Filter /FlateDecode >> stream xXMo6W(O,CmE/I]wWZh%;Vj?lAj_di48|qd`%T )& 7wˇ]zE|\ q/ͭHcM٢j›eLŌPŜ6RNfQ֮-ƁLˬ^ =m : +XIh$הJ,HFU!l2BMX:AN#U/_+TXlkkv\ҕ'*.Ior?yas="WٮzR66ǻIJ8Ss9+D1mf* P3fŀVЙY#_9nj@mڄ}]NyAUڋ&>Յh;% t U38lfPO *A0ʟ0oNmLqwŷ;{iiϴsla8r>MYml: "LvmZm̮Lek Ն~,΂x;)S+c D㏜c@[EY BR$csJk'_h/om/ ǗkIcS09F<9yw:h$Xh,yADLSlBp3D{4.ڭQ(-_"U>FJB'Su~^::9WIǞ Q=4;ځrAsߵD-S_YZ%%5H%N/bФ?:u}WTa֧)~h$U/T{>L/g,z}Ó!!֜ޯ[4_TuU@p4h95ku hYG~G?bc ٳ[d? bu/"~/ endstream endobj 1229 0 obj << /Length 1022 /Filter /FlateDecode >> stream xWMo6Wb!ciS"mkmeIm;)G A8|3|of8/ RO oxz !JpNrlSm6GÈswa=Yzoʦ+1zRUWaR(#oݞ &Wf,׆%LDB~ߛ7˧#ADSpoYo5fx0;rY,LQy[Uwv'iDi'St>ݰg x4y,ˆ &^9*  dի~IJ=K e:&@LR"7Uf HC,NⓀR ,9#+'PHjl}Z3>]=T@ c}%-b3oLfF"As1U.Dg,(jo<,y/sS.VZM(A4j"OU{rC1y^O0%6qlaj;Ǝ!h$L]Y }3gƾw]TԴcwnΨoeZvuM2vRTtK{qJQگC{Ep/CsyƮbQ &؜:ڷKH3fUڼ޺HWn 8 Ll~Նmm1G{7M1@+i|R%d`D,w0kD/kh>& 74@p[40k -n9G/0$@bҀBei@%+W{½>SVr \aiy6~%n,29ezc.afa9>#ۗHxlMQ؎7 HyQGfn[ImQ GD J|L'azK`<{ۍ]0$_tk}*nJ> stream xX]o8}﯈K"5wF 兪;oC:vfQ߯ۃ<̀( PU5^sMQR/ppA@,x'rv6˧3d!Q ]-Vj]e9!$R>Mr7NuY,Ǽ(e*Pv0FəLgtNB5tE kQKj(+ypUf'GխuӾ)X 4\C"^5}Mnmv=[s,669`)XO]C0/5M̓2a`xު~I9c%PqvVBmw}Lxq4]+,]  ]Go$i~978ӌh 7hZR_RM.&civw27uPY(w1Hգg|CE-yp&ǫ(9 TLu.alYiXWϝ1]'o F4Oaf,O$O>'|~5W}sڹ%|05>JzW*e3WmqFaBT lABuӅS}%*J("GӇW`!q.#|zX&{u&c#2 %S=AqtM*F}k'gqc>!`dcL!_ܹN+ YsYn뷻5Kl$MЉ ]MXuyϤzP`ۍoϡ/?C=$ڬzW Ko2na޶֫z01g!&9VTD}ɇI۶Ǵi4]^9ѓO"`7`% endstream endobj 1236 0 obj << /Length 1053 /Filter /FlateDecode >> stream xWMoFW%nKqESK-,I,$DJdyfFiX23ኸ).ddvuݍ%8'9V1Ԫ@ۢ鴉9ĉę@}vuet7j)(c_~ZK&L (ZYLb"|[5}\>ND U8~tRc 2w[mu֡(^wh0 H g2xw}Bj3K/鵝]o54e+vծzdG6v`'TbE0F=BCFq93gi:0"rԮ9!CdyG-@>8e bWRb뉿+ l'L@:ȽW(TվiZWL%0I=dt(nL}t79(ŹKG8uC`t6ݾ'xT=8(Gf,s@< 9%aN%pJolKEWILEͥJgFuꥮI/mR 'm}mLQmݛb77Z[{;vyeahҲgŰt^SiB@oûLJ;{fw'-kJ=T5xRTs8/iJҡk[| | s7),n&T7sHQ7n鞫_{&ãuq (i.^J'\_ו_$b p2L$P9Pp_:' S #n`{qFYAnIeCh_Lֈ;Nj 9z>]s).l+H{9h@H6wXoN%UTQ;ѳ!u.Gd5=\oe w)Aә\ڙ.,0p[#oby8,s$AHa> stream xXKk@WzS ІBjrIsP`FwV+^W8gJ  根 &\}.Føcq>$kZ> @JޚT)+&zv 0tlkSdզ06<7-ǃ՘֦#Rb+ҍ i YR H/!2t1R77UNm$\aIIS)M0@L*ArMu$s/7]\RyfN?nc*!U_^=6RtW{whdj`z|>loTֺkV]N51۠(P7cr٢\ $h hJfkB#G~-|CI'><>L&fa]B4G**)AQ֯ϰ:Ě:Ϫ?ΪoTUi[*% C$yS{2>F;y1^uJm# Km|YdŵY&`'I661kstq/!Oִ6VKl57< (&N;Z})X) kRW0f>b—Jg-p}9u{$5ͪ?~3% endstream endobj 1132 0 obj << /Type /ObjStm /N 100 /First 958 /Length 1203 /Filter /FlateDecode >> stream xՙn7zyr83CV pshkBQ ҷ?k'-ĵlΒn%Q"6rf\CJ3NƉjPHԼU&-u JG }8Sk:j)h¿“ҘBjP_p[apQЯɤЯ#vCa;𐂥+:5U  @{n{Z* TZc9.rڔZ`tD&*#֖&EPy.'c0M<]5(p( ̙cй@'UI!:iCkk|T-@XaDOca- T 3Z 4}ڤlz?kZzn}uw̰buri}{+]e(7yian %߼zK~o*q]}÷sLhu.>RM+Ç{X>\j]v5>aջO=;>mDdH))"E"feYamXO;tiv#nJ`t74q>b#xm֎kug^/OYXH'Տ=3YH(2n9]H(QC@캃|Ns#mώIa"_k+#uq"2>F~%H5m5~2kw#qM"7gq:G篸oDX9CɴCDƉWۂ,DwJ9<qm ~mټ .x_9|;TOpNCǟ=e> stream xWKFf6Rqb2=QkwqF!R2+Xe#A"QPTPՇU^<|] #2+q,]ѧݮ:R%)4.$)c<~H m=V?aH%Z&)Y^KZrj GNp a29|eY8ٕ(YVu-gU1Km:Iq$86rznFu{˶ I] 䅍}Q]GsLvl*et$rUH`PaP!l!J N.P:7^.!ERcNK$܏9üچv^~}(*F|A0*i|ͺf5j*׽{kV ԟIActnE\狾rE1-@1C, }qiK[}6KDw>g< 9:te%ē x¡@Eckbk*kkojd֗?2,)#{K.xxEC\i2VFG#}8dНoإ^bffw$OGgQ̝}Ⱥw0ڵf˪H"@;`QX{m`I{Jݨjٻm&̞]0;-(pH|8̰O4C_cg>GjM9Urb:QA䰃LqCz^cp̮ ='HBǰk-ȥ^0L8oyKqz =(VyoLrs#@)ͫCjsnQ2w]kW:]sp#Iw7m endstream endobj 1248 0 obj << /Length 1017 /Filter /FlateDecode >> stream xWMo0WDH3v8 \ʊ pHwvK6 8v$xۭT&7oߌ4"G#"9\E6WpIًwRFd4Z_N+Z]uk8ᜣe!ѻX ԕvW@4ܘ8a2xv=&Lb)LjQ tuLb"`Cqٴ8%Tt'Rނ¶3Sz1R#SI-.g`Cո߈$[swgD~ i"q9t5e.Ey'x'ޣ Ya83~ڇG fXwŦ1yk^&R0w LE`9зZŒ;5Yԭ 67ř*49..UӸ3dBjx  K9v7D  =};]}mc gAQ]܄Q w4sD`Rz9Xh;# xu#;s1,ɜ\5J=ݕ.nk܇Ošz!/gTJ0a΍TS8I>>^o6k"NV,{x\Ie|B|ZN'V `cɽ:$ԍ+ղ4܍HUWST]{{`؛ޓ 8a5:0 2U endstream endobj 1252 0 obj << /Length 954 /Filter /FlateDecode >> stream xWn8+DI3hbHn.~d葢?|m9qP"txK?I$")wWнm׉_ܾB`>AㆱAP%b|Jڨ},',7Pnu],"BL".5|t>;[ fs^>"q\xe3g/\][FoϽ.~{_^u?͹'L↿O gZ_\֨ӣs2sJr}ԣZ5C[.dl5BS?e endstream endobj 1256 0 obj << /Length 1083 /Filter /FlateDecode >> stream xWn8+*.IX`/5mXH}ZL- 6CqdK.M.8y3it>2d x~NNʃߔGi>߅RrrhG  9V@3pC5Z-k?}:I5 6kࠜ&(@CpBAbSCVCw*o8__j2˲c"~VTTQ&<#1>}IbF<\T*̘TTAewlG8ލf endstream endobj 1259 0 obj << /Length 1035 /Filter /FlateDecode >> stream xXn8+S t3dM#ӱ [2HпR$eQS%_{(E9rN'yTẋۿKa:cuAPEj>6I !q&I)euiK% [-Zk ̝73 }PƖ{'ZyBN /PX߯6xHƨy'_xotfύ7@}8h9_UM4Obw;ׯ};2> stream xڽVK8 ϯƪޒNnmQx%1ة"`R;N&AE~$?&͔fH3-w78M_!Ir&~q빪*{glQ2(9B|薮;fm閦(²uUX| *?"_4#1.Jp+DdQ IEQSq5!>xdQCpV]UG=DM] M׏@"U88[ #. 6{>QI"9q>"*#UBKqRR$!5nsyP`ro ѷrI~ß\%5# ,JB{u/]3(T^G(Bn0PjDf SNdT#i6XhuGR5qafeMmhkۘC 'œ$IBdaR* b-vWu/9~wbXTB#b:?sGPǷ.xux Ҳnt3 9+Y~I*H4y`nk ;j?XD5-J#u4), x))"hȩ?'zVT|jOՕ:|S1Lm(Z76vOSby*L7g7.%XHPʬuIiM,@`IzHKc`ay}9E@JO@3ǧbL~,Bhj %D~4@jdUSle~CZT.}q?OrބD*^M溷q1+ItY`b:>1] GenVgMk=ac9ۻSrx,]G,o`눳 ɔs2dJy0S z3kwYzn1ݟ}n\9=]nƎ8֥f4q&fKξmϡaeRX_ɐ:sRI`1=]ҼܞD+4~ z endstream endobj 1268 0 obj << /Length 3382 /Filter /FlateDecode >> stream xڍێ=_h-IQ)i AʹAAcӶ)k"4*+7VÆ -^`K/>|ZzڦEf_I߾Hf~ݕ25:x7aT ryzt]<%/߻ ͉'?ovڭFxߒ:+y)OUalgY=&?ΝJyV"͔aH/OJC{8`M Լo˨6F%K)C",p.‰ K'S&= 3CMoY :[ *Ն$^EϿDX튘k4]a?~8|E͚*-tB:w#Ri)*r WY lҎKPznxmwP&W5|޵4o$8 =_8JT%:gN 'lu{"XKmwvZ9:nlaH]_:+לhNFZ:-T~J,<+# `ᧅJЯye+xr?~HR#7 Ldu"7|OuǔtOgf΀ +<6erljń^24۩2!;7y"~\y/[,!wh-!EKGJ\%1!#-|2 cfHpWe Yբ8wQŁ80!_ rHGEi64YTE.#P&,bK$B߃qIVzM ahϑ_Պܴ襦#,x0i{ !*ֿDJTC0N#Y_)> $F+W719A&bigAڷv4Œp#䴩K'.DS 3M-r"Mh_2'ϦC/5# 9egAy#c3L~oW<̆ߘ ib^e~NN5_u(c*@iNY@h&İXJP7LKK!N.P a23߈tDɧ*̨Z;ɰLod0[ӱxMD#ŧ*"G_!)dxsUGOi \$Y' W _3O?@ Ȫ0ֵ~u>@NKؖE$;pSOVM1RdY̏W:{}p:^N0 %sP tZ#Ҵr8n'>D>vfM5=UpΓN<exJ/"*fq̬b; H&9<d:0+ oU *D/5lTE;,u-8󓁥$DRԵ\=6>RnHXٺajX; G֞I*#a\.[PPZɣnS\ZX37 LSٵ/dbꅂBRtQڶ_t7M!o19jr"z`Ftء#B_y^Ύ3̼𢘯\~tR֧Ð4wÅ09#8T1H.3H$K3:>J|t(TgnA/8o> fU2xyJ_,$oC}x\ A=آƧPxł`vdU59]q"cp ̿,#r5v5̖$?=N1w2䖄8 P32c^pO2.|O;u(`C5K % 2ДhL'3/x@t8vD&% a9gE;p0lW:c?g)Zarh?qrGMܘ"i ,4F0N3ދ?^KMJbWy9 SUiV'y* vDE{/`F% %bJT)OPL \/'e3$`+Egk)dB;/PR:qQr#אJÔj/hQs&&9$|bV3=n KrȳoQ3IU%*̹87lƐJg{ &&Y J%T$ʥn Ynd\FÍ:Nf-ZsÓ8 ԡIH72¢_z@[CgVC)E7t<#uz3}#ƫYs0Wΰ&KD~}Bdt pi*(${T"[熲?63J {mi/#o_0;l!%\yiZT1ρnž ~r^-WQ:j]z\axd_ɝ n?lTS:Ku)i8c~oy݈ib#YnN*;S9|p8c'.dE mh"nUzISUqt@Bܡ\DN.Jj8Igq\yGEx}JXZeʴڧ}3?jz]iU G J~{W 38WpA8y ,sX, :=zE༫Ɲ>7;tjyĵB oEOpgBk~fzPFuNc%#jD fTQhUBa/U=6ӧ#P&_06ᩒB.\?tLG94>'yfyϖGzA\/, $(s=(> ֩6/('y܅go,X+"cףs_. ryP]-eZ+O7w͓n49Sh2x|U7bw{`"NX}Sٴ2B*3 66DTW^藡uS3PA8_{qNs:>χq3:d:/8]`o 0P%*9vnRA.|[]',6~B*n endstream endobj 1271 0 obj << /Length 3534 /Filter /FlateDecode >> stream xڍZYo~_1K(@bdf}d{mx8-NrCZ׻IƀNﺿ%OtWVY\e9K|/߿S<&ޯf߿J:ao|Ov{>˲?OLK?Ϗkkl7Z@e~CPqx{*)gH\ gPG?}C?}ǟ>}+]2!kUM(kt&wcw*뢆E\ ~U~8qÇb`v۴v~vlt~"⻖zq2$*+,9Pz~x nUv챥5H NdrMOS[/#}MG3fsʝkd 4u{^4 _;ǹ#Ҳ؁,aF{rMfɌ_Xh +:"[y醾TI>yЇgPyly%1k -itIk]Dߚ7@gP)쁖ÓfmP+4)wrʂykPor6^oO: W%I^0'gou>;,no|׎vo.zmd$18:"u'U}az5$b=܈&qa|ma=9:Ii퉷UviDf@v {J$Qü*D8J/V^ݬcE+g_fhe WYiZF\♏f7΂XIOl/6= )r )?ȉB!Z<_/X»,1Z]gql.z4vy2Ŵή7gW q59kT F D=:X D3F}r+nR'qW/jmj_ `81ֱgAfkOW;41fYlo)+ZJ_zR0Ƃ;JJZ94OjR'g'Pן/ʗ |N:wQakyQdN8=δ['yz/f:ژKo0V^U['RZqo9jr;'{%*NhTapn:Z-q+mELԕ Y'|C?Kh¯`ɒwBY;av?&Ж`v dI A!.8ZB`c9Q\Tя`mdNpm@Ǎ\V!9Gr9 t\E$2ىlQN@"UYnc|g!@vđ |@ i>0~WՖ#}`yJShCHP !Ew}i4?) axLX1FĠaNOWUG0]n:⌍iPWi٨{~ Ƙu<3}vk 9w:~> i+\i*~-J;`;dAJ7 MyPB^qm!lStC݇[ I ʖ,p9yB =pzv׹a+E,cHOdyfI.6Y*#>@vLΪeY~6e*Y2\)%'}O=An){Z< zIpz!`d8{JGWsL:N7S~iGʢh>AN7npl4f79jBʉ^acfn w)<ѩ*bp5l읤V L[eݙ)|MIS $6v2sq%un; mK.>-8+ʵCud75?1 獇7eKM pHhgwZ6KU+UHӼS˱o](qAX*@|]T:NTסt*Sq G͋跞kWKx{>^ˢ,68`|U}J+ש/4Qhh |UJJIWI>2))&w^SY!`&<Ҕ+%"bC*n| rd:Jaig,zUqs)dBYF2r!1h# ƴ9)1laR`^c^PW\wsN^Yo /c]JB!oBblA>,ÐyRCWPlO:q2sEOխzRTJJζwOV,T LިXˋ<)cLbI}(E޺324]ksis( k>ru?U1HpUXJ}SŶ NR7C].]GQEe d:(ssO3>6zH4=t$ٖ*hF>(LyKjlnwlt딽Dg-'-e:z肋r:@Tm{'hw7e[Zܬ2o }}_sCDcLZXt5@6%:*?0p#o5 kѵ0{@+0q]X6 s?vTh endstream endobj 1275 0 obj << /Length 3442 /Filter /FlateDecode >> stream xڍZ[~_a%2K6A$]$A %Gw3FX`-R$s\8j?+]{zQ~d |F~_YSYZg=>K=vJޝ]%n8tk7Z~k0;X@ezǿcؐ6&?wG੒)u4fxJ'ir37x 0^V {#w o/ {]'1,x4Q^HgYStmZ%(v ]w\n#872K3.('9A q .cqSC5(XٴP#k]I>dI3xf"݄C"sc&l| Um)V&-*E>XM|_p*C?< <3Y@#[w3< a_r@0YHh'*--cmR6a瑏UxЫ)pގ>!Mpdnx"rO1Ju*+ L 汗e?K L>N-vLm#ToA"1!1<8ed3srdpO5k2qx@&#i挐+upl4\T21D6*J3Q(XR[:*KXonTY,FE7uXxdcG$xjx#EX1;Q]DJ;gUֹp HC#j*(:d$L$x3‘$ 2%e"Jf 00Ǧ~=EgfӲ 4څc UA(ےw3@' ϥQhRS~P엀ªUǏ8y8ޜuZ>rAX"aqYB׉.'IItg9X6<84l,K-o|u^N-Y¤Q"eĚU]_soY@~Z Q8D&d0`>ah):ACe\ح!<8{n&p&Yd)d ?S1wLBsOM*dpyIKM='{ &i Ew#ȋ; [Ҩ.> Kw%˞DPہQa\ˌ::w\CH3$m:5e-橧R7/=:ݾC Wu߂dr??iku%D'Bp"ݕ,+\ 7ꌓѿ b 骺.J#b# }H:Pj7On^.@߆]T,$/#`/=\f:KK%ӑҡ񂍼w1 5>/oӃBIZ*<4zKXF=J^OdAN;E?~ nlRYFѷC F)`E>pAwv_w%K 'q7,t¤F _\UrDפ]aPj /Jqb-X)s7݉_EN"dT/U.XїFYAl`mԛ,_) 69*)IȠ\3HE׀`~6s*2#${7Te¶< :IPsm#s:MWՙ {L4啗ʱc!#]mGe 'su_ V r,B@3*C,K2 OUf5|1:D_ǩ4 (U>V03+Εp=d%]N0fE"{>Ƨl`%ܵ2S~[flpƊ ċGnakъgQ1/ʴXWYjK!<]uq7S_pxwVlZ% sfn`L+RSz5,\pxK6(Sr/}K%9|+1XkM{8..R&9a** *T D=dTQO2VWG~R[2> dd'4n F<$~܁^VkX+IV8&W+o*BjͺaWmT)G]vC9mS6KrLYԃLdz|grk҃R`f G]QHri܊EUI=<ަ< `u۳s!^]!*BvlC!|jf#6KnxD!>ބ%3\XR+tZ 4Su| (.޲p-Lw.oPd[$ #_b=BMH[*`JRskEBjh )TH>emZ8;שltIo*r%TV B~2!J-*bjiq>R "7-;)0q) RѢHzqo`դsoE6zJo@'K,5y)+q-[˚tĚ4T{8q^õ|b+D]*n,hW5R*lxۥI"s cVpvV&Uyu&1d X~E%gɳ]lRqP݅ٵ3I^lRR =Kq1Y'Z8`z-?/I\X'i3F>kӼu,tɗ18c` }$^RonR:B؆ endstream endobj 1279 0 obj << /Length 3571 /Filter /FlateDecode >> stream xZ_OaZ`W)Jҧk) mZY%W/߾3Rh;(r8~3eO*OӇ5~yO0i5mQTYvχ5IWI7/Oy'w? |׍ e[jз: j%usP0ܽ,@O*R`HiV r]H;h;OeL_ӁqA4-f@~q87xy?tmɾNHwt8<ˮłI83LM[d}ugLl/q߅pёhġQ={!_h(ުy_8iٞ˩f-- e ZAϩZ1K||?^YZUfWUZ*7qb: Q]-_w~>"8\e_mU%]/8% , CH]Gw#;RNJa# ATA*f.wW42?H&[l%&˕]‘!:hܨشD"|pUm[.I4 8J /*F=7Ve M8XI ]Pq0l(:-\Ĝf iEE[UTEd!HVjqwTjJd Ju.Dnf][;ʜĀ gކNEs>!]tL(s~P,JѲ58j|x^0G%'ۜj@Y)CRY.;kH:Ldlbi;iP7NqpQ_qNm3 9N#SmG" >̦ۖ#07^':u-uC tąRRT 57f_=>y)‹\c7(]TeXr m .U}QiL# 0sA.?#w?1yhZ8x WIdW$scH Tb3S߿OEx2-Io.TZJjt9C*yh5lz]De&/k(PxObM3gQ蛅Y'ޢ+9dop*0Iw,Vq8.}ɫknJ9xg7q#HLi.WT&Jkq#\A'oEUU>J0} W!lm^7GZ0? | ;%rgR:UrM$ =xML r49t4 z <(%۬wCrjMfDڧ7ߗܸeJ|YeySϷ : R&:rP GXS>v.\mSWlٌByV/ҳԡnwWe_;[uPB.n؜zIc (N|ΗYzZmJս~" 0`{O2pd4lw?Pr[&} #uxԏ5_; m4 endstream endobj 1283 0 obj << /Length 3534 /Filter /FlateDecode >> stream xڍZIϯ|b ;8 c8mAC5EHg:>o-VI'Rc] fW&JUZZ?;#`7w:w&qmvG)v8t4ɿ3>d7NחkiL]Q='>:`q"St_H>γia^LtF8\fyĦ<:r\{عq>^Z_hR/0?l?pG7b+uxG|mOYYE_?TM"+G5ko'Tĭ@JRH.4E l6x/olދhEہ j'_L tU:I ZhQ& ,#/-;.tKװq-y$ޗȾ,ɜDMo=Mbij_t˩y:s#wڙ\,N)Qf7n GO(3r gU ]b:Kgr&lbYSBS 96-Lf !lLWtkP4'[й:z/rQerBĩj)h lgl5 ea^_ZlGi3;Jma Y4 HE Q*hCGA4v΅X"x25^dGEbi!mQ*)+& }Ue"7 Fv]:I};XD_p3&# r>Fv3ut& ̯l7pAIIN޴ujծ0pG뒦ذFWLˎ9&5Ln[o˨J4dPm֥Vapfe Z^ Mt^N44N7`e`3g h1Bw3Y9ܡ;470ZQG0a4 =#u\fFYZ)}rpHgps%\48YѴFFg^%N2n1ݬmep:8c泣ǫ%BC6 YѿfэX2{Hf8r0`dckh" C,S;W(>uIBطL2%C0OV#I+g{h^戝y|{HW~!WB$فTX*K~c(ACr7t)pQ֖ȉZpEt"#,qV6r$ηWTz quH`}*uM +MN3%@ jPְd@YUtw e Tv{=S)al rgu H+AQyG,IZpTV!]:2Y he7VO灬IOzᾝ86N5| 0`a<|` Zk6Wl,<3ϸ܂Ci.Ϩ_JU^)xA gN, :]Es L@̎Zduj:dXd0J\sA ?J_r hJ.J )2҅ǰ,(p֓`գtÓjuN(תꢙB]=u_%J$tE?:P6s*WdC+Ԏ;J=/1IT&\S}i-% .oe}!fkSdR5W Pi?5eE\`T0<ǩBPX|5B4pR5JOס&ȋqx<;*C}, {Ly (TD0#G DLGd(ѭvJli9Pg{z&;p;dQ~&{OeTnT}ZoH-pbrE@#s(@k\پK5ZaHcqr/inaU(RҲ,hRyYK\,I/Z+rꮻA'bPE\_ƏWTw0ªs4gW?ӜKc~c{Wdljz?k#f].J00={Ȭ_bS^k::YiԮV,7uL?|r|چA*R5_U%@S}4בS |((6bV1c\&)@T :N 8Ƒ_id‚Tk8NvVрfW>iFHN@- 36Oxf^wuZDM<:2NjR_|,+I@._E{p[=eŎJ!4^@ W]%d>6"Ό! BX9 WCn]Ē13;q.L0(??o`cD\ZH=PIMH`osJx[iXoW-0{`@4U逊W>l ӣ2L[7o"o/i|_%oZ\>!榷ّ{‘GыwZt&^M"sMUrɥ\Y&ˆL;$'4Z}RPy/7Y 7Dy+"ʊ&G,u}K\6 ΀»qN?M9;Pǖ> stream xڍZIo0r[%RKzLs9*MJTHQj$𡸓oޓ]諸H뢺N2^J=h>ܩ,mF=㣞wN>y~,"?vSs:n:;PM%?)<&5?_WT*Gif4ѥxj8LN4g ('{l{`.nxj Țw_zra'dEi<5|q A*&JV-d}d&G"jZ,Cw]l^ Xe)HG,̖G$'9V>ow?4iy$C{d 'n/:x /;e :'LU͖v&S]Dz;I^AVȁee8IvLƞ瘋0|>wO6MG8n𠨀UilolvMu.EjJe1ooP g4VԦ dw 0L5[C"h*O CÑq<:~GY w#mhyX˰ޘY53fvDv('!8جx-<*$oir:/g}v=I3LS%ζ[/Gmo0 1։;/1Y#nل2V29Ӳ}X3 rS?øPi #JgD^te>гa?tAm?"w{%:Y% c*AD鰽`kD NuHk&{W5ÚID5 TdC|HeXey"WSwSm3Jh,W)tw0 d r^^é9ʣi_Fot g\*R/Qx psOnTLpP<^ /μ+=08O3? \J0/vģQ1[y X$7 ;e&jNJ$\b?@ ]\_қGuY&)6ePs4'<M:- Up]{,ϩk]CZ~7UBJe^&kLe\ZFV CV|e ^ɚ3~# HN}CfZL@Ox,H|@U`#gVIZU8f!*ywU Gr,0(tHN:'ӥy bz +|s8u)7-bkU Љ>EQ)=y8vW2GmOU$ YYpH]VYt_RUV{/TłQ>ܾWcQ{D{$|5~~{K9`cX*Ta狤 n(v c! : O!ANg,}sT87\Ky5G91Ną$ e \H| &bCVe,VP9բ`yuq a7di#h${eSsCC&x$6VaW G6R7CE c O1M`"t"O77J/5,`̝g9|^O0-HF\̢Ky]vn2@TB*ya~ Uj_vN06t>ӻfC[SS)Sأ(E!fdEv\xgkjQwdAc;ʭ!2"l 0R%>aJ7(b #n@h/\#GVdAN<{Y;U:)3b, 0%:/6Ԩ-c1N6C^1I`Fg YP`<C;z<햘yq[`3|j_VZ_m3f^R(}6"n(ەYV[BD,*aӼty^űXLڢZhKmWUuX^Z{FGӔ`5sx } HY{4qnV:U$vnje+{+2")2^]}V\=/9|+/Dx(V{ńX魤R\wBokE 5 Il`#x^^AVmQShUB  ]V+k%N>4i,ǝ3/O0T*vx2;dؕݸɒ!xX-U٤G1EJ)"x3B<c[];r0kx=;_ mE[S$|&[2M*Eo4rࠦϏlFO%?qcOv`!OSv;1RJU^ʄJj91}F( { ɆUءÙq@;rlmȦ1ni@|T^?v *Ҧ4A>N}R6eEBHAq=*9~L~az.s(G6be| X%ֹT8341͞\/ϘBK$}IQ9+h.L!F+| *-+!1p-7ggvLCl> stream xڍZɎW2,$3$I`lhKJItS&Ivu;\(aܘKdċR)SUPΫCJdnxA&m!e &G3iy0@5U4/P۲ݻBzz6Ze`7 せ4>߆i=sf]:3`%ʞ.ou:⓵ְ ̗ö́fn=Ǚ;Qn|vɸW;ͧxiEn>|Ӄ`Z?pT'@5fYHfA(0Rj}X,s7QX 0ȃEyg;< hs\6i7=T+49 ]vgn$a8|+ }Cަa JވW- {3vr7uȑTx}n?' E2=#Zy7G@xg^ \0|| Vn6m2JbO:$ApTGHB=]YDik8N ƞ!_x|hBp8@O"{Yj%gbᖼriTF.MM!9swX&d_*yAcYS/Ҟkn6\ wt[CPK>D}Ƞui YsgL^[': *1u(\ʂ %ᫌ4Р͇QY^3͔ZL<@ d1 ]*_xְb+5a_ -p+yuÕ=<~6gs ^0T{cc0*tp"״`Dlo/mF%|?lD{AS (x=!6o2v0BFFJ^KFd~]Ds!%(TpŎ=W:@-M4J}Yd8h^c n DEFȭ"^(dB@ *IKdDC)@&:Ce5u8"уeUɯ ^5g ɮBN*r 9jE: Ys瞲 (0U`;J?MkVd!Ċ azy55f/PW*>W(^؉,D\s7^r09{jVn )%E18r-2yH^o/caAwL@16},iqA܎& Bx~6M׷`_f Ϧ8z<r9G%GRo]"4='r Dͫػao#өGzg; P3"+Ē! tr uNBAC%6#^hYq S(7%Dc %GMx2DJp+`^Oq' -^NvKi G)ڑY*؅ԥKᰣ ) L*=ow&P!n(Fq9 &?{nOk3P!Oa*rowb WGJ0 3DZrssKJ29Jt_`n]y(b|`t0H s(0G$mdaFNa0Mśr bHˁ[FJׁXA+JhºGe-}+1 Dl\ U93WU@nA" ú7fϾo* #jsm"WXcʔ봀&1s$K#/d {z+8>:%G;?[8JV/귛G~ftA ko 'ꂉ'[3tz^b_$M{U bpfd迓{qL:yRR(r^;7F- NF3hIg\րAFL󔂺0y1KqizC>TVN,P[C{o.)(Sw&w?\Qi\O ܲ u)͞j`yllg\$N$~/#K?BǛ"q.nq+>$/o^M玐AaBQW4r46b?ԇt-*`?v&IA֦鐵i n<'Tw俒pR!еʛV4̴S D:n~o*qݩsyf燫_?6U!wUZWep @]=g b_bDɎ$M~, z iٺ_ endstream endobj 1296 0 obj << /Length 3546 /Filter /FlateDecode >> stream xڍZ[s6~ϯԌ͐x7q虜Vf@SũDjIe%;p.8;",/TX޽:7ȟo޾Oӳ8 ˨ϖk_~HB)\n~ł>Ֆ[mSsSSv0@\QP/j&ij7OoG0SJ@TF>["<[쫃i@ف[{VA3pҫff״ա_~f-e"ȼJV}npa=zVnQODFj2;8}mGY"|5}ܭϥsw#}h֬d@dl/wo6$h3 Th:l*bjT` uGn_㩯XL@\ \ ZEn]e5f|ftVkX?F:jEfD3yA{g_ԅ:E9 :'NԹ"@~+z`(984 _!yMt\:[$΂ p$?rYg16Cc L6Mj0Cj2_7qzv4YHCWcpq 2r^uL{cѩ)!5؃qƼ*Wl/D/ybw7Z9%^Ḫ=qJ\PfΨybn`m{I|joj1婻SNn%=\367gGF\E?)I$L$ȫ55ZETXmo7 RBdB*FYq!ֺBЯ{ +O: OVN ƹrFnvAȢsvHO¬{֡v߫! յFJ 48bVWcM;EͶ备5)ì,I!*VDW!0td$iR9b xg~tp* p#q_7=X90b\3X.9|@yY܁kİx7s,2GgfZ홡T'RE}O@t'BjJԇ~Ǻ'˂,' NX:..m`Yƾ72in*E~Q3f2Ic]Y4AˁU6 Bs;d\ e_1@^ T N.KyE)A7)*(;2'}jjB#BzH\.,f{kJC\ V:2}ԧ~me$G;.([k#L*TRBl,E,0G9s1sߜ3CۛuϐAMo0suUQgBR⡔x_mA\BJ!I44R'm*P=Hn=%|{`BEİh Aė#tI50&+*+5ô& O'Ozv>u: U0P'h؉!bSv-@L:c5hP<؇(\ckI$ uP9@|0cVpؗ#lp^t3gnc{A}ٹ783y- AsXki$VI:Zr-cg|gf+7h@|l]7)'j^FH?ӟk|Gl8X7 \: \\]N 8V#/%JgJ4 gJ"Wչs۵[6tS WF $"I"WpJƆƻK@0L_ hRZ }'bk X- ~Cv3I@ #*N{0!E}9ju`@,I6"QvÆ+;9Tf%cq6=OYs-cĊ }2=OcF0 [ƒa&zCoUfbMS;<"f*׼~|\đ=#Y~cUYj,Szu$DC^q)1x;M`ᆡ\X\;ww@tbf߈vv㿡Dl${Hv{iy /_^?nɸؤ5l-8) C9St:ɱKz^.NB ߔTI%x h荌(WhV> stream xڽY[o~?Ke Q8Jcge9A@[ʒ!Ǜ߹Qi(Pf87FoF3{oo=n #ͽ JimZV.זeiß0c2ӂϻ"_p{/`#Z[tZL ,}` l@Q8'5}x8I^4/'B%]1-ZԿ6PYx' QFx~w8C<&8 [Bd0e=E dz(#SEI8| > oq@t>0zn#<>J&ͤ7=\mȴoޢ|<y<:sHn21fzI2>+U]! p @=J?QD r1" MD3@t Lj,+hG:Y @ԗIw}8J7 4/|#$A,j˜i4]l#g@b ^[(:xE1MӉ#NC wmZkB&o6J^Zql[+y_0S@kz>/JŽd 8uvǽ[*i5tE7tRq떑IF(M8%|CE(eK|>^2Hu!  x AD;!ݎFxk%!sVEhw1cфW0f%9 c]f9m . vS\ =Ea4X>R.r'D3.Z $`5M OgmPncSxd |,xtl !KWNa8֐ %Sr$ ]YJ]&cGy悟Kȓ|f.Y@bToZ.yڥJ`3[N"Zve,4dfG,i] ɞjR(OYڶ#_fKAFe>qH˲jYd=Wl&1,*pQvI9"{eA丐.UQwZYi$pُ<;-]6ni!mML(^6[-7U#EQ5VBu3$R.Mf c*vmƽ=A5p"L;?FKZTe(KGش\Wuޮ,B ˅t&SWhUߴiv2@/l|f9 YT#.8G$N.ۀsji:,,* ovM[=tӔ'䋍 /3n; ˳z >e)+-^l `ܛd߰<] 8z.kb P*jǝeFW‰@`j%Xp"l%Ze5ÅX6! ]g!2 a5zGSpuQv}u`~"3t9)YzQ=&upK}&g_QY}UgBiYx:뜷a&٫fݖ2uA! rB[o6$qD@wzi.qzG3:aZC,tp}z>If̥D㦺bBڶ)o4lq{UC] I$@,mC25W<]Ÿ]V8ݞ|xӦt0G" }[ngѲ9W6^I"+av-cmvMΟj l;h5;y"!X|Rx zTlծu*y(άćP:mڳj7òU̮59LU(҃==Wձm>UvmRz]8z=_\ưhŝI嘎n_(fe- DР0L72F2Q?ou +쩢1.Ėq uەd2WWdu!SYZCVh]fIP༳ZΤǒvcNM NN(Ygro_1m-+&dP) ~duCEv/$|2]) @瞡ة*#} ]_XEQyy~]m;:w}^y }px$\̧Nb$ʺm?{U~S9F0t71~+bV$D^twuG&]B^Yf]ybweʚ+=)4eRO~o%—K($*jRT~zaVNwS{_YVzB1BKzV(҅n|:*/ęN)jte x\.Oy&UM:TUTiWx$]BrUR "\KwhEfZT9"t> stream xڕVK60rYXѢ(ꑞYXAn2mDwȡlٻ0`qyqE?(EQ2Rbw> `<[}|AR%]wsU8.㴌İ?1c,u,zu/M'\?F FZITUֿ>;SNx]E@GNaV;MߝWFzQta~JclؑE ǐ,a жC $J5_}3: :Tt8SWHINAIHd~VQL䮷mD؂8{ȄA[_Y &RZB ܕ Sh@1dOhpQN 8mk#RvJb=ZZ60Zې7_ [% ^ZH/-TЩ\;Pۨ6dYɢ xx\H{e˽x6msBbPʰvG~pfPbBqr,QX 2)ꍇu ;yNJx/r^kYh'&!1$ugYVE{aq1"P;ߞ-9]#qTm,1e M@^\8 I0U vl0 )I򐓼"i uVB6jtY J2ja] ߖ!.<ܲN1[_eMiVZ^D8쑤?u͙| <U0(7(н 94J#W΂rPFX)J #f }J4W<>bҹ)c 0&P~77 =#붷=;t.Aw}BxxY_' hJ|c?PP(m{PqCG"PL`^ȹD ;[0)&Ӱlpvd†'@'>'~.E ΥK)!cEEB] Ea,u5~^A0H3mCk'IvoU$WPbt<jn4>1 TGTGAAc+;e؞VC~Hk|rkTo='" (ݨ`/= endstream endobj 1429 0 obj << /Length 5159 /Filter /FlateDecode >> stream x][w8~ϯ}Cą8NgҧIzafhGL$@)ݶ'Y_•U?zؙҜhnUo7o.̓g"Mг!TvN`I0AD3a{ؚQEŶIRٟ,j"քג/+RKc+e9vI#eg=dޣ{j6W"xҀ2iȿ_\RE/l={a +B RDh7R5u*ſ tJNA:DKC#_pF;RI睞.y͌X/>mvIʸŶBMT-}"/" ]p5*J Vʍ *B>/ɝ^zˣDI[ \\A$ jSƩ|iowͷ}-Њ0]p!8~HyjgvḣyLm)p)xV(ȖsFI`bPY+R1qjf4Mrd { %G2 d+JI]VbW |Dh+H1)kD\`oD Sx#\QGت2)9sl3_bpOI Xb]^x ex|QQ٨H4+,9up%MWOKO_2T#Q K2RV!Z2^fq{a.<_ux7wS}lYp!u|a=lY9ap+*I*Z$W.`do"/9H [IM457/]ڄuL扏Y9\u :%G dZ^vU7Phą`'r9J<%%. o׻[Nl4s5uj;bX^0<^ٲa2V}kW&n挘@\ \Qx_r@(Qs@.)tK#Y%G d+JڥQilef p`F(ȆtdtwcLi#¸K1(5ڧd0Bk%ѺݦDURs \°erj"he&7?c>̇`'rP8K dKӱjn3ۮW\A9b_Nk0 #,pZ/9&-v Q&, lʎۧUuln󩹖g_GQ˳wc΁j1SoԢ*\ ht*՟]ĤHDMx#O)h$u)%G' dΈ,(]Rӧ=+ MB_C`CGvz%G$wO'&;C_A)W& }Љ w(J7( ݽHo5qf^̶cv|l5nezM5dצP=`A?0}3rJ)`Sq%Ԟbc̭}}2RUDSɇ.к`Ņ|F CJB;ߵƙ<ٜzKK|E "|*4(lE$hVJ*ꟺܿ쯏x\KVWH-M$ᦓA_euN=~C z>o6ڦI%Ome=d %З %mudzq]&"yU^Y/0fHЕv]e}nr.lw8͜8vw`Ck*D4@=X<#ŧ`'\!>lRi϶m;$rj5=  p7CNt%GH d+$ !|ðigpr..:oSDV4DWOq3 C(0@3M*ք>_kqw,o\q,ЕeLOkJ\2ki~{ޭ7_Xl aSiRm9c @+L2cd+와P5oo7]bZ߯]3({2.480 М@4KJd#cuM4eApO'& Լ<+l7Mn& kOc&C`ḵ[!)W& da'm\Юbt]/-Sӝ8U>Zp }ëxSpR Nirer( 'l N*Q,}3T]2X^+f~vG/PJ.)ǰX!Qa d($ =(z5_"[jFd}Z,gĺ'I_1W?v޶7n-(8ru: IF|QG٫C2"hoj7ϻjB\'T&0]|p! /9'=C偺AQ4{* \,\,/9H {YԶdȈ3x`\E Gr$zq Y/"uug> p@@e|M 6DӅ{ܬ~LT4\. p@'S5{ ճ6CYF*;.<8&Q/9'uIMA_?j"q8GXx%}A @+t0>\!iK^JzD(U.`$!K^ RvW,{16 qsp>npU@rBU|QE٫}mڹ(lΞ|-2Gф` 8'@5it~&cD$#ů\HRQ#kkSy ?y2L.zpm@5%G d Ɖdj4lwv8|xp! /9'=Yo>w/6(YUx%IZ/9j GrmQYf[տi񛀥 ψc23.UA޿U5 LTЕ QMѵM_"K%4iVi|e 0Vi䠗A}%]+pu ݝWY}ک0ʎpW.puR0I4_"Th_׬pGK? 7CWG2XNzuME͖Kx3=wi/׳~O z`-#b}OЕ=$ 7M-cf&Cm>5J0W)K| %GD d/"L hso1:s|l>rp]@zm %G d , D8 Å\. OBaL/|y5'iLwۑܵT&d.Ib=#RרtD#I@Wr$1JJMtIz=&J4#~3*80VJ4d(0Z+ZnP/{8KO}SL>R p)AFY/9RJ {)qFX)mfo/ft V9USQ/$'&a(IW ga( d_4L,+/[>NӬ:_.`dW%GV d/+S}廈5䚓VG1qA*@0K2BA_r$@'4C3R@3x'ӓn> stream xZ]o|篘Gs $!@A|0< ߧzx}2#TqjfP )R%Ork jiقZphlAˁ~j'R1X"OxD 2}J1~S o\x1-dU_BIBdlQHR(Y ^0 GX$v?AԀFH(|'#,(F PPz6z5I3"TjjujbBJjsymM5kb@nJ ^MЙQ 49"s t s 6494UJh=c1CdTΙ %[g,50*[V dXoP%$ &.65D-a"Ҫe (a[sNDE92ؚjAs;_'?~}~}e'w뫛3>o^[jEV)#7{{ ?&DC(}L`q@tF>\YTm Z:XDǧ3ii#i/nB9\.nwӾߓ~Mr(V:?i}>\AMof~)VÇw.,P㿯>hCϗaӋ⏫/WL,sAor>z$ϬS?%.ROQY[ó'Bgڧ>O9Ys8aK&fKs.TC[^[-џoKq—|ymuvvq˜4m>'XG0&jܦY9nKqz_\(ip$T[B]'i.0m)%87\h9a"׽i8*K+K剎^&fEdWz}*f#, .ts#V)ӽ+0*.; À^"lMPePn$ %6NM,Bԉ97Tد*`;1ޕO^dE ;\B{3fKojcoks͑ks!]VTZ*pb(W:p?c endstream endobj 1516 0 obj << /Length 4249 /Filter /FlateDecode >> stream x]oܸ~_6P3oo/W!9waU]cw4}IFZ"9 #7pȡ$(B.9)^ܾ(ڟ>- ꮻ0^+vR.hAjϳ7U_c!&4vڟӂڟx}[L)x+#JpX%W-E ):_,˟٢$R^VQ]</`gۻЬ9+Ͼ}̕e)_/l7zߞ ,5"%-D#EeO` @Ec_*%K_E6TUI 뺶g~ (p>$ƞhGtSq(н^pJkS1_!\!0X ЗDB"SK^mFB=sm~ƱBU&luJ2ݽ*dq^ʁκ9u&Gr||`$K" r4&՟oUP~n68i6lXׁXzV_Pah! =\a@@acA\IX'YQn\ IVbr͎lrC28 1d0IC}ޝ}nͧ.,OlUY7+a0- wM˜D\IQG&fWOͧoC^Ib 9R ~R~xa(WR/JRJWݭV߮Ky5sJj.xs ^vv ( ]/A_RtA6:&J f[]9jo6f4˱NYH|d' `M# JBc6Х"^@?>w?}2 &mHydz 0I %%2d- ceag7uG^ui62oF_ %A?GF 2(WR<U(~Mw远K}lK a~؆[Aُ qALd(\+t pP\i¨]%)cW/WWD?4*&iatFp_vߕ#_" qW@lr̥T> +*)DqIB|qW& ]8dERIpW@DHPfzhn;28^h]%2எOL" j._2F]ttc0?eĐMyEi{ru)񗯌 $V(#lz\ ¸olܔsk+QGqvq(rt'8"js㶏)CX̗`V$_RA)+IdXnn,o8SKL'| pIp%E'dV R5;}^7u0d2[$*Qp@_DC")9L "i[}shB˒/.=QH&l%T?hϙS-ON0ny"}I#MF<9p[QGΗ۟HdoyD'&[?ĖG" ѯ(6Y]5υ?($g0F_B_RAs1yζS&5ӹH)7 x|IQL*][h0$o7ͩi{a,s,$eڎOLs)GQ̕ ְ(~E(b(iGQlGZBpJpf0ЗDn"7O[w; -"sktrs}r@OΌQWRD")Lv5]:W2?+GGR2&_'>|jqA9kozNgTM_b&gBSfD=j0p$)Hw0B_F|IyI%1K@]Pd]~AhB:p:fu3u5Kn"N7N6fu]nV9+6{Gt"$"ea¾qҽ&KxAJ=?¦<_L\M0r)e༠څ}DBєh*}`|IGًԪǮYGnldqin{YVϡjL!z& er/J"^ ,|ڛ` T&C7}pUM4'8Vs` 0txNH&%Sh"|.[D쬕Uc5? 4Cw:5|ILiFV$ w}@ͪO{=ϖ0j] A_dC*yy4ê.%EOd'm;~ޭNRs':(GfTT`$.KT"^*ʾCޤ s R{kc`GAkcJ*"^R]5KQtޛ{:lx%EVd/+!g:Y:.v ‚U%EXd/,.~]va?oKFt!{_ʴ8}' ȣoܾʙ\vqy,w O ȣoPD+H:<5&]ͮrI] gf$ L&T> AhYpվ.wuyb!~$L@:BTqIH%9n?c(% 2wuxbam)u>+%%E:1 Y,G•1"8QIR*wuyb2L,(1te2viATIWǑ'&|KB_F]  4t 9%=l=/< ڨ#a\~>;ߠ/8|};x~ ?}IS8Pg0[m ~הVs2(GgXX`(z"KagA,oإjL|RW1ˍ{z+{_G>mJ|kr~@x@ /m@_RAvvk#?( EeJ`[: rk4[$2ЙVmgDQD-D}ZvY}? Bggɇ|M)'@vlя1^jʯ? >Ԩ endstream endobj 1432 0 obj << /Type /ObjStm /N 100 /First 1005 /Length 2272 /Filter /FlateDecode >> stream xڵO$1h`1Y6ۇ$f%}z ηSک1tHFmWӫ~~T*ʩ*M䅖X,I/}V J+?PT\)ӇZ%T6*Ѳl5QQ"* c4v6$T\Z֦%2z>f#q-M\g zMLz:3. >p=4mVuxשbg=IR+f 2(~J#cH&:hI7,i *n/\:)%0{&U^JtmC?YOS+eR4YjYOm )pZRSRMBR1[P%Y^8ǦdR-e>|KZQq%U(^1=/yI|hzNGA}R9ј`^mPG,-R-\->Sᄁ@ħCS dJ1o,!h)f_U#%U}ⓧzRyzN_~/4|:}黂P=~~)}>܇Oђ{Yޗիt&K:Nc}'2eq̮yvd _0L:{L)1h>Y5W{ J6J=&?d+F0E\8 SK.aeM3]$+".r<%WN#T^cmYφ 36kU52ǝ&%2yQ f=. g%1`;̇|`FcҢ`{U6l& 2Rˢ(̈B{EzfZS:md_df0f5.|9J>ඕp(v"C7bB Qk=`$v3"6`6fڃ ;3=h-ُ l|;Ef2̼Ժ^yV{wLd1{\e +bŶ;hSTDl{ɼ.L/ۆ"YDl]![GЎeb.nLL+˕bX&V0#ژXڸ/ZKfR˥رbs)02m S|ٶȧElv &ov`$br sml%Q;lSiɆ,Xp.Z3 pDzTs=`W1+/\[eb;%n#d,wo󒉰rC+.6"RȼZ5f}[MywXIȻE0 yFrn !2CSZB+W#[(UL$^|#$^Ć궘P97+ֶ֒V,(UlsS9v[^~.t 1<⪾g+Y|{EӤ¡![acyn.'ÑuyC1Gne/k֯$R3x^^-%k)}姟޼|4o0t=K<u맷_ 7һߺx~:~Fwo|~~_?L ~] 6Xo?ן~y5 DA:u8EGa t ]BYBYBYBYBYBYBYCYCYCYCYCYCYCYCYCYCr -[(PnBr e e e e e e e e e e ={(PCr=G(PL8W_3^ZۢINҬdcgSAƹ;dC@y*zo H#6z-tiX+ i'nZdɒ16Y0X@f%l|ҡEf6Lm̎|aY[ Rv5W/طȫa[\.zqa^1bNy\\ԺMvm >;'a$cu;bT Z[ْ.&jX3ƎhcVd#w>袤OT9fvͽs1w> stream xڍT]6,!"CIǀ ݍt7 1HH74HRJ H Jt|>}k֚k9{ku!tC$Jڊ@!0!Er@=H7pPQhNBi#PI$BB;"=%`@[tzr(!=N(2? p+('+zE0DBPvB%}}}^HOGYn>/0zA=}_t? r^xC$ y#C -;폳>_+W"`0tu08 U@`7_``{ 0xQ^^pįAwYA uCyڟ2 A_ɺ!}0Wnpo_.h_ qFWtE@0(0 ң /dd{"L u8pRl߁_1&a8w1$;WU5<$nG6iaҥ\3ܢmc2/5sO;u,s2f:Y (z78PY[[lVa]{C)z9c n&B?Z#vgd"oa|Ku{ływF\S}L[#),x?jh+/!:L&QH#{t%#cP5nnO³vX1@k`Fԙ~Kn݂?E''Vq[a<|2z+**ˎJ{Qgg1/j[di2c'a*kiFov7A%lgS>lQwOqIK6$3? p*%j=ʷ8dxr,q:i)tz;:!.Ӷ`u1wρ/1Ԡf(ehoP|i,sֱ؏墯ܓ-(ܟv)2H Pb lMY0#|!׻s7@U>3=5jQhzŅLnU`k|&wzx^5$ 4aA/r/nsU xH9Qo?'QNW]mzۄ|Vw1~(EOR(%P]^S;q1 ه9B_Z1ļ澾UQ2LI_`,do|( wN4(|9/ 3e8YM} 46ly-.i~!zd9z;eMFمށJwͷ?(jÕ៞k*r=M窬/t!:=R`Z!Lwrl>so/g-|s/1BK@ithVJoSMH7Ay(~ uGNwF',iD4o$aFxcݱi 9U9|U͏g1Gpi%xi9ۙ,>KסVQlr txx2o)o퓂weh0ovۥ]3DhN,u6jHkn/-QCؘ[73'LXRK/4;$ĈIJaQl9Z_:fB8:`EkY[qXswB2$O$^>J~)ǟ,o7ט3ϟ g8Iۛ>- Mʅ=@O\deC#",[3vaa][G䟦/\;•eMYf-Vzff_Du"ZF g_+,̊wK%;nTy,⛽GFDu;O B`'/tS^ zT}]:zMFݲ'q8 07FcO=m;\<.|Yp!q̒;KS̔AI{8O$F+Nj UoNG EQ8~=Nqe0uFȄFgh,@6wq=!D'ן2.MU[ʩ!ڨ2wФ'Bjy-7UE&#sg[Ijs5lΜ%Ez=E}~6@%'7S֦[fȩsuo; ;< }g Fuis.C0gQmM$X*hΈ4e}3²fՒ mA/nw߬ʝKb6/sq={{#YVD^F㆏a3҄e*@MnO,j^xM 2=0Vͯ=^t>?j=ªX[Ȱ=a,\φN]&?s LGaCE[ M̌7aB7`:e͸hzܷu9l$&z9DZ@d35tx(d!Ηdv,4&N/S$?幯p"XfȦxe M<`a嗏 atjiH(>(lFkq?~"PBz"|| .?h(%i{HA#\`^dӺoﶄJcg-H&쌠 'K8B \yx^;OŽw|N=r^4{$| f✑݉A|uA1ݑ*^VˆXgn-xa%PK&M.b54sg\#,6 GN>[m f)r CcgTcɵWzR"M296QvIx%m}Gl|<{ɏx>rMX IɘeCvVOr`&"{"NQUW Q>-Yf-*ioc3&#y~4TJQfQZˉH-G;,B'$S2ᬚ'mQJAB+3RѶvNߎw^ߢyj9є["h.r?1ڡ$&{(hUvvWʁs~{e|vj"^fxYJk&7Ƥ͟;t2ꓖ4\P Zztzl@1Ufku̪}b r.rQ:98weME2D.rJwڷ >$ \:؆;v,NԴlFʻ בJёuꄁu9vLY<&;⩅*F tsZNyRof_qRg r0UeQstIhR1by {ZF -s^m HSx([DMɆҖG;K)7#>)K 2'ľ:/q.U%MZ?H"Oˉ ײybLx]CR|94+jd*/NƅzEO|0E1} ]iR4d5S/=EA|AxZ r)̇R2) n@gZã]\a4KB\;~X!Zx1s[-NnI})XL-l=|V<6uWOHښhCjXmӾ&(.r;~1w, p\Ȭy!\]z}~P@Y YpCEݗޘq ݫ0g>Xa\Gj?:IcJk7 &9= D[$z-SFâh0 0.8\LO bn&WVGX8q@%NV&O !}5MD/Ɨ(ťdw{?6-~U. W9h\Wzb9]is4Bq++t{khgFO޲N5YIM<=)\bAO?_\ZǙPj]4r1(ɣa pagG\n=,+Z{=l΀_Cvc&xמpRNK'=N{@noz* /\yIk٪[:XY>%e1.LU# ybAlֻR\CT^*٣q+Q~eTe/OHLTvf28_;bk-|R3IuDVK<>h*zqgSq21ب&jϕÉXuQCo#K9R*YbI7UW0H*jTw '߇3Fe`!Je0P1p2~Jno+0}w\\84|\Ω>-'>\+לu@a61&iRBa&]N4zӺC3Ͻ5B*Ean -b#69w4*)Jœ9={TQ$Uשm`@ͩC}h+eR&E .:*BF%X.eRbeZ :!ip첊ܢm5& 7UdLk%e:j7;mǐ?SSVE<\;) why2džIF%jiϒQdKaqhOo:̭f\*%>o8j o7|0$!fEW 뎽I/OTQdj&,ZDm=Ǘ->jf8`s/ 5ZX". T}>`X]zMUk}vX[[&Uwt]wS-<\"`_y KjnPNJN~,HA"*[<^jsД+ږVm-7i*_5[bCre4rOW$_1[' 2Wګ5X5]@u^ÖĆ5-9ҳo%wM/,!mK۬5ĬUzvd}M Hz1&j"I)-@^Dűbkq}A!\dG͕poV7l5WSgF̂ߝ H~,>}ut/]i2-$u6ozdYσoԤQ L?ckeỀ@*8OGxy<+z(%FS[(Luc`oZ=3z3*C;Qv;|#@{w5']oMfEM2n(HQ3 զ3a^g5vQ C ,,Gfu)(E%}w`^ !=uSN n Kr}ZV%2ktW{!PWh8]%ԧ9W h:i%Afi‹Ecm; 8ޤ.rB̹#]n/ՐUw}p G z6Z]ݶ%1YS66̎Zr~(f&f8~˻DսǮB k'g2Wr<._m/-Չz#ş_64H{a7=umvm;x.ٺwacf+ݽ{r$of endstream endobj 1537 0 obj << /Length1 2349 /Length2 18091 /Length3 0 /Length 19458 /Filter /FlateDecode >> stream xڌP\ ݝи{pw nKp ,sϽ7~_^uUw5e1לkצ QRe67J۹002DEXXl̬j.6Sh-x!4r266 '/ /33?N1#7KS<#@ O!jdin?&4.mN&Fvy# -hG#%RP[8213:3; -],*@gd-)jT\܍Ђ jg tvJv;@wq,,MY+`fi(J1xLr4qYE ! 0)>g'KgFgK42Tfq;SQ{[[3_,&{2p,Lang h Ϛ9:&Lmeo{H v6r\\>4/gaZvfc;YztA`z3#fSѐED= lV y,̓O=o:ۿ{B\ 4.3 s+_/# W٩vZxԹ.)͂u="6&ba;sYhdbbwנX-Z ,.k -LM2VN'<3X98,q4zLv.H 0 70A\&?bI$$ V`L2"A . 7A .hA .hE< џ*r1hA@D_:[Hr7h'/'_ 6ۻ:#;$⿐T O hDT@P!lAP%dځfvV?d@cqcq3_A!!?rܝAwt1rG Ц t1X8q .p$g t;\&NN.s=34_7 n{&pgLa^rjw}BI\wNA]L}\ Nej~q"X!ڧ/_4?4wPd;r#+b+qtSsb?E O~脴^0 B֏$ĭ tFm;ܡz7m:؝-MMFjis=&64dYa+TPRhO3UN ^CW";*Wy9WA񥜖nH"&bYq/uڱ~mKy*B #o1&Laxb&SkGp.qMzAlas3>ws$[$KZc.j~7[9]E>J[; }pXulPmX]j)]6.ޫb`a=n  Wbn'~j]q\Ⱦδr xIRko*.+X=c/`N0>m=Cv{!&R6CeRwElC}%YnSC}żq- VOB_tJ.}o+ӝ`ZFJ5$pL~U p[B81:i]7JۭlS@)I%2坴4Oz}g1pݩ|(x3F_7+ 11T:/+ZKHlHمeo#BB=Y! KV V@$If1`M̆A'>ڦY=g9U'.;]R=&)Ll!Kx)t2Т UxH/1]b/j @M(s]ш8ے"eɆiv3a= ]b\sQ۟警,cLOszdq 6 o@GrdE} 1#^%ҴL]14ܞ۽rF6* {/&Cdրb#ix[RU[czc,c(+z=I;eoz)8wR:Z 'YZM6JH!c񼰼kmӘؚȘ>AӒ5͒rKY3Q73ř]`2|2tĄ2xϜ=x< Cn 0 ZO(h:4mg3~rxU_۾dQ~hzD?u-/He,3GRle쯞>wᖒF85n^rs G*iw$i\|^ Ve^E9. N}\ K;H~v |8o ]TDz_]v3(JHȖ(KwgIK^uiݘQy/QCj5)c= xӕCSZPjt2,K$^r : G/,4:U *S1| ?aVr&SOcE6/3=O͐".[),2LR ЮxZW>|A!l79`^l2TD%,J6u\X}Jἕh }܄EIz5v&[yjH*X˘uZMV1t7.+\`Ğa_?bo.PF;0aEOULq" EFWɭA@h!CUލc^JhʃOzطU:v 7kǰ3AGOd@I9k"K5oY#%uJ o#.4XRV&{I9ֱ~l]JS4jcOFJ6 fiָx4" `655o9{Z3ci{ww6mM(Ӹh8b0'U2j1tL>oP_'ȥrj魙J  `-2Wgw [an%߽e0AY8TBla kZ;dHSo/e[ n'D6gP:u!VX+߿[ۈ֜{PLR5hId(2aʣz a^k;,[Jfz{.O!waNOճ И[V|m1|k`Q1Reb1 Î UJou->qDuû=ZifvtM$=uྵpD/ ,4>feJٱOpS!I׬ofJy3tT)gL5-dž·§ҎFkU}Ne¼C#v"6pj}uT-i"yTeV= % |''H36;)AI*&ZF ۗZЗg`ͭ{K6=Lc@tbM E ּ4ˊо?;g-W]1ukU";Qq;Rn~sKĕ^%v\&xO۶vVvf҈*Du+{Bp3eQ#x EHJ(`ES-3Ywy+ $ 3nSnڵ@m_`brG(e4 SB)\>ӽ3ԓ""ǚ\pV*/<M^\ HgL鐆x0cm"j{{Fެ3"r P5huQ"ojΖg{^F+dK&gp6 /&y]PtL6"SB:2404MZb&1Cq hЛt!TS;kr.VGƎ$mTkHnWj:E56&+Dh4n@ eeH\y_h?bK꾿5tu8UycQD/|*:m$K2 x1l ?UbbFV#s-R;a(~h1%5MfNmʊ :YFfCfs\6SviZ_:r.qYZyLq,K=VZ;]JG^Wyl~ԘD(ED6kX %EgҡB&#!fQG7Ex*0iaBDUV9, WEŎ맍Yqje܇Xpd/Bx뫧Y;3>HǗASzf-qӐ=&zAr +}qpw X|o[ k㸫Axs(i"Ս_ |+dK,= 1g^ݶMZ_Skx<mVcݟzoz8$ X4/f:RX6+luü1΃>&N^wrGV.v4pINc y~FD94Eפl.~a:G %&FEnFPYTߨd =gY ]|^ǩp!=3>%6M{jñx,esR\OxQBh+u;|w'R=Z80C6L">P n.{W5mKv)**B1b4y{l)_֝LgqSe;I?Zl\P|A&eȕ3F\X!h I +f][Bo% 0\+"I>,T) {9mJ_YK4E_$, 4 JHCS)Nm['x5s:DmXyl,FVϦjGz2:oU::)$-y㿁OrlErL30wDJ`bY6?`_ZnFR>f_6f9D8n('Jß x'4;͈c|'bYa!LŇ,w4bI=5B]iN([Ff̦$l>R^[ Җ'E4QkDz[OTdǐSL ` XB[o$8rh~/'ghN}89[ӅnX~?=jK=N+:V%ش|Z2ѳfvHzW jMY&JȻǺ8Mx5~ewŰ6bEUX3juV /?er+$ςuY+Z9S+pp\s>/ B|)!B>;8LuۏDؖ8/(D|EmZgr%aM SHf`Կ* AlT7@KvNPE>N +o{6w V_欸 O獳tKZj-3b0O–v ɼ,Jяi{uA7nn<g&7أNHНXK$Tm8NHS#rXm_Xuؒ͜\v",Dl"V֢:7`{b->{}9Ok%V{9 2[rtw}ќb!MCF`/_%[Hk@U}[)J?l!.嘭8@EZsW/Re*bK]LJ_G,+-7%y;e]}#-<>_|Ԧ_uy8Nvԡm?Vp2dP*,FHܪ.E=ͮAz'`Lٙ]A!}GHU )7('7|!6{/vlk d \MCL;oݞ3iEvNO 6Rl1=+ @+g /!2lFğ&_{Q}t؀ 5=k l7q:!.d|M:-lwU)/Y4Zպcrߊ[vx<VERޠW.\Ͱ ϻm(c8b// ñE0yJ[ :5[;.4[J#?#jcbg)ܪi~b'? cK^UTMJ$'?@Tcӆt0v(=i&ַ;:\;/e/r_&Us?mmM?@H5&nʉo\qJqIy~^_=d:*&u条<#TK /ve.X3K1?c9`Y]o]tcvȁץ;Z U') >K#-EF˵{/d}0SLd{H2q^zk"HȆPwAHax}ѭ0>2iwO$o*a! VnQ3H$Γv9kFNTHXB8)d<&Iz.QZ&aŖofnf |(x bDoP1H Т`h: jГ6_{pkDVy}oUF\WڍC"?KQ9){S'߬#ثoC1[wI>} M '&*83L^ (Ueh+RkU3~9|2twɁq;* U Ƌͪp.F#E ;*ЂCkq;k-]퐯1A7Zxi/?dTnâ @N|ﱹ0@`hf Ӓ,;eq72f{K)ÙuHsT @o/`S6`Cy.X@և۶f",hc|`>mOI6F#ְF⌌@w !Ï%Mm⸧Hc㬰Fq1'3w'h"7y<ǩޯwO15|R7ɇ M XݾU]ѯ-N4Ie3l0bvIuHRLgb~ZrEID &)1B鋑}~o-S±~9"h fwlh^`}dʠ*Ȭ)0la.ɑ1Soa:M+4Dag Rl^dˇYj*Dh' I(Z)e 0^f{%Q]#n @@R&6ߜ'i߳Eto)eK#Nݷ8͔İw_; ctT\ [dZ`w TqQ|ľ#țtkѬJےɩ5V V uRv_j %f* §g[ԴEgQZ׺9F2г +<%C!bׅC 똙CjZmJy}޲RYy)9ϐ!W%x_a+. )6G+pE :8G!:nϯMͳ1*PKYY;LU!?QZk%doq|EТ2ǘU[p q:}1I:W_5K )z=́؈JT\,݆[w֥~Pg]|K(i}mc;! ]syWKW5-nV/q]Szܮ+kX6ɼ?%lGBsS#?uΓ;P-]Tv?LgxoEz.Su7T53VQ Q_ rjKkQ-+HUeV#Z2Xd 8H.7oWPOQC?v|VBѮln0~J<>9O _=+g*ח0/MSDdp% vߥ +RA_GG>s@xZsK˰Pr?CTLޒӻM8v[Q0i\ y|"8xG8:m0=.xLtv~N:Pa#EN6KRj;;j̝2{ Ip/xeC8DKs8qf\Z z`,v5~VQ ~YW }831ijl_DmYg!R$`E|<4Zn:1Fh<ȿ=! N'^SAp>[XҼ)5x[qKx>US:yř-[‘ʜ`xm Y5oSUzPa5ьi;{/)&Ho_aE~m|tXwL؄EvʀB %%ƭG&ؤ7Dw.+VPDį]/d$5bm8jd|-qӻwN+9OT=q(w7kW#78V-h-4_>vq>%p}me@ӷ5QbY% 0e~Ќ3)w(JeU8݂\ F cn/ֱEǫ\.ۑiwL5QiqcZ/{Z<Afe(ʒ1|;pU8䛚[_+TC8M(d;gbVAȝ_Z#/9?. KE ͼ&V60ʏlZ D d^wx(,KUmwf7E4A(2W+'oap}[p)3oۙD Lp x ΐEOrzz r̜O%T7~i_9ȑ6\1`lΕt" T<4 $OtBcED)c&)]_EcnĤ'/~Z~s=zqea/v!B\sF2dY4 1-Ɯ0ŊDtᯉc8$Uhggy|SFk}w|WڔS&T.0IڵC ;}zTDk-IF َrETI7nnp+D# cjˡpE*l)#td30(:~띐M8GB*JnD`d$z_eS\B†ɸQQ$XjJ&=v+Bh=mybd].^,};j-!!V)caQ[҉*{[*| Hq fρ?>{Ub<]C#eru)'>F8-(pK ^]y(&RF@~+#n&}c`yl9dBcr6<2G ]BZlJpN QWf: y25$#t< Qzi צTb9jdjU l+è[t1[ZOkĬ%4NgB gkČO@H}"䍺 `bvҨ]lBR朳PNVK}-)9dy%ǖ`2`m` 3P?vowF DF*RSDBt#^h]'423K{\ZZ԰GXwiO") SZ,)`p v!Q9-gyNX=uRU[ͣ+@@ ދ)l@͟GVX4?PCѯ+9t7u췂8fك,n SֻtkE9;? rC=^W4p [g/^L* r?IL}g%p e`ZՄv[*\fwfN\ FsH#HIEF 9nSiK<.+g$^y9de>[I[>.m^V& =)ZT"1(Mv5 ic*>f\8;'\X\5NAAB^ / ZUV%Nl/ 'F6^7@1%Ӿ莹OwT4 X5& ڸ 6Je03]T^b͖H/T(4*D={*뻯ne솁ppCz ,qg r+\Qu~ \8:%֚?`p 9RCmQ˒\iLY'rC|A2ϳaA8Cc8+2HbV}剕i-aa1`L:tx#¾\* 4 m\h9K̳9/Y]ySpН;g)h=DIH{ e] |BZGdݏI#!d` c7VpFd_Q(*^}gCGTO̍A1K kp~?RyQ/?k-|?<YܚPX |kFQ+m?5À_2T L #aIZn`k_Pn*9I3ͅ],"-^,g&n[[@;!IwlYZok":/[Sz˼cdKJ4c_ٕ||h@<(YMOo#jL˹¼2Z\M3zZ)5N߯(ܫ ?E׊dP[;Q r99 _-6WEcgr^EgmK rJ <厞CXpu'8|>W6xZpV1%vPsڶ}q+Яٺ6paǼZ )&_q;\vⳣ [D1_1Sl=|^Gb{dzb6vF4pgVT2i1.ēǵQ P3<{%c0#V$S7'|)"]6qx;=JTx]*9vkvdTADF$荟BZ4zhm3>e;EdTJ$=qݼ N'-3V zn@:_jӇ&n@q[vx2$fҀC͆_c?4[QJP돢%p[R@=v_wѹBr`A7 s@9] sOer/Eq50.k뤤~}43 i=BTQEc~s|K1m`a: j(*MB.T4گ,'냯 nbگM$_A_Xrkm=? #ڎTu$$޸S/:hw_D28[r,oL*7_ȿz}:{'Xּ i=a˞-Lątyc,W45Vc-[ؑ{HLX˹Ii;kˏ/Zf\ !M|J2!4G }#Ҍ.^s%.OGb֏MVhQɕ,1L5%)aց#'lÓ`A:A;rd\/%3t::cǹYi6gTuEPlLJ ì|= @^i:5Z+aKqd)yW|gsD)Dz1vWdkxkQ,6qRu=J:t{GBQa$2x6 > g+#*1+37eXՃf 4xTKgvBkKZ#-\Js. ͳ s)# ;\%w6wWLVp=˷~KTAJMդϮ4JRLT>wyj(C=1i8%:VSw$}I2V*6?Irbd!Ӳ6ؤhG\X ,@Tc>U%\~I#ah]' Xƾ.`>f}BZa Hg'd*pld OÙ ?4(#]e^o$H:Uf)TC}_^ wvkL;%(NdK9-QeVj;-.F(#g`EI?i18EB2U|_ %MJ^?@pBw[G5 Fu#yj]]a}2YxM7+Q Iuݴ07IWR+K.(yXiIKM8 :~A2 ]4QA:Qg#0`0tOH¬3,ފfM=*11*]eavE@k(]?> /hs2?錣4Zǜm@d7 7}RV0:ǁLR6wuޱW3FSCIra%2^)Ь#`*ܩ( (e8tJO s#:!\gHEi)~ :o4=4>]±-Ϭi}gYucKEc7Q;>pfc tF|[@0YߚZIBeQBHiXOK_'R,S#g&}WT!*&^Sc :l:g^4Ջo dܽQoam席W=]0TZ~H>Tt'[q;HX;;>;ۄFo:mwƨ3 #S{!1+iC)@ endstream endobj 1539 0 obj << /Length1 1398 /Length2 5888 /Length3 0 /Length 6843 /Filter /FlateDecode >> stream xڍwT6 RDJD`Ih"^U@IP )7*(U@t"EEEus]Y+yg3}DH 8!0HA 1aHm, tB]`1 XR|K@0@Ujp,[ q<P> [܁Jp  A 8G+!#4AAp?B:phiOOOa+Vqz"p@c8À-!? o    Gb .H$dh poo } BQht#\@u]aNA΁, \ v!@u%# P  c.=!\ru#qXy} Jwo?uF<>K$ ;Z pskT8Hꖘ{AEzῌs5?4 'C ?,a~>i0; G'e1/%@?0tɚ0 oik i_FeeGHL($*AR[?B_-= x^E]>?ԅyt+JG(+"uw_v߀qExA# ZpwoBX%B`qao= 8o֛/  7Da_6–A ,M,apy. K:ԐP|D%$  I}5~("D.@B~@{p>h )0\Gl;CH˿C(LSupA,fQ.axIg`Nmnٳ}j8j8W8b.&q4=HV.]"2dmT9tpU1DvH~k{eI.#m/qMv;L|r}mΩ#z띦dp;W(NMMU|:Ϝbtz;+s|[K[7xo9&G ʩHTvIC|>ּ# zvXhOw-wzrK__x؇7UL&ɷg52j!j)b*_4};9"H»{>xӼVeI(d }4~f7&XM-4*Z麰[`*+÷J|@(% ~$Y6{8FTh'm7H Q}? NеxgWė${򺨈'~7h*NǛz}Zo- ܗ%.(8 ]}D7h-qtNSNHK-%r·~s`eΔajqfw]ͼ`a?y'Wf5=uA_pb&Lt3ZEوwI[V9\&k۵6ej?ڶ:={y7hjrJ^}J#ICH?z} x"7_^EoϷ+jqI|z2CMa=~+x?.>;B"nL~~{)04I7rE]hzcgrŞ,2 v@ߝۋ}EGL.՚~E}3LY]π7mD(#W^11zm[y+` 8k1WH`8"p!gPdaO|Ln-&텇T}W:UV;Fx^c~VxZe$2Z_,SQ? 7JS"Œ-gSowe?iލA_Wg :NSAcg3Ւ>xa\pѳjJޢ2Ff*hշ2*Dk<ꖼQ!E L1ȯ-6;!tKrJA3q1"< ֍} ӽk~;ٖ 'FyQwuc[ęTe,\L5zçpә1A_k`u +)pF'%Qc X*,rXgH;u|"WQkGb^nހjO"5GSvI ?Vy;Kʯ6yJb]LJМmP!G/3$$ג?=`Z@^ҞYXQlrgmVBnD3_hab؍$2J8aڗ338(3&t<3F]Ck*+&z{c1It×/-tӢ#Ku]j5kkw+Fz\@d)ڤn(Y[9n/G&FWc+ږL$K|f>Rxf"H~DA=45pQB;܋\MXo_V)ۙ*3ǚ2܎Rk".0pLMS^a $Ia/8yM+2Z@*a+s^mF mwܹ=zj7g([f Z˻L1dUOǛ,HСdyAJzKh(ic $U̼{-ǶSr/Ȍ:}: w6D?~ر ynK69i@CqgUjP0|9mR֢(+Ei1 /Wf2BjC,! vf$*~MlEMp ,c-pP܊ZbEsyLMt/|)|up`fTbcχ'~kB?X[_lvIQ&"BLcy˷YG+ [ {R \[ĮT׎n.nr>?hju:#QH9WbiX.JZhVpi2/܀SO >Ɇ&%L8,̑ %2s?~MPJ.=fAH5$`UƳfPRIŐK#7d.=xU{ȞsRA{^\m5Kg5TEx NAu?&u2U:[C393֌ |(%hqX+ƧfOJ݂Hms1JTe fR=]X~4!Zឋs"H`{@8.!.1xU:A7K,Dg'դ[=ՠT 9rZk=$3ڜ_%t,IѬɼ3%jb.ڸX(v[gT]FY[(G옊`N8*6:[zk\J];t?sU֊$39;>|g;VY=Te7 2N %_ivM}ݫRtSU-(t)Fq=vʆ9r,ݤĤq8+R}ydvI9M9Le3.jL=xeAVsE8.U\+JNp{cWz%nP(/zu9˴I8d|9.ҨIE6+]rg ')CXQ-xߧ~܌'aNʓR ! UI_űY>VMh#w(o9KӲ)@@ nK!a,S4X"ϊ˯F'DXwooj90a{` L/L9I`5U-зݼe{/xQez_n7<4mtonzC A9*6's&lxE+T եSkz.޿8U%ha誹ȶuF ~@[ϥLnsIz-qeqCѫ\<^3e~F9_\4 t8Driج}5o$*'?x"T1UsH-~^+%U{p#Ywq&aP⤉%ŲvTh4avgja`6]\+3ݏGwsKt4ljnvEA=d-[StjZ~^fZP3#mq7%-N&FCAx,6fD_ZI>_׊(fF'Q ԋ=|O{xJ_uN+3s0j?oՠjO޳* 2]Z d+_?xD9\WT"ܱeuWKXaC>OSzx'H0%/ ~Ƞ7W gUxkWB=p:6hn?9G$9%jJ tn[(k:b\a1=RZ߭մ)y xe+,t;c"[d4im35DcF5AH%DQtD!|  =Nݔ#0z#qЦ-//hrC~6~;G5ֺFMzIBg#WOU˙i.&?pg6сJV-Lt8<\]p_Ĭos&,yxVF Gͼ/ 9Xh%k?R+3y5;)y0\A=)d-*D/RdL}T16SI"wV$Av3/QQ | 嚟\8ҊA+}hPnչ[|2}u^c(h>H\I-uff[`9£xUCαw6z5tz0#Kiֲx̯0H38MxmL}Gv endstream endobj 1541 0 obj << /Length1 1398 /Length2 5888 /Length3 0 /Length 6843 /Filter /FlateDecode >> stream xڍuT6("LABa0$[mlAD@;%$DAB:D3~{}?};NV=C~E(FAB a0mp>aH4J!c``ަ hPĥABB@a!!h4P삄h ༏vt ߏ@.7$%%+ !`PC!`{!K9J h \!0,  ;&!C-{$CQP4T:PZ|? ODHԯ`0vpܑ(8ij p|@0 Ǣ`0lj TU qX,猂?YvppXvEy}E?ǀ:; N0u? ń$%D$Ł0' Y ivǀy#ma'00o Hh#Q0g1H7~ , QXPMOQȔq*)݀" $$,?x;bQh|~w.HG!'A rt !1! _!7dwloH{?x," -*;j\?3Hs4~egZk4v/DiўvI f&YwT<kGjDY icx G_ + Ʀm1gj 0DxQt_Tո8(/AZ(iF5,]= 'u%/ &5 d Uy6FOl2:T -_ܛ 7"BPpgt<xGBeRIGЕnlx%l_lq Շ_Yoz.Z\f@n"1b+;4Ij!#] .te& <2?ċB\ITj#$>嗚 7 4U[\ݦROi͌%ZzZT9u+^Br4)O=_?LfԢ]c#UF f}d?f|/s/sU{@Rcs+aU:h;\,iX RRl%ux1d"%qMꒆ|KYff$e7Qk.a+;z TL;߮QVz<D,2N|Ns=:l4`Pxo-Wb.;hi+> ?ɅŶSp.wnCe`aPJ^!M$S|{1K gwY2\ =̀|0Be= ~BFǤY 0GFBџŖLUT}N^4\aAT|~40l3ЗNe n]/a& ,^/+z`[,;_`Dy鲅]sp'JUfԂ)Ʊ'oP^&!`#qNOMUyI+PNqahN23Agc߭]'>)ҧ:Msͣc`D%Lu%K:Z$nD N=^$cUE ^q6Ǝ]9k-! >iV@ے U9](WR(o|@"Δ9K̼k7׾L8>׏ayi0Bڍ OEgKׁTS$< .~us%Ucݝ1Uѵ_t J,j ]⃒p7j]@bpTEFN_t$` gaI 7r׍0oܸeaA5YyPA})~iw6s|_+3<||/Z. !3td#d=?pKTXX-G5L7vp*rP٩NY ┪ůjvONF)_p!*&|Ua\[QV oτE\xAGrUvB=t+bŭHvDfhc_,!B=e>dj?nWɻ\ZKk"g%w f[0^ň|Su_? (51zkEWa|f m-8R JڴR3áDb[.ʖE?hkoAXc\fV^,Ztm^qMY{籨|# $ *߭SR3a20Oh{n7}ѨD$q$)Ԃ;G/9 Rڻ^ *}<9[fsL^`-iwmf,'<@{ +VvF,(*Cdg),VcW 8>S) Gp`VO*>&%Omot g_ra:#2"Ɨ 97cKTܣqa^={rÛ iPJ6F[Zիb&WU=B}k--_= .HF,`ZzWMWK'bV[IK_ica9 ,Jh~$3^Õh֧}RY(3q]Laբ0:wR]@g Dŭ37AZhx*l?T "Q\]|!hΖkAҍM$C$Q>A%~bvs#>bR_7T̿xEǾ6 tk@Ԉ1:cm$i9MU}-@3?nx{W8M H4, CY<V('^u}gw2MlT>8=z]0lFڒZR)-gB(V6ne-1NL{c#lc^ ogeծ~Й;d<ܩfp/#°y=܇Krɝe#cMZ_)GbNrZxYr@zNM_L*o\/iPa T+L,iNUuz6~ ,כX_*YU-\&,X9u{ՋYta)L|@!v3~4Y];-=TLڿ ȭ~)&{%m}܄4dTs*˶A[B=ǯ$ AONwew\rm_v?=yyU?3o$jHI6#d4d]+$?R}Oе`; ԓNp)},츅UG߃NiN3TW$]5Yjcij|ahZ蟅9 lH&n&H } MxHzRk^i>p?qu y*~=/Uѻ2_R˘aG쬶MF6/OnK?}" Q|NeiG4OپASUxtI^¶5fh"s7*=|fJ AȸJ(/BOrgh 55ɌjބI>e,<60)_aU.K/v=PX1,42z3>o$@*~K7}2SxP8ý5ɝmh1>mǫܖ_gy$Y_o(hJ/ȼ=ʢ S ^Y(N6oY~qZZ+"׊ ;"]Pn)lP֒I6djgǼ`̜Yߒ9e!17 xA?PU+ٍDv/G?߰?_j_율u++<3 ϕ-'2ᡟE/ʌTD3mc* &|T-Hyt(u1 6~LnY!O$q׹Z}ngydjDLK~dK$ߘݙP +sXIL|9*_ttV5> stream xڍtT. C "0twH0  13C HKJ*tt#t ){׺wZ|{gww?+g (a(^>@AKKM $P#䯛@B0P@@@(O0#@@ PB@TEP H'jkW ..w:@ A0eqœ9`(\v(?; GJs?CQv$ r``EmP q8B jgX]oBPd wr<0[ QCy@0_@# + w xH0B!FUsJ0kBO1g0;aYՙuq)`\$BP0x7t rc&r;l0C@|6E" Q+-F7揍Y>0b'C/k8?S4P3cp8WPD1/>, m\5 ]=e n?i1r3ysw⿪X )::sa/ZWFZp` }Z-5鿣j(F r0[ yP2b Ep0. qd 1!1jC^/?Pֿ'(B @$c,F(L 3 f13f7p_~"Ss @< ` 8Q}EPI;ڐ$^҉ P3"T҈r~zڌFt3my^J*O#^f [f#xcF :' L]Xw#nXvsPx߫蘊wSUnnn-KӤe7Yy5XAw/s):p5,,Q;UC$νRO_eݶu}(JG„Fs/2?mPyYܒݶ*\N8>Cnw̨$T{';[=l(@!0"QJ?`u2/X^HC բ#f".o ywU\ @4eڟvASe|[)\'F3wbqdNF}֠5,(#NUl`vk,mьH0Zݻ_0+>ʬN@Pف'ooRWHͲhE'B yߘk붲jrճ8Lo6e7:=)hrhԧ'0, 7͔aqݶQ.:2*H%A yoEVd+xEG Ive lyEis蒥ƍ8D'nLv>9QPFF}BI =`b[U|(?LJP=TtM )0y y7{KjnyzCPfEg NC )vFϕQ;݅[ =M ԛN9vy"V`̖#,Z&8E}冷QO -VE\ȮX{8ͪ7MSgtǡd (5&twmx X'+JɣC dY;ƹm@F!7 wy)Fy~ d!$gdNZXPW܏؞BLƷSy:Dvjqc/I/}D`wֱc$;=X7\]8%At| >;5m Q??-z+}R*^pzmx̳!xEVm2ӊR5hZ`]0C8BXKwSP=ͣ6BROLVYEnkD z>rLIsTKX i|OXIz&lCڷgXOʂg'[CCs& w?aIܧ  WEM:&49R#;~WI8aF J*סsncij?UKCJn;.ѭ wga˕Yw.${enj+ɣgnMȖ 76\*=*Aky_cKӟG|#p*GpiK/pIB6˾&g7q1 ̗~z\| ;$.ĵ2TXl+Tk6K ʉظI#P7m\~ycOLmAߢ=>*˝'![0@OS@yLgJ^uBt|P_=BM6ơ:FO{%sQ1݋1U3׃C]%yTR~S˩|بjEwߜxA"FNXJU,)1s9 K( cdBMo[U &6,?PqkhpnuWo62m0z0Et(8MfK75sY |{P+ڴƂNu &՗v Ui27qd{s/^W 侲O,jgaLX~)2e$`yL;oX/*ŦnZT,_"F[|8W&4DIa3Sz.4nr2cx'oٝ¿r<:q+.h$8*T7؜|+R<_ 00oĮ?*-zvSmȃ1^tStw"V?H_ϔs_ &?YSL 9ڇ;RP)39 JH&l7_y_=tK -Ȓ,u~kpShRWk5!)Fm_pʩmTHX]oQ(`ŝl?I~ H/LY 0͓OC}d D4M/jֲv씮bblsy`/hWT~W_~0o"K㳮qx3Ch5_k_+sjWЂ|~^FkdnB˝x\|m goWLHf(Q!X2rqjZAߧrM~91"XZ)"'즶(Ir.P9 .6M?%G"[!VɕҒHNow oR_@7|xj(AٔyZbE ._:tϯc/r+/m6ﬕ)[rShwXWKr*wraƛ(USYʟRg0Pe~꿀JGtb7 ˞X1y&pMO6txɄtͶ\ȥ$i48Nja7gURՇލ7qO<ˎ,f(rc`\6|i86`>r%XU0$r| ]Jeq;M6%ړe$ 5'R~%gxiT4b޴?aG\DGpVȉ@ݧxͥ^O"H$g@K3aO}DL=|OA/5*wv?JToD~2Y" N{Ps7>̹JPַ7Ӊt-B`3/NAv⁧9=?{KPe|sL3rwz(\ >'˖O+JÜ 6 .'v䰐*Ԫ͓Koݸ=revy>.$|N2r!"b~JGJtcD]0@z <7+SOX-۴өbuz[M]I&$O.NGQem㸻b>L7JV%kqT.p|׹J4tfI-i|Л J?'`U+5ܥ2(#Oqeͥ9i7ȑ&CN}Q;cj.g"Vj-eUNok@] o<țY㼏-xɾzBh0[XA7ND_Bv5> |{1H$)QKkZ2u60ҽ#?Sh-`KYTQ@݃z>/Te J6JuUR_])Үb;ùC׻[Gb܊3]nGo9 Tw4hUAF깞;džKYjYf5o"AVΟ%/FU%W$\7Fs/W{sܨ/i$p˖&N~ee/և5_(6t%Ӝ WUzMq:w4qFf_p"9ұRVh5/霃I9UMu1}JOT^#LOi KiPex Ċ'3:Ӟfj˭^L!ŏ'kwؽ6d-e&߭DjiUR$R}.C*V&#»'ϻj?NbZ2&(3炟z+G)QDf󺈓PM?=pYvGW~Dbloe(Qg"CVVɖK0]k+M|*_i)f4ljPF6Z Od9bB]b[fx23JtI3&ckIq.=ot3z\7~0-sޘiBfp.LMa+i}4> stream xڌT   54ttww#%% - -!HwJHwwwZ,ւzLIA(ag Waa03123"RQ4N ;[? D`3N b `app23Xygh 3v2v@'D*Q;{G38>hM,<<\orAƶycgK 85@tOZ~Kgg{^&&777Fc'F;G 7%@tt~ P0]#"@\ A@['NP(m6-XY @ ۿMMlm=@s5(!`lkoj 66 ! 0OyN {g'F'~wYLhh nߓslabϤn rpJc!Y\?~;G .&ϸYwl\@GSοd ?F}Whfb,lg8מY~Mٰ[?`'' kDŽ8AdұYN ~09[:]p/pp3sc%@px? Ɂ#yN粩#xl9῾@SĹi;SUͷ„n [#&4[\_ӕ~\qD['}:h 0Fe| qv w4@AMhÓ +F6LJ٘nݒ= ß9e2DGLReM:3ÿ8uG}!G>dYe|7TԎOG }1{֞*NXap*%[~JZQN30y}Y=cښ)'XT)#Gl0nH@P7ϵo"{vwn!"ԸB[U2ڝ%áo6L(D\lP5oht{[,-FE7'#aNV, O'ޏE9m3U4a@3m6*DdC^֥z >dhj +h#ž݄k*S&{+ïD(ZؘFE4ryX/ӱ=ӄIޕ9U-c]}{׮ I"&0]2Kٶ0MP9t\:8+nnWˍ<_: S4XUQ g*JlYd 4c¯ePa溫DeF d!`9+)5ƺc/™_KXKpEP~(SIDB7O#aa.ߴgsRS7<`yR_[[Q"8o$xpd8 z2E|yV b3Qօe᫺( +Nsi) ފÉd)7߳+N{M Wgh3 GzqMv3ΏKS-˸(?@WrP8DTGD2cu,ͧ.VE 2Ni%JJ뇽XUvI>x|jV*8ra.v>%x._3'9|mzӉmmpE;G6ǔohfM"ùZhh-ځ[Kv3ehCJȼP&;.ϲ BM ~wBGd_:<(nK֖X튻VeOҖC.Y"6,g=8o>/%P l9Tݨ&*%=o y|٤~j~TTNbs5St kN}*-Y4bKyso;+v%+ͺJI5DCNUDiX4]8g&͚krp$@n/Y/jP&Ͼ 1'5WbZP<6w_8eV; )d1AHձyP$oόI<-B۔|E.F)#P|5!)B佣AjQ6D'I"E)qEո|8GFr9 ƹY=^!'r+߷c/Y(}1m_:{/muV$7+t:K2F'% 5gթ;|kTvWwOlxŻJ>qZfA PhOmg7]DYb?bf~ nyҷ(tTY }I ='PbW|}Z]6J(]i(gwTn,R %hCܑMBJOjoNdR扗7<'SeP\L|G|=IβXa룏㳇1@^I[hjU$q\m !/K+1Hi]bR6?/& n3v ̏MgZ%[wQ'S8FәoJx foHBJQ'49~tOHQYsa\*LѼ{6AnJ~ dTy:tܛm%!`(o\(t\inTKS񺶾A6or>2֓pEI vF}ce\^W/R R.ЈZ s$=7 Ut Ŗ!|5.cJ5 gm Y#O{Q_@`43f~5+qwi'JǬ ClXw#ƻHVFi)ȥ. K.ަ]>dOKSi퇯ߖB:gmx3[h {c8%. !kgݞA)R:zTQG$(cxC"T~ j ulʴVmd0L6fGTR\il1h~nt5 Y{ xo[XR@ lwjSD\6:ȥįsie'#5oT J V8-w܁<./;x<_ѻd(7,btס r<^I&4G+(n7`IN)>֤IT;r=ۓv^k;l'4r"{z1dk<'1SiF~?JnHaN7CcB,mйq .-_w:-`I̶o^{.)h>"gy>5Ru%d/ 8 ~wj5{ }{IypP<~u90ݎ!r@sbhd.L{17P/ZR_d̜5sU&] }2%pHכ{,eT|K ?|OV߃qѧz̹|-Â~5.72 \IvaN/SޕA1*A!kӵJ@M=bL.}xG0bWLCRn-vsSCCM׫kHˈԒ;@"g!d ה]Y!tF!/3/>k# 1߿kz: "=A%|S #hQˬ-qsCtc0 MLėa_ EeEi,&M߄ϝ3)0o{g8&,ŗTbGeN|wFfZ}?;hV4ݝ1 > ԅ40JscjGB'; /HpZK̕%tMӰ-bQ jPt0 $AnOoBtıD!/o"U`קl?f8p%| S;"?h} BUFF#MYx0|y#3QG5 ¦>{6)j=<tR8H'Q=/ލ3law=E^c"v%CR^j CDYhI cP[sOAsjT1x̋l :NOUXLV>ʤ-V㐔=ޡ~rn}2ޛ"]>^?,V$yMhrtt*bcr`2z/ѫ TG M"Q:& I1{#2@rz Y?ʲ/ˀ?LX&{z 옔Wn9ɑC|̌~ J 3V*~umhK5 ߜ>>/|{@b=h17;%Í#Z5@rnA؍]"g1YZ)L⮰A,R٢h=tP̶*}fnfjDJdGIs1I+ğ헛fvw=bRlʶ[~o_[R d@2>Q4JHLm^ӛ8]31t%Cr=P{9V])i5EυQ3.@I]ǘʬdHۇ7/|(9^ot xU=ܼ^-m_r{=7ޘ}=!ЯTߍ1nD_##QJ؊+/Eaȷž5j-׫3b 3e9R# LN! 5댍Z-Kgj@Tu >}tɱa]]qY+rO $6wL|8ݐRߡ ϨjvMTe `^$ e\GǩyׯW Ǥe!i,J{)63m 'SqH2ץH>'r2ZF(+&Sї~ATAXLE10Rʑ<$fԩ"p~}n7~ #Y0 [v9P{LZYj +4+0mA2|'<'IL!oKWh>/d%XC!Vd#28Q\vvL̝sÅxRpd-xG{2v!,E=&攟+C yWY#< gwG .|Og%.yZB7֘]P2nM{ڢl$t޺mC;P53U;y٩г+=9VkyY㻪IicZw#;f~ߓTCZ)<&GoJȒ3(sPʈP^68; fV?sIzjoJ|;iԂbJWOuK F Ċ[ dE׈:_SHڗ+dr Wz`6X웑UL,;oUX68LZ[Iqi;81MK ־Ycq[)8akTmKofj!&.tSWw1 Um`7VQxl  'qbd$fLJj(]x 9 lиg*꼊ԗ{2<p >xQÿ t@ tEJN)T%q߂}kU`GiLFj i@V%galQ<~v9^5_2]9V4sL I`T-{TH6@C#u O^"x2ў*Un;u r}P$crוP@8%RG'P7' +.V3s6Zz4YĒ 0L_ڱhKa l9BRP-+P(X5nq+՗Yge(U/urrB`x0/{]yY&pm*` +<"\⺚G f @oDѿK꫘mH_>v4Ї71ٜ-4ah a9pNkXPb  t ۾B+r#-O )m}IjcUQSrD>^WtI+ػ#;b  H#-[󽹪>]<ٌΜ*nc̾|l٘ 9DLMraM9$-xJ`_[9wz>=J SObљ)nE[[7L Q|-Z7,p9lR48Kc|{OSkږe0wg @UܐYk)+Oe0 ;*\ DaVJi|9Ll~gJW\_޻Jo,ZF$# Jʙ:XU4- 钬ݳOSEH:Swua~:AbnH-+ɩ3Rx&AS &d#Ya%[94z\f( D~ܜNa5Ta,[Y5i "YeJqՁ壯!Eӷ$[a'xOŹćd XpRmo@aOZP3j_LArefE[g|dڄsbQ1ر}i.T#![R#?2R~ 8'淧{%bhseR2'mv~4'˞DvW8 P|hA髣%f&vcH u5,&րaY6PRNr C6#\d3j[rvF|պ[ZGh k6hz}VJևCnFZSlq}Sb>Wja(PuUSMd%z"z/L}ܗ "-BC'7ކ`a^@#jiܖ1b6WcsPthI<4Ë:vCE~+ŽBi ̀yxʁ2ǨfU5ׅ^ҀsU㾓!i48ݮ4wBK^)47lNf /;$wB'\0V*xyk')ƲJ| 2gf80E'5 4viR 1g.% GMf8 ͒<#m]-o9?E6*o&r.K$b]VbRBJ^bq0}[W%~ fcK ^!fէ({!QMVeN)wPn}1"*"Bkx<n-djԡDL`nz=i_QT?7e[d t"| nYv1&^]wL|!޾-M/4hRS_g(,ƣ5\A2DyzK#J.,Iz^VSi"ѣf FbS]pbC Mr}olzIh[ݹđ i&fן†~hu-)"1iG"ē_ǴY1%=~` 2Fi}A|ىvOD8h#v'vsAS&i=iOk t.*QBY!_Uŧ0]c֗ڳQ <#T1[frp?0ȟb.cpyg |οIM~\Dw?_DۈɬҶ jqkp-Y̬W`@v53GXFMjZXjU k`%@ B$@6 MN,9vYŲp>Nu)`9^*aߜ_'LuپաߙٝR۷#Fʅ&>=%m3#22kI 4%U#^87a J\8f o1~Fdh&;A3K 9qP{p)si~09c+GJC&q[*/NbYnվ,s9tb^}זh;5QMuUU YsesXUtu;H%?_] R!|-Ʈe8_3ޯG}ݤRH7?wqF# 3?W.>!yhF8>ʰL{-q!0&?4];K_KFN pjI{'E҉7zƾS}M K9zUɖ׫gCt}ئޠS {5xh^uk4Mcej \k&hy!OC0v)o%V]o7ٷAÉh-P0>crЌl } P>"+!τ5p5>AUM ~a2#_'~PN,bum,l°u]K;b9Adewht*g4eeHGFWXGL mszͲĻuIS/>ey>:;Gx,J\n N ՟R* E,Εy<@B aoe:c]$MVU#\ |+O- wB5=&TtXGiV!6}k68֮^Q7).O̪<|[@MF=2z3]ވɐp'a+izR%{ܼUx'̩1hpsȱ2aCs ={>aTiuHד=d+TLZUieA+ر /KKU-@fkǦ$= Lp3ahLnC? ;ʗFR>1LR#o pA;s9=ұ-@41iQPLJ"$#o`^tn4xk:hBc/<~#cO)QS[H<Ou3&zP3bn#Ej[,xNOPlN} az+E#RJz{tX^jtg,[xorRy6;FԠ 9x*^tX3ϱ[sJ;MWl6T('Ym]>Jh,cdD,_t7V9mۖ EB~CXC\*MҔ 5D,7iygÅzHCzi|AEbnN]u^XVlNB'bRS۸ueCkpWD+t\%iF5&,H,YDGmfbsOKh>fpwtLbRL]& *߇BG7ڂ#r:"i )G=+ԎG #[f/iTh/teUO!ws)lB!'d4zD3@TaG(fdXRTIH9r8 Gj\2˲U9iUgkH.f&2"ze&^8;6y G=F vI),^h>D4$"Tӭ7w9aNJRTgQh> ,6)ڏIJTهa%fdV[M:jY-ݛ]NOU3'e ^^e}tք-嵙yDcصu6#knnHD6_ml&8>y^Ϣ w RR3ԔUAʚ{fCt[B^+Cq^[I^чvMGjζpĽQ o܂wn&Hl_|vV̆0%Ǜعn'8^|vTMri@3:X@eWCT̾CiE$̱x}3 ^T+]S9CЦWp$1$$.`ͪϢCf¸ԕKD0'fE{%'WQ.O!ޚ~fie$D[YURGGɟ-.DM\3c!1˹P4+r-2z0۳'0yۿ_030ZU͇w6@G=#TU0AQ5]5:FM-!ҚDzw V^5 0"wB qyHp)-8wRQPNZ!Rέ5dX3NvÆ"{tT>/cq>1r8E uѽ/i L[p0 (L5XRz;DtԫabwE~dk XM}|ر&l#ͼ @MG]`BδhG 8Oono6Nu}#[0Νb 7[+L!˻3+MCbuV|I,fvDYG ܤ&p恾]# }Q 3(3)K

l#lgxn;GdR@aZpnllx愈w:%QՇcפ}|$6~ٶ#*|2VoE7{ {[@|jsW@2}<C?+ #G` E0䉏Id{RN~EeJ7(#N'HeڵcaΤn}HdsW5-uȏ df:"G(bЌlR]b`-+Q~S9 9 &*<=ҫU2l*jÆ$A9"rGpnWAo!- ay+ C(zRJtolB@%\\/72}|aEvx_7PMu17a}gGIj%t8,2h![}0o럃6Vr@2sL$KM/*brG/oj#)Uw2Q18]y!9ݹ}}RqxAt_HM\vf9pTi~;Q!kD$|,Lpr|W'/f pҲB89 vLQG$p9FӳR U۳v|Uh}z6o񑇿j`yNɦ@ @<3K5Q1Pp8wͤZY`%O)Z9836+FLbuN'WBD ݵqE"jP77!^?0łq^,Q _(/YNé Y0ȤIO)JV$!%ŽcyɛYk{ΡRKGWڵzʞS꼕2'."iIca>3L>Qp!ibL Ȳ0cHiѯg$`Wَ%z (Q%1N|H $V(|P%B ˨Td=%[XNWbZ]CS벃 *9j5ګAnˡngI<' =S0la(QXȧץsD%rO R RiZj~xC4/Q>hw 9ƹo8j.qská,TccvIǨNxxz{_s5L!g޻p,wg4a$RL&6L]`1vҒm@93D8(@vawM.p;50 17r*G֕(Fy;&"=!;1}fzDL9"L:0iX#tu U?4P殘ċ|X,YօuYkM|ԞffcfYM{4;X:>񯷖J&&d?Fӭkm}e֊UH8UK&j1y8:yB$H]pF^v\tϾRyR{1+MzخJT%@ \1f}Y#sX\3n3*o#ǮztDZI2]1yY+E-'~6*l&rSm<$}(Ȣ~ꔧގr#U'w'Uk]uB[rApՏ'''25  0*{Jn֟F<\sVl uDpZFDov,R[ q,yoj}VEUYz/Cw27O@vkk@HȈȨ g]W=&|x]\oqgk9u0M*}vbMz }5wuY4 Ĭ?NĦ,*W)0a@ s ip 9]bx{h׷% g$̠g|G! W;pǤ^ ~,ˑhZޖ؈d@` 7y, r@?,ϔ:~w.2B‘aD eU kn<6ߋ?P;jl#b;$;R}Y9B\!|F)N^l7\'fNy%$\/Mv F1ae3'Z;\fO2C| `蹦kG=97[y~`WF;]PiZ(Q7"Gwr슰)> .%Ѥ*cUDe ,Ar/讉Mj99)^*=VyR8 #x4c4rnf߲i*cC.@|(,:swEJjB{q$Nfn#gbDh[.FlU<%lQ'{֐UC ?3E<78tф!5eLL|u,bfbP(hk6KPD#fe3D}is;SE=JjOiv6Jl}RIAܺ~W uiC{I1K RX˪` )Llv κӏ F }?Kn\p8ٜScwv0\T#ȠT)s N3CpҼ=hz&+Ϣ7!d%J8s|m5r7ܝA|d+:%ܣ˧Iyεηym_NLaՅ㗉 9df; tx}dRf*gW/VeF1L+H{22܃yL\#Q+>؊ h6 9J% pҍڜ4҃aY`AZ?A"uiZOCID@ʣ3]@U>D>%uncxpUj?WCbFQLGR"+ sG4IkVo [LPd-i,OeH~utBġ@ t\&3Iy] އ,A1Қw;J}ua#OMe R`_>P,I&ojD]Ӌ^ѣVR^Ԭ1anvMA1%> KQ5KX'B ތ=vJvΑ'/XtYݧho}3W?e"nV^\Rfq .9q!r?]ٷo3B$\T49fM3N9j־4xj?Xp`}z3Z(QFdIQ_1̀UN* ecJN55])DHl4:{cdXrKI:f[.FÃӫ / c]y1I10]is]EHQM@6Ȕs̭XxŐYV 'N cbupN]7ݎAQ!xki+p; =_$Xï1q7*?ZxDu2ot?wVp+R9cAY.o .j>nܣO(g@MploHz8n]Boز jB.NR AǵG~ 0o*q kDJrz0mnt Nr.l͛R?(tݴG->k&Җʸ`~8>Su m䏒i{`m2*Z&I)3.HDUoݵ!nTbtK}g͢\9='k/+ iGo -27ާ˫}mT3ٶE)K(! 5\ޒE ^=`Wd(¦=[Lz(t)Be:5~fY(s3+#*͠9&H{F~4(lh]srgro~53 /?)w3jiTo(#MI<p>R~fbY@R2Ƌe%sBH!TV#JOUw3^3wxna0隹3#oƺ5Wd 2J3\yY#o28#O*fjS,>Rzqd{- &46q]d՘Hi{U6%Uv+K%vcohERe^ΐ% ,ALLքE팸Ic.Q_-VQs YbRgxǝ÷$hCPm[5/ߜn\j ^MuJIέz:^9$>{9 Bbv&4=`mR09\MhBқף>-գd φ[FgHHhm^_2EJ endstream endobj 1547 0 obj << /Length1 2281 /Length2 18843 /Length3 0 /Length 20182 /Filter /FlateDecode >> stream xڌPض w'4N]-;'%sOz)Pޕ `ffcdffPSh]@ҋ9M\e&f Y7[ ?μqw9@ `tsprYZgj3 ;3`j{hfb Ps0]Wj~+WWG^&&F;FgKAz t: P4#<@ Xx؂̀.n@g{n<@h?p+og33;G{/%d (I3zL24uqx7q7ٚ] @RD`s1s90l0C7sڻU8h>u/ {sZ0wsdҰ9ec.#8xX@'̊^,qtpXYn@?+7AfS%Ow1~?yg'@}X}n;z1p%DUn*QQO z(S_{ ?žO vSbw,E,>37k+˂z$lmRњ؁lW7WpxT uUV[w I'\jfϪ#ق. 3ѽ*3G}V/N)ao`b8;x;q|Xޯ9 01;X88u&D'Iq7I$K\&?`C&?`C{v?]S/qSCT{>?O{v?]g/zzɳcש2 ߫韕cހ|7qg cK`G󿢿X SD_?2п`dl_OOdwW%W?ż;;/{38?-{7t?"zx7wyc"[xl_/&W+g%W9p_ޓǿ_O5@bKo+GE+ 4_Yt0 nx`88B BS|'2҇'A}+J紭 &[JQA;4SAB8uCNA6m`ݲyNnRkTk9^*fb5bJ)MpH]aiѯŲ\_șTcmQ4k= GFǝfu*l`$)'cbC-?Hr<γ o3Fwq- R5-4;u9Rg3!ɉUGllE?E g,YMԪ!lM:wGI%n顯}LsSa!X{A$ "Yryo"bNlHutJ:]f~c ;}AsqX4!݁U ?tu[QUUuZ=Zכ'pjQM7pLa+~QڻYjnm>@q7@_[ˤ2n%~9ǹC{'0Kn'?׽rP s2IcE?tmʽ[5iͯ;NSk2Zs\6+INFLfֱ*~xgviY6?qAIY[OyIW jvdS%kb r*--6cki}!GhGw;D¨+f!VE<~ q>E$N=cn3EO 7>(ԭ 4Ĝ"mȒ+$z9.>Hc' §‹E>_(Ks /]`k:V^;S_c,*95 l~)jn 8W>Ԛ-Gy[%M$t%7>ڐϥ:C׊^mlnQlxKmc/QGf˼#ꀠ݅ J>qjF&[nMh:.`? @6:6YGJ=eR% |نOT>N4ɽ7{qYy_T;d-?#AnZH8t2iAsY%׶&?4aSwMX/ͤ74tx@^t*:Ga?!(qQ!~=Q6}l8uj\M~DQvnܤyIh<rZExM]Y_:h?6׿pvGC1oOeCeg\. 9aģn_1V|l޴Wz^4/*̥>xQ}dsh QW|D͑kah0s.{rX}4l~kӃcȖl \pՓ-SȀ5Td#tȩo%_CĚQv>&M\rXaA렮mI-\Ԟ1kBd( zf RT2'Ze)Ch˃LGHwl VTk,F$vXRV@qRՑp֢QRc1[*KU' X22@qeD4U/#=-tqS_ʕ\JvpHLQAqֳJMQ7'\w#>ƞAGuF 2_]#/3#8(r=Ll o3Ȑs('bW=U8 $wY̩CK@E #-ڎVPoAGSE)J_uW5/j YidU0O8cSfګFRhi4 \IBNK&_`xk"K|$cmxDYjOUpəӗ تNdK}w.Hc..,=mYnfS&"P:v0'S }|lWt8 Z k#y:P}9džr@B"uоl!kF {;NrffJ5ax\AqO 1HZȥlFlFMTJ萕)̣Ig Zk')DO VdYx`;U#Kgkpc̒ck&مI2Tx?9S_;Ki@6[M֢?/tυ DûGw z]2EUwKV~':Էq e9c)6-*k57y|bQ!2ڮQ'R"US-{IpZ-IgC?oK\O'0Ѱ[ھnAq/_}~z~F1;k LX T)9p%HBUAJO&lRjB1In2ŷHlYN>xZhG#9"れOL|5(@&](BV]›yKRtS}[k>ybNօ1Ojjc 8L4ۃhٲLA]A7Vƛ萔V7ii@,ă0'Ihq4#|Wj$۷LTyosF,;5<^QQgDS˯P<2^'nIْCLt.eHI"5<إS'wvrkqn:!AMP8^VNȞ mU&7W7Ϋ0*VˈM2F cbҙH,ky9*/ _&Blo oc7@@Ə yݛAR-Z.kAmIb{@a?KlM2#`Gmŝr:BLQ?$RGΖL{SsnS$ZmԦҊ<'E2&obYFsH#d;@}K<,֡>°Kjک}@ʨr4k+]#"MY*܊06T'e9 q12//(ʭV:lUaY2 tEjה&lV%X$ c`w~b  !|v=AQ:xd1PzZYǂn?U˶/B4$Ϸ˗9\{ƈzUh11uZX7iTr."і{'N=>_%labܹq>rySq]-3&tOn>E,~Xp Ju$+]`=(1;)y6$u5`T'=#/N"K^VjJFX;F}&Cl@<'k\,|rs@ }jm L'z)6fRVUzAn YBꧢIXјndIӟ )7ؐڹi2I"ØDھPT';x3/mj! qžx")#'ErY '{y}Q'QkܔfWUӸ_.kG^Ɔ<'^`O꜏X=D7!/ojtd/Me5JK, R&ڦ0_${C4:M5>׷&> GDlt)f7;*T 8 Ҋ'=|1B c*(w&<]j@LX2O&M=cX:1ˆU$S İaZq*̓F2g9^l J2,Ib=-M=Zp86ޚ*Γ+b)IN8$KF9]E`q|½#b+1WrGьr;O`>б{-}܄ʎ]!n| WE`9D"Iq)o3'99u}G /[u951/$מdxc9?Y(3k@@2G}M:וO8}JnC6<͢4 {yXG~LySM7-L?0cГmORYѤ9"6~þ}^B<懘3ϺkB3TH?0wdz!}4}Uq}֫ݪ@GN<|(Q8|$${)ZSc/*g}I>ݠ5(Xsw)1{KbP63)(3ғVW) &d"m/W<9 xFpW@06sgtKҫ/~mV%v{0bz1zq "jIb 0*[_N\8w\gevڨΧO"g)Kms7,դe An(Rw^^UG5W~iÄ';j4ln `T2~ \Sؿѯ;RAb`1P}?NznDIjJ.s)‘r:afR&_+*ٹHx\Nޝ rD0<חκԕ# ˝`&iVK6 =taHW R>mt&L˒w aE|J=; %m\beMc|eRa@cy;¸T<oyO]E^d*%pXFUP9.@ǠUrUЧf>x9JUiw4b֙4w-@'0AViE-WKlŜUQز$RA푝7dP3 #u7"h`rs_^w~knc_,yn[4Z -ʔ.$qy9`D2(֓mg?ǮH5t10YI lgq2 Z-7ᔔߌۊQyWQ{pYvȺJnV8:cN&Ţ[ jxabä:zNYW&yڙ]N6 >490ysėq32r,n16yHc-gEI.XېS+9Y.7R| r!0TG.  gY͂7mv6-!o;8>4vز #{%q*ݦw*.WyۙvY_iAv+b xvde \ʪ$i(ܥs[ A85DLQ6KWo[`:ޅHX7E@lA*bjxF2ߠLf-؏fk0.QzR8jLkz4Ax~T0ʉџsL|͔iFF_DSH:Z\P[Ssj46un̊?8w_*>~s_{#{~_;'I>0?8FUF1 O\4s"-9ߔ`DƇ:z{ݨW_Y}Btwجy+~&uGϢ,;VR#A @Ate閬q < Jyr5{ud /XVhpܔ!&c~c>..Meʍy/Cu2 퓼x8CϷ"$ fCj;0,uf|qAjRS gW3O55 \/ j@ uJѼu|pʎCȱs. ~]TQ߬OSScK9]++?YiɰTWmLfKɣtQ!P43^ Rǣppykb;xijs}*/02-dRUc"hߠH5ZrF6K:ZUS3mW$mi;N]U9Ս'd#dz3'5\b-_s3'+D^L.oΰ@'/f4'Qy-r OG]0rY=sC3\/* 7W]RM6ky7(0 @k 80HBAf=sOI_<klˉZpj끒 ]3%qqB~V#r;Ehtvz/g$Ov8f=-kP1tF(s)S3d~ ̗/O-_{ڲιhQ'6]VYmeJ,3js\oÂx.h%n #sɸpv]J5)L 2bR[wH i?%qRM)kwU(sR=Q>5Bv𕘅uY7Q'ԳԵ\fz<r5O,dzCSE&J^r}$Vؒ+dK"xtu n\Ξp.ZwU34Id܇ Oc> WZ@D.|Q0Cs8C}FjU$#/NeS`uvᓠ `G\hLt).(.~k"4شDܭ.v!d0#x 5d1!Y|^J="ѷBeSi{~6]hyiTHT5m}lHt@9舒WJMdE-tOL&<+i ]~PStdUkC]+7hktIP_^j+׎uVSձS41vEZ`#[F^9'ΦTv Zڼh^ ɏbiԪ % l7N<]@Z4&BZ 3O͎S#O+Uܽ"`<:IEC;dq' 8Ȉ s%aVS@[Q56絛jDEF*@> No&u%~(XʳXPJtK~v}͊`{}VRC?m1m[^09NDe tX!cQ%hq6gF۸~qdط}U:p)D =q95:5Ϊ 5M8ppb#دkmmN<6L~lVV)M'X{QE |\Yg:wɄ[zV[r#C[\l|/vB#BEaeEI<9*aaYy|n7GFaY6K';Òۧfr;[yfw^#sߝ>Dw:جq@ %8,BU&#Q^].!_j9/#%+0u8txplɝ} PG h O߅&N~!^U{1ϙt^jubm=l_i/^Q[쉷+殊W42!-a60hF',`C+OҟCvPle.yIc) ʖv3䀨@"%DpȡV|f7^BZ`BsDU"\ 2.5y!=]9J3vWR<\gxuUVչoWK F'-M'3? gUV4NqXNV'HbjʤCpkg[谨3SҾYp `|k?X)|kBEW9p5>s׃:+AE.:GV%XL̮.V Ipy/㤍73nlUi~Y;frqd -R"F4Ȧjoqa'!d%Byd֦)PLY( q|.&"ޛ"-ӆrYXbnU[m&_]˞ o"o+]d(O5}5\1~%ahscVMT" 4wPBR`cBXc( |5xMǃ 8?5D`=ߔj8ȯPg1|Fzp<}-ךrE°V?3l/Tnfb]8hv;zŶ[Mϭw]@hyb=`@MJ~?n:+LoB59:4ip \i}ŷ{jݶeo6`l#TEXO4 !9Du ou< A=ſV'=ANS"L GMA)ZOgL5dh&uFF <yPq*J ߟƽH>u=K_˳{9 8O^%69UN&sيFn:kd#.1(2v0.᧨8|EF[z.Mu2AC Ģ6\hd6jw@22sƁZcg 6p7o϶3$ 阶 UtŲBtxdWG2v π$e%c&hF.1eVe6Ϩ~X}_ꉨP6M*@ W TicS* Փ: B.Ϳe7;9A&۫gkSɾCBړfR+6+ü^ώF{D-@= elJ1CѠ!Yl~tl#PzjWa<Ю}o&C >bjr[٭xK4 kZafy- 3^iG=DkfbAܩвizdvn5*kgQݎ4={_{(ބ(A%''F}`ET{R9o Oˏ>ѸE {9b΄ZT&qR=L A|/PFht eXK$<}-]HKVӞGp׃NAahj: eWԫ7z2i. GGV!-/sST0/g@›.IL:Bi<rqFfߊ<]3eˌHx4q\3q ==vH+Y@'sϜ9x%:A2*} Ȣ>QH\z(u3BO< eCC[o_OO:|}y{4ѹ rcLnցu{2JNҽD|^M:Zbu:aHpߖ^#лCHE*zU)b>%)nL` U )+n=BZ9 $qzG6XWvc$zFpz ?qޭmg  trȋyQj)a:Q9LJ 6ے9OH|w_wեߐf~r;Ä̡{pAjsry!1+f5Á-T8~J45ѣE>liI:(_L[FtF=ȳ&&f<^wL~h3gFZ~ Y%oBVۺZO]%m6ѯErqKu4X!A$ G3AȂsRz`Ha{`fsyXB8[逋 oYˣ.#J_bm^[G:u| Uղ8{NLg$BDB#H.7noGp+tEe?xCM066AK!Oo#iH-1=D eQ= !zv\?+zVeς>޾IJfSy`kU!blӍm{}B$p)tQ\pq֪@]߆Fѻ_uFwH^Vß̃7Q(>*TyoIQ~ nH5`^[2WK.G%F>Tx}>zmoJF7_'/pIF"5E9q+D-TU.=oEEeV/3 bȃ˥N*r@Yj'Tl"Ik$4Ɇ{ kolv>6;d—IH_ĵ 9ֲxV{.v:`ro^rpl)'lu_+N+@7yF_n~ ZvJMl$WVoFj~%8Kp–n.G,1=8%W/D ŵ>C2J 7љ797Oa)~8W P2Ex>%o:,(>%;Ca7̚\'5"%'%\~)b0vvA!_1tݚ?c:X+HnTgl lVX=@(HX[ rk3Ģ81'L<~ie$1!jJ9c&FV\`*aQ2r[3fNVw AE?7B̐ɲׂFLUJ,|kժ* V߬HV}#B#ieewFcbIE zsw_XG;4|~tu G@bPx A).ʼPw]hޟp;1)C9\z)?3G^/Ԣ(w5QO1_zrqu*7 % Vɓ@B2%Rc${'1Iͻ2!{ C!G;t+zq< հ.mA7qr^ i g[TLLVT)G+_[$˯ri3PI׶Vy24Z b7M!}1\>^hkZˮ[eY~q+$)6s5Nl'uWa58ZpO 0PѢ=&wXݸ^޿fr,q㍇&60]!puj-*f? =_ȠRi3a٫Vgŋ~x0/(LZx GvJwALWfX>GBB3haTVdy~'S>To)1 q${\6EEO̰jWd;Z3J#hGFp„Ӛ{EqD dܚ%m *~UI#aBP)dMI/ ܐ̎*M> <P8$\qtΝ07@ ]py{j0lp .@m~WIV!Qrt\J-V6?MA/jcA+ā_7C$ȍeax|cŽo& Lf&"22jS֚+Cw#*+מvz^,:4YKf֮Oqae<߼+;CLzt_1͠N ~ȋYHJapfۑ)?FKSvg7msP6V&G#qCCs nm`6{LDeNf-l͂?R# 1#8 ;tZfA[oSC#UJ,{⣫Tt /trCqrK%ͽ# B:.'UL~W< W$IrjGLnl%~Y (]FI`-ΞPOr;R|#Rd&l_YC6H:`|)H3H;3#2 a ȘpwڮI Fq2pSDOmظO n &BηNAF\:@q]u0u.aqĺZ@ʕYzW<5Wĸ 0TϦNrФQMh>+p9Fh B$#_tLrv`qsiq'8/8QWzK$AsN%V(sX,zoEij .9#t"1abRf=:0G̳x¹6(PTE ` Py;! u8ݦ ~|}j Rct`tdtپX̴ ($(FI.L\U,ޤA9:=LQ#%P~cT&aCٲY)`gl@Ez2ɽV;DE..$颀|m|.3hr6<+bFNpǏGx׳5'ԴPvT/#Scׇ#_R¶ 2铗4L~$;L{nC1VJ8f^Mm|0?~1Ig9M%"t~1ݩNBrv |sn!"xCo& sJ븏`>Yu"u+JU ?xVJog)Җ &*gry R^Gd%Md@@=4kȧa;U}%;,*qi.B;y\ hȳR}3ǵwiB/T#Y?z;1̽JAR9a` tՒ)35eל&ª"(e 1ԭm>qd&*:3]k df e,9xD>rD7v|, kcS`тΨnNH ʉ QRbu6*W<'֙xORՍqkW9񕆣C뮨-̣6죀7M@-\: n9P{#"])$Or3~_0+˳}!L/N\?^ Wm9:cG'XN@M#"6݁Zh6ݝU7ϡAy2}ȸR ]YfύBj2 0;rR O\φRzvM!=t AE}r<}Fxc`'%Л.Y$QUr ,'~ ,%4pbM }?ǎwÜEjOOā1a1Q_hE|ͤ Lbek` ʑ5uv{LO; G9LBj _ĿPw1lVٚUisHq5Ee%_Yq@Kfn8dq]3feTkÎ^WDu(^mJ$W3fQhm Y2t]ayF-}#SlLz,B~ñdQ/{ګ،nKl @qV}l:ŤAYȋg &QZkC~DJsB0 b[5Eh:Qnj6w4GiRڈe?OB^wEwd 4 :8(U.gG P!: r:NT5/@?5 |q1vkdynw(GO ouVd׏@:²]_=@@3*^h>='SZmk Q͔HDqX$RFxo;9E l{#ci7z,)nw4dimI s[N`_8O:*;>#..:,1k! 87{4ϔZg4w @ GH0F>%QRjFŵjQ**A?o3{}%-Nlu v/ff< i\4R59Tј+jcɉs;1 endstream endobj 1549 0 obj << /Length1 2134 /Length2 17074 /Length3 0 /Length 18340 /Filter /FlateDecode >> stream xڌP]]!kpkpK\>^սEos R"eZAc[C-#@XVYLGJbd9*ֆ/ aӇLP l`d0q1s108ց bbn HHmM͜>#ˆN/w5 kdhd`P52:YXhO}"@swZغxӆWs{gl>Dpd@'+;'h@/%?=l&mM< \'gߊMpcs#'!O1qn-c0' 3rc+USOU ٺ2 r##Ƞ>2( #_Ao?_1gGo_/4c-˿/1?񾠷 ?ڰ7/GvGGQ_Qӟ?99:J\mr//v ?»u{i#ߩ69;8||YX}ƀ@7꒭wE]PC + Mځ(ˑb0-sA`ǝOgL͖ ^\ &4^3xe~Hwwk3b^( Sb_.fT4&oI6 )Y%T+8%F`<_1}puoh|7N./ WZ0Oz'GpOa8O-y0s#qsހ>(CIkԮ./| ;/kycXZIFF[&IحN3(e?jFr )AR%z\pƕ, 2Va۸{w@g+|=^pyT_D&B|DTf/FQbCw&D*Zazn\SvYC!q⧁!Y$g[{+!:Ú6o;J}ȧC@5jmW g{fS燋 [s`a P_V.# %l6+H,smvvE\,ʖVs9޾\<sDu(pv!Bs:_6~<Ga{;?&>f[XB8Ratr<Ǐ<|'x5vĜzv [uGyڤ죩&͌ϤO=yU2;=*hR]$ŸF]>V7/L=mazk|-u0Sty%Յ{sn택! /8(L 72T[v7ESÝ0GNjHN%LU9#?3V% \0]Z9mLmN ʥ#f20VԀNܫŐc3p+{0#AM5qI}(Hqq6 ż-XX%Gx:j#Ȧf<9uâJbpXxYXMSHBtI (iX:a_sBT`1Kp-8TcĶW2"YT!: |=ڵQZK -0@)Mbe\ׂ{aOleMKJ^mSb{[=d1'^+ #k}|곣A33x-%U[JR'رRe ̀{"Ow&b"!5c F&-%fߪܴj+-o]%K,ƷD3RjHNG8[TqďfX|WdW盂Js\ɇ,YfUY˴jzUZ: 3<>`ߣ j,#\+phm/* kɍ~?&-_ ũ__z@-ΙE{>gu#(TP(~?OJP(<ڍk.H(8fT'ٹ,UvT:W'Jq ǞX(瀽FFIOтb~ qJ׊l!-9" X(: O|thŌpeʷFhn/8++a:$8D IA8aYCWQV0#1i$%]^} ng+UT8OQTҹ 2uY-هTu# }Ż.؇7 :*C P$RPlVnĽ۾ʉdžm"[) Dѣ9HSqhG7d;5O7)j6!-7rAj, 0q鬛;?B3R J"+$(⚎j92Ԫ~x;17ʹyk=SKFM}MPV̓G /Τ0-8dԉz,0z!Nkϭ/#3իf󋭤I\jهD0b[!Z){M|1{(&$ȹQ-ٸ`jR跹DNȊ`;fd?z1FEnk܇iFx:˔Ir WyuIFKNSF^A{1^HKªm7wn.~`_̎IqŎRTTPfe#֛RXjPeg]yt>%Wט^RؑΞ?7 Mnb2øW'pوǓLog D׷442Vqr/i %EF-hi-9'C\97\ + 3bID[ڐ?NU})x5LP6:Wh-ϩAy)ȠN.ȓ qn$y6ll7Kn0&_tEYqhEsTvz2`'W4`Np DٗJ|G虰 tE傭eNKmMsh -~yf~H_^dFx iYԴNf&]hԟpaHw\^xĦ%m{ZiXT;aG9mO0 ԤaDm(צ퐺zK2` ]WJ?iHy%s18 :$*&W{y.`;70%t\d,C]kyck˜ ,ě\-]UYSͣ#W$^7*҈@¶9& dJZ*rxrIs'JHdNbϕd^P Qix.ڊ{BV UEGI+/̏ D2yT)4zM @N }AJâ15eQhiUlܿ˿/U_NGE=TLC(A1ab!{ cnǁaHǞ@Q]ʧIq6V~aK6cM1lVө$u]1P= Q.gڠpmtgVWi,a l^Qr;XazVyZvvEInP9PtP-&=^M. 5ߘ{F;3 2ڣI<؈[>Ʃs9esri-nʣZiSq#)ç,{z&Syucx|_s<:D~Csd|=1cǚt W&v>1:\!2L@k_g)I$:ldO6AWk'ǔޱļ^2}jF?;&nJa%JpsU8b8{ uЧ8M6_fQ$>z%k6uHS'slld)q3%k.{Q`}WѦtw}RZ 5f|"=|ߜڄltu*YO_kWTUu<ә㯰o+=nUn5B"Mtlچc'݉PQ-X@88R"W?waN_ͲG*6vvr c_SD'D3EB˝ގڣdvH:;H@~|o!jx䗭3m*eu5-riyӤvQɡR+Ni7ь .Cu_yHl*®;o;^ݴ N>NChN9͈8F6P zc@#^ &KEaғ,6f{ɮyB?7΄-lMBz| {%;`U@SYlG[Ƃ ׍$R+sijOEG?(E~v|q3oIp8ɆeXOs+|?,*TT]e@URfIgZo>}L>!( 趇uUBoBp~jR+hlÂOL!y*RWN:rqh4#/ ~{QW\-w y7ȶ9õΈke7Ԑ*=uB[e/.)]QZ"Y-NyڎiX7g2xAbK zE'7mܝV}bi߯TM'B\at8У utA=!Qu(i%uKx]W`Kd'02ϡ"v#)DY<^*_#6%n9PMԮxe-簒urVXUf akϏS0ÞAmkf)[|?ya'ᏑL<{ݴgb(GdKB7V9#CZ3}.&Q:Yfy";X%8=Lb L i6#XH?֦o'm t: ;=kDiڋܘBnd7”rcv9V6Ln?YM_L =6џB:$xTIRYV-OT5+{])/!johֲ`邶7a`h-쓍³N~~ [G&i:j7SY1"p\Yx70ۺ2LsZ4fDAE?U1)αV+9̆uњv2IY q%}~<;=ҥQEy|g/P`}$n(v CI; < m+}~ hTX{UJoo:Pf~IK% L`DŽ}{g#TqXoY&%Ú_h'* 8% ',M]NfFg<5]:(*-qc CLr^6[Z 呴~d f3n˕fv=Nv}֓,}ajpG2F} fF{p<|4]8Bqӽ'U1" 7~q-Tdu7U #^MF( DXS1#ѡlW PA#2ZӖg\0J̇;Zc_TjzՍB!.dsBY-U|QXx[yP'7i V7Rvo2 Nn#3v HCPŴҨoG Vڀ) !uRvݐVH{ǶjWU[Glh'{^?kN5ۺ{Mf4b{ۃ_"K K״Mt%$W)IJb0KȪ_>G_!bqJnGHi6E{3BYVd^nf Sf^ -=V'^dgYcvg$>ظB ]#] YV@m8$aZQ]Ltf5SSw|  A)9L?^WzH঵-m\-^92} Sg**)0+ވc,n{hf3gЃT^X?\pny3mL-țc`ԕʬL̚׫_in[ !!-} UUg YͲ @ $Wyhv1gʌ;A{K&s0J.jTd=V)*!mk֍!"'tUFV5$2k[\.p%Js܂+Eւ7>J "p|[Lu:|W+8 %gYk(v4sﶥKV*0xXU̻([U}b(WS1tάO piPs"}DEfqDw}&7X6m<SZsaAѕrPG:TDAm8ݕwG)(jbwυx#7S%~5бӫJ sƻeP㨙kDX>o3 >hߡ;N n~UM/7&mJ|81g$b IKz`q{bVI_ ǝFPD7~DU{W]Zo̹ZXTJ1O06s%"P /O谙)0 #,Eӧ75zGegq 翚\o~v>=!dS\E+?Xqi7.ypݿg Q8f;xqS>w^FϑbDRxl"EAmF[b,ϸv7*imZH;cCR>^$B*+h AMf}*':(=`k ;dZMRKT_nR^BMH3zx񳒄~wC퓪.}lCB[d#16 SW$Vϣ;F}tb]ߠO*o/A;MjFj꣕Cĕ<\u SjXR7:JP?J޸=N1 9^2Y'.w"FyD}@瑀f.OJ%s':.! 17.m E V(do})'s1Xԅ[PgEGqRƮ`|`[ixZ/]Ȯ_p=oEOjTIsxP ɨžp#PՑ;Y>_ 4s ]2HConTKzr %}yPjl%[J-nLeL{90)kl;x:^g¤doe Yu [.潞٥}7K њn;Q!=AKflߨ;2>Ϗj6$eM8!o TorVjص2Wcq˫Qő#&x)w;R\RN*ס+;o ފ0^&8pL(:s[HrR]b#l&)8\NS#9 C.Aw?iW3E60#_bI)B ۚv넆J)*mReS ^х.XT};kO ^S7V4SčtS<gq~w::?AZۺ5*U!nIV -.ҿZL-ɋXbi`B=k2WP}Ns yVɫ^)Xhe@<Ѯi3~`25bŦVoڈ*^Lk3(ƖMQ)iz8RV.몍zk"1O¾Z-&w"ɩdahΝ5uTKPBiҰIID "Gy8\ ;iiFd 0n86LmR,Zt{O-ZN,^<^retn/H] Q {e)=) rma]gI@>7ú&fuWaĻ]>)TtRSFTG9ҩPN" 6P?3N 0s@.>Vt ;&IVmT\= 9`hU4GG wT(LU)*z\ ;o`H. _D, CZT7$.PkW~e[Ee~O \lCOk'GʀWwuf@Bu8:`kK:I2'#%HaDhsvk*FSQ` ƹ{ =Lj/ߎ؈LvCT~ׅSTx˯3;|){CϚ S'q:ȉ<|E4Ջ$㦅Ap(< ;,tuee!y0=P仭̩rFedJۯ8FFQ\ c sMPu\9WQ-*k6,fA9cBn՛=Ц>)ЗWw塎6( mUCAg/0ߦjK6->EBccsxL[L7xRBA )%w3"uaxTas,ωWΪsPժN,bm7q]Ѵ#K94)Yfa9oٌ-V&(>{=lWTJPJPuOqw!}JZlTPiOpVig׉AD*xߵce4B+-Vl <&}S$RYmDPfK:&hPym'Jtc=JG:I'߽~~#COHlLi)`oW˰wJIwcnv5>V0fhUYWNE5x`i <ռ͚;F^!'iab#3-WݮU,i1>W),3<<ǰqr%ɫ_=Xp4wА+NU8n7pG@[I#=8HenT]f;UkM;/S_w>#Gmt&d S 9Q9$L_o>t;o'< ]?4ǥu1Ps#*w`JvJfHm``ȓ1O'uѭb#a_s㵲+VVz翰YXh$EV0ހ,@~]DUڃTAe٦ݳ6&һl'[a^"P\ lB>Q,sÐV!NU9EG4[kۿ(6NBM5L_fLl5GVNH&7!/z A-ɭ8^}7w@-GFɹdݗ0m-h<: .Z:8axboh1f9 4 A$8׮c(\,>I0_ bj;nO>[Y/Yng]4TBM^[3\_/bE.~^q7&ѣe%v1Q@",dù8d>;a |AӶ1^_-T[?[W<'|r y̒s5 W#K!Ro(8]=AOAʄeud{;*/J$ RYgDϋz!DI5y5o!#W_^: > $dm~5Fg!> 3@q߀L3 Te]e&x@/jB #hh?oI ."$3?bahN6c`)J?vJ8~ ^UR${3'R;L7/)~uoBK^FUX]a-04N6vhnuuP'JQZ(`~XA] Sg#lag؍~n90ԓ9\{>"a.o ֳgˆ0!k欎#O;ɾuCyoٽ)}n]ll)YwR\y>H =5)&WBvF|WEË3\|9D2ӵK7ȷ6S'ytG<ܕci5 7KFF[G^nT쮵OAz}9ZCF}g*rxIl;Xū(5|K7f ZsbX❪UrRPPkno& u_ EzONIJO-اq+wZA`#@FT4H7BC/1#i tvS!rvte Zw֊cf5S`%V5JqcP,!`R\o;zo~+s`ݏߗ {EX5T$)﵋deH9 =qwSh_5~#cArAAU\ F]UgnZj[QGbfD..ME{n>F6$ۿ_uOY/a ],Ylyw4Lz;9eQ ziyF%Og6 dJ1EOxnFb!fx)Q@7&6̾FAǷ\nOmX<.Z="`G1df4&*S[_ qr\BNW[|_ gOt!Q:rX/*uQA(sdfAzIt,m d0)iKq&;\!=/wiAV>rp7۵TBIzA+4v8.%.,5SKjU5>^ؾD]I@VbX撤91Ḙ `VG)>t:uvev~XB7&9fWd{ڴk 1:`~g͂u,K2Bd18=3jBKZÔRlKL~3h.<_FmC!h%vLyB&|_{=4"yy1!w8k0ɞAm~|cm&{4 pSXbqgՈ/'g8$ D k!Fi4$@wZOZ4i@>tţ*~b .-4ԏoޒ<BOU^~*$ʚ\7p4y^C٨-w\55,]t, rix8>OkpJ|Lm+!4HVsgMQԉq*tpݗ(9o꜇d6jJuxٽOP?-ѺآB" rnwiA60э5}er@bhˆ=9d$`cJ׆^68'_WEM.NtDaVl q\)*$-g4pɸPx#,=ibd ۝oyj*;Y̖9-o[PwKQ\QOC2 ȗWhouzESۓ LKĚڨQ.7 ! &U~XeA.jgfc9E;K?;!wI3MZ*I8¼ 's Y<](}X}/*"hVJjWAMSRݗl|g uk78թ 2JK Y޽!'lQa9w폙4 XޒetH6"(.~M/^պJԇ]d5BcW#Ũ)?Z|h*)rLKqєX?=%c+i,mxzx<Qm(I9'6MIblX L @pt5F.j܀UYJhOKyR7߮VDpv rS}8"fg2\Muy+N#_ BW55+uk9RHradE"<~+|ݸb],Gocj`|wɸΥ]`%t$N>tG2B}r[wъ,B!>u 5`@ 7qҵTp bEjQʮN˽9Z#cA i7 [(_Xy{NFն_W"֘P'D#Y&_˛f"*-lcxX41;ZsgM6}ây5T \bVUH*rcIH*| qWf:e^nW#ʄj 㸒LrI,x[n/ol Jo+YaSFPx`"MV~fcv㞐[4ǵ1<o9d]O%v6jC}-:W{˜ܡʠb#^+_>$3/A<YyOgBsb]o>QȮU_k˘"-U#KePgp.c.L13_AŸ 1G\RW"dkebO tcSl$?,^pܸ)c,7>RA8\v7']=&dȎ|fKbՖk$jܩu ̭ En2 />q^PbZ57 DJF4g!CJf%]ۃ^$HZ<(v"k^L&]0QM yAe @clTmm|Rg#nb/f޳rٸf]a]̉ pDCվ!32EVMLu.M/@D)0SVemW aZ nxѲkQBPt͘d;!fK53dp>BG'gKzXXvub n^ՐI0bNƁIxì`-c5gm8n?u2{ӂÜ?"_qyScs| N k.M9 6 j5n#0X[lBbL: VkJ @MMK֌ 4KӾ5iV( Zz]opY]: C!PCKJ= <# oI4n@bt: đG endstream endobj 1551 0 obj << /Length1 2061 /Length2 12731 /Length3 0 /Length 13974 /Filter /FlateDecode >> stream xڍeT[@p n wݵw'[p. w.!圙9̽?b]_TQAl :102DTdUUYl̬ 'ko :Gh&j*H;[X,,\Vff8xF. S#@l tD۹;-^wW p dbd 3rڼhbd PN/+##\ r(.@S_F61"PT-@2͜\k 5x"% PY_t+`#;`eܜF9Y;_\@FƯoRjBG##/Ly=h1[S DA@דwg[ق]m=/)vLj {g追^~ܯhX0o#_˯:=vW)@o  ߄08 [_f.pt_?^lkͤ$("I`7'+3 xw"E#п #T W]60@u9M^?XW&qgk=yـN ~ uk倦 gJ9kk30sk(r*L,n-5v ["U``af묙X^' :J c98#06+u8Mn3xU 0; h99LB-8L¿ $xLb+I7~7I7)C&ozx^w7M9ӫ?JwoNd0A@.Zg_EY:W!:Lk:_}__._ m~u}c1ƿtݥ^!Ud^vr*|p|7Wۛ8;8 ^g?{t ,́M>Y~j"pecʩvLŽe +kUBsŝ)8l!P- K j#%XA[3q"eZ"*`,_[}{XⲼ x9 >J3̖!Ɉ]wTڈ7s߄9|g%jhpvv[t|/BwA_0x C߁K -ܛX(*>w2z%g*0>Cw)BgGWѠ$i6ThjĐ|&[>vpyq cq8}z"%. * fY0tf8m'3gǷW'pgr]{ồ\ [ ́ _t$їīMz'"NJ6#F!=[8֪YFEﶧNYKrͭFÌ VW!aǢo?6зrW^RT8.I{BqŦ5Qa.Dx@czuN^Az=6x_ڻ+!Y &1cepЩ:"TF˓ v )L9f6#(:Ӧ+?lQGB1/jU>ӞH+ٝ'/ŅrФ5;H;Vt>y Yn b<۳PςaM=d9պܮ WBMd"E/7bAޏ4wՆ6XPRjCJPg38H@~+Uf$^PMĝ?\;DBEL?PU 'HLiy|هv_ܖZ䆗!o-;(y;E uqFbUҨu)ܳ5(Esŧ iqzu{od+Ly&nē ;O7?m]sdqPT^>0;"]$ uXӓ恞"cms/A~kd'Ɂ\WdEEl.cr,]{'(%毗V KÏFBeqĒGR[TYhS' vrE(ǍqSչ=)߱!Wѿ{mִm7tV 4}nݭGXoѽ6No8z^zCNX0&pYHEefTUEHZ%COhU-q߾C0[g +oo*s'pejy{ T.K ރ YޚC5SzE] T#tcI^1.6|s8SlȁWM!Ȍ K\d7Q'V(U>'Yޏlj(='ulüH)ؑ&lPl5Mo87l%*#|>K0R3mZ8*D>v,( ^W o? v\ `vW)_!~t9jH!nSo֍GDCih2ri0.Me&:c0}m='ze-tis5u,-|>qpM~!Xf~yroSzCKlbK. !v36xis1<Z3b!̔JRFC<:`ȼB l>D4`-^Ko1K0&fcokOe\En{6>LXKz9F %N'&vP.@Ԯ:P)|V"0"zx8\j}$H!S2Ba fˠgT-d?z!\Q#t X$=% $wyhꟑ>AՠђJ'1U4h!ȝ0Ws ]s(8Rjky[j14ݒ/Lhgqq'AGpDpF]ah)'P[Mf\ɄO cq6Doyu=] Mo<:gvn,pM LA٘5Z%gtpH/Vo}9|[W|?DFKY, eI2pG5igpnY zǺO(^_"Aɗw! 30ѐl[FO0Zq';yaC/fsLG}j6{̃YDEqSIԗ$gnWGQ 63ѕ &p3hq|[ZG,gFȝx66 oe:X_Y9WWdΠL"/tYM7Φ7\Si`t .jtZ.6,s˃Rn| kьG~y_? L }P}3So<&R/L w>Ju+a\S0[t~B w ;"Y\@@^*Vlcb-I xP=輾#d ETԜ#:~ #.O]Z3E>,Cr{DX6U/sdz9G=Lo耭F2uqsx1U}Ωα3x}aSXvK>Y5LԭsjZ|qMC=R'`?fi|-TV1B|L!-/U?SD'צ$FSa`BO0Lyb>|5褽ԥyW.b $hD8<CqljWE;G RN&wCjs̽u?׹Tla=oCT`Hy߾-<pjZ;M{Sk?j4֭Ҟ4^$!߆w\8c NS~ӽ$HaYӼ"H |kF^i1MV{y"KD'=eFu6W\xdPF"b26iiaߴn8\jܬR=-&hj[$iK 82#7ٟ|SfzҭJ75Cx_2L屳:<-s$Q0XILK6dW 1A(~טa2xjFfu ?k*ɌYR2aI[y1C\|HL4X8JbI_x"ߒ# 35O\zvo[=9KlgV@(s9au1*IsyOO6(l9AY$/5W|/d2~kGn|a= ==W^'KJddoIR&Y6K螟u]RyKkiWwPլUDH]gbظ;=}Y,>C%V<%rp6*6|vtKlF$3Ïu-ɣ?2trqQKTl& =<Ȁ酸Ŵ) %h#vfͺd `5/F*+}ʶxA3Ƿ7p4\cU+ T B4Tlj]ˢ`I4k2w%.Vxr[Y@b  sߔ5WzuY;ʟIK oa 7 ɐǍ򘜃%X̠k]ðJrQ}jN7liCqn Z75%|WN(xݺPQ#FV1<[ꆎNd6m):a2%ӽZNi_=qCjso.T2jyzV܁EDŽVIi~@Jw}&u$'R-OGKP,:+ {OKWhE~}>ӧ#I pQ|NaN/HBΗP7;|O+IP J׬13[̼VaJwvU/25-=̖=Ɵ6ȣ@w瑾zǺy*={g!i;ߧ]edyd% "X3gn\ S2wF/?qP"rSx> -$;`F|P~І21}TTg@sU{dz,{"hg@|DQ' 6_GPs y )`Iгa)wEsTL1_ H6rw.]m/F`. 17X/-40t-.d}}ut(~ЀLУw?CWsc)H"6$Qj49ET=0y%Sy7D 㚧Q:[Ij=p.oZL+m /|y^:$"= ۈۃ j} ȶ:8M&>g3bh׵nr٬]@C*E>=F>pۆx+0'fV;N>x @j L3cy%B5^s0A.8~y5o6À Fa }"eɛssࡰ&e.Lht/AQPTYr|Qf\RNl;mp"E[DGEhMؓDsiOЩ}@V)!nM5d˓2qm19AWlV6S-ԒqYPD'sKonxoaʫ-#OH4wRX:NFNT! ]ε%ź?de?bx䄣hv 9x˒3 w NBw[ {ќ{ e.&*1/#LRFSw|)dlmגA6j7 {>UG6GIZxyڟw~\T6=%QG[4rӯ{}rXIl8^&z$3ZRD3EQNZruс;YgU#ֹ1<'Oj^ez\j{ܿ4 LC/#V5e:&8 6MRW'-~^ܑŕщE|8SVJi#eeVUsKircJMOY:>z%:\It!'O Un.n!H% A!ˁZ{P ן JD0 =U ) e_̹f}cC%QĹJEr!rI%>3+y2"wℌ^ ̢o@fIosҿZ͠Qҁh;& ~MvTC]Fn=Eٿ:W9v'}>MX `7jWMQLƬ#q12[גЦ{OIZw %zI22#5󒢑GrΪEʗY5aѥKHE%VMb|a,cgAG2+AЏGeУHһ=TuFѲIs.ve~ª*-p sRŻ| u$q~i_p6z{̫ j-6;Tӿ&l|x9fga>&cJ#h{%CȮ2&˶>`ʼQsV,1 ĉ/wZgO>Vj>tpϽ56%񮆱 C&_cʥD,zp3MxȻٚ&[oAv #EdD-2ðN7s9F-L[ᬢuU 5:1izFf "4~{x:@yS,FBi&6S܇6'ǔwӑ3JT}:[ݫQw':?kΡN9+THQ0bi$ S?vm* #ſ ONj(,fv@("1ŘM'uh~(x %zC%dn>$bVXpd45fApݸ(N,o|՘#U"aM)'s-vMG^#O^QC٭l(y+Pjސ4guVأLT)f{=;Ҥ+ D7͓ӽ@FU ݅:ٯ;C%opfsoxd?:yCm~w ϱ& HHT,J@?8hɧG,HVL,4 ~59a1Հ&xW1W<$ϧ w7zTɣ }{G7.7SEiHg)i?L v8k܈0sBt}6~D22:?>χi(&Ū_t,/u&`T_!L,L=b4SW]QF :Ѝstl/ =MDV"N#4zq,[59舨eFY S>nw5 k^SѰnB!b,q+ R.Nڔ+.H)^0+`8,f^l*t)>)E-}ˆݻI̓pG ŪK<-1,EVM憭ah}K۬Xl9x ][̳#  MZ5I0qg. #-CSOٚ]Į{LEۻ636(lN 0|ւ$ "eZ*Š! $d ?BW~ ^IL㘜.qt 30Q]'S->I!2WqL53p%3>B7 DY"λþ" WB '/r+>hA% 3w4yˢ'B_,󜓷,Rxt,ՉE#:]#⼇r-Pr?[:;JKuY$"Ta>da][Irwˀ0]hlxBNCcɩ1<[>q9lH`wϲ@ৌ4Ѭ̍ '7(xq-azvҏ]q ẹ{=ҔՌ1t}xd=[ǘY#ޚ' ]T3^Ab2=+1,5ptl^HhMmх7CdA',l6=n$8%X ))V3AfoRZ5$X!^.JlJ\:X-x}t B Ԝ6M~Aջ+2 ޥ6 :A7SiAA 4=p6up5=ϻpr\\.~9xصV+KfTݦfW9ig$g,\Vh94I,uN#'<˴:s/d^$8 H>Ehkjuoq#'S:q.Ӱ( I.iz!F. 9Ѥ~XLƗC~İ3G \O(f&30-0Ӭz2,!#͹uH7RR]d+QrXyb_mP5M/|(1m t|*莶gLدLd:Lx'fv5`r' "B:bV'&w C5_h=N1Mv|ꁞK /u_ƍ@U5@8[Y;<yH h3Ƣ}&?%$ܟ#g ɧ>&@B/@h޲ܒD$KbBxhEH<-~IϓcY,NͺY]b&'Fsgmc0n7k,] ? !|,Z @%mmU(:A Pr9|zQc Õ N=\;fSuo5c/[ zײƘ XTV|Cw*qxD\I k8Fh3.6el'!Tguq DЏQt8=+o'ބ {xZT˝1#I&K>JumGXB;yAHb`ONVɅi9F T v8yVd92OjpM齸Ei"s[߂jU+>/SN&l+[jsG9Qл= ݺHq+|rGHOպ]2yodv(DQg2{TB JkͮDaj"0 4.c8C3wmPJJh ,hmg G5Ggy$5v-Q|i $D c>,H̚Do{v3?rR+-6̮ J%|x3TZe˶[<7y^6*P2CaP'>q  ÁZ3r3Nxjzt+~;ݾ/Q8~#%w?Xg]ٲk(wg&aC);};{$h;Dz!/| zmLw_M|QH;-Tsv=V6!u5d| &GO,9%J}j^8+R7{K~Y7j pcmA{i@jx">d:5'l#~4֔ꖒ4QVڽ{n}e^'ZoIA{;?E sr=k[0s3/XU{A,Y8_sMy;pP^I%̌8?bͻHz{ \V#e}j%T#*DR^%{]Si4DA%zCg]RiuaEf_*=;/["4YGfȏ-UTr.8 Yڱ󍬕:l4eMQ̪3u̘:O&֎%#)=>9z2Q0G=ÌvQ%̱P:9k+>'6/Fx'ҧt)R..P ;..KB1n;J;1JzmpTh W#U;<0GOHOQR@_lq5>Ԙ dN:";80=˾g" P[&ZlU}gfQ)Ge!~Yf 5+PRɈkZ3Z7w|{Quvwo'psJ$NIDl 5h!L%}ķq--s{(_G2Ê6 A۩fF;9ʺ1F;)UXŨ>qn^!5[(j6@Ъ׮АH>D`i(4%PWӐ"c2o?Ja͡a%^&2*( >dZD=hQĎHJ';K6`4+m|y|uMYwQᨮkӔP.$v1wϾN`b qVU[)k9MtwwX7 0Í,3c'bRt{6[J揃:5jO4}Ђ.8k'\U*ƿOKƛؔ#pDC=9߲K?MԘOCâDZռCA+wSx:3[~@<bEzӦ*lv111N6K˺nH)S`T k`#Hn^Sl.v BA~Ww:58cA|gXZj.fE~:YSiaKK 5ݫz3 }]JOpXxvI.5z}.`~%"1^m|d}ߧ=Tcwvm<H 31Q 2O.s:>z>m +[GJ QAYMʶ:^ä4 Y=؟kE<_͵'e"(Xr5z@ 5a7e]5)u1 y))iZݏB>jGl!%WCAd7ߌ ‹K8Es'(TCA loM~Ҩ8@>ه=[05E n@x&٪xIA63^h]$N?8(^ p""MRJGsQs3ذRkV[FΧps'O_iFfi0B/SDŠv"MF+5_hDhZ1-crr ]ے̀jGELl5G<~=vc|nέDJzGWThӄm[^OBͰ?6B\ ,҇v3v3'( lJ1ٞgc`ヮm\Lq4uGCEKjYVSr&*)b_SEpʵ#1\D P3˛UVuXF>IY endstream endobj 1553 0 obj << /Length1 1401 /Length2 6058 /Length3 0 /Length 7007 /Filter /FlateDecode >> stream xڍwT[6R"C7 tw03 ] ҩH(%] " %!)~csZ߷fg}]{_^aa㑵@0$?/H /$¢E@B<P8L?0eS#Q@ 8 Pt~ ~Q =$T0EupD rܿYW 4HG+-ЃB!H`rD"$y^47 E: bBƋ;Bzp{7 .P[ A<Tu@OEr~?ODPد`- { RRE 0'삀^` :P ̇!~Am"N !x?Sz@lQpapo_+{(vn|0'DEeA H $@#n_Nf np75$jA#^ OǿWx @0k{@}3~7 0࿎OIDX;>??# Qaq i?mG Mu;&E\A [ԃ_!?;Rtqg `WH4()j\ *H0J 07P@촡H[|m74( G@-?_>lQE_.J=.P\Qz1 #Q!j@L@@?]_Um==PN/fZkKojn+TrV)Kͳ{~5IO0s͌rveړ%#4;gC>Y!s)ʹH4Ş%=hjDZ"k3L3$NרּUSM(:e1wb5bscE|1Xx n 90cjkX/b9YXŚFi}xp2 ZHTE-͵8o1!G0g<-Nx}:lI Ec&sXsA$qV]66Ϊ3okb.YnCZSh9iMX{#+= O"pRMG4sAIz [&^-pz^&3c\сi'%m=oD+Ek{UZ\]K-b4'0Xz#ᬉS:Qqˋ Png "eS?)<%C2M@GH-]D)מjZF!&gNHݑkN4dRyd2M扅}Yk 1tmb#Mp Gգ9L Ӹ^䉁ØifԇGz%`l恼GL{?u~dٷZ* C}Ce0#O\鶲LGnKRMz~9ei#涡hϟ|sa>9ݡզFǖִ` r6el:&cВeS @%ӱiGHC b/VD~"J]VM$Q& XsWc ?J#OYj1ۯM:'u+Ew"&LBs 0ݰ>$+jDk֡))O*ɮZb19+CoDXF̽GsV߰  }Gjd"L^WW/.Zi!M9΅Md[֮@&sb}ApP9ۊM,IΕSsKJ;w!\#-)%tipFT'݃@f & %^n›W.rv>K]7$e%: :fSnTQ}i֎L˱kz]#7{A" l81`ڗޏ >&~ʄۡei*PZqՠ*Ey F(A>+ufj\i{[ ,ьk;GS'AG)] 'ҶW2Ԫ'(l- {wf4 ǁ$1_N a*`XwMa4!d8dGZ 'mu&G% 9Np6~jR\剏˜Jh^Sp&S*>_#%ӼタJM[@(L3Mhcă;?#&$O3yj!XPoᡘC[Fi7 ~bʩ>ogNwvqi'N/45)PpeXQ~Gbwؔ1g?ZGQ'K~.YNab>#|Xͤ᲎o79WbqנGVv$uW?sqY|uRȑOq!k܈x~?gd!U#y)QzU679/^(K88-sAYav¾^5`QnW-eAh?G%.]S _⁋9sn' ?=s(o@␡GeicK48H!eg3n.is5A2{ֱ]S_6S צ\E̫Xg#|_s-21g Qf^&O>O6B2׵ȺXp<Qj$]ښY$k'?tWtymшP4==v|8Zgq1~y.5m/pUxl: YEd 䪆1kr0F mUϢJٻ>ŕ80AC͝a,*}lU0SX&\Tss#-={,^cR22y;} 7toQ%ـ]ڶ0TŜ Ux1)vCF MǘN2H'ȻdșK2NNSMI-gq "8hwTge OZ 7!yBC&̸,lǗwW"mJ7uY*_2 V#H%#- u~1_rb*s roF@cU\? *07NҶC,f[ŕ !+E]Ŧ@mXFuvOG>b۫\[-a#ݶG.gx;Ǜ7SKU)q|\K:͏/c:Q$HI{w?dzjltoc~=pt>p)UD,~Qg4&H'xPnk1~D!t:j8tśΪJ;tAcP ƴ=}<6O ܌~w%d1w{oƮMf̤FyUX+Zyn|2ηı4δA%ޑ1!Q_DH^K$]ْ]> ZWW͎ ż^ ,!c(<` 5 GnEΌ:S7CS™R%<ܵK.{˲0 zx޻ "i"h{fޣ-hT I>oȝ9jSōdcX~Uk?of-v£1~90?Y.y$Q̟Btz~1ó?Ljڬ;Yݸ2 y@6g`6Bo `geblK շjvL[̤8rܼe OV3꺣bs5Jwdvc2B7*6ψ Hj{);zByt^_^NA9H~CȳQXe.KΕ!ogaAf+^*h(>; X2 i?9RϺc;`v0A|{{P ޣב}@,T_RZ Z[frr*RG {5; &_&;?.`O^j㠻Y3|0V]Md[S>]k$iQ4/.[Ե[rkbWe=%-YfP0`?ꏚ̜ީc~YDH]5 TYȑʪ3Bo#NQyH]^i[[\dٔ>q]P>>UtD0%FM4K' a`t|I3_w^x:|,=s^޵E]ӎɵ V3'hgG6LtvbigoUn *ޤ;ȾFzG=h"Ic2QؖȜ 56N[LŎ:Go karj.t"MޜcqTZ7u|b2KЗ;mC^I|>HUxҌ}Q%󈔗Ӿʨ-zc%\+KKa52&ɷN#̟E<UB}1T*/5 >6#pvw5Lso}Pp;W5T?ox|8 _#`#,C'GlGa]%зa^ͅ:L#&fRcR[ cGL\u+'aNzoEk#z-n;X HDm@Kc3(R"ҍγqKXW$E˯ˈq̂>vqrTX5zSFZ}ՙ endstream endobj 1555 0 obj << /Length1 1406 /Length2 6162 /Length3 0 /Length 7128 /Filter /FlateDecode >> stream xڍx4\ڶFAA c3:kD{DoQDI$z'B|}9oZ{sݞ,F v[*Jt, PD&`g7`w$;B۔A(4PhzB"!1)!q)  J DKAP;@ ؕ>PG߷.07@HRRw8@₮F0G ()pwxAQC  r5;0Bأ@!p$:nq4z +_ѿAῃA`0P-F@p_@ @ǃ$B _3 JfG! ~ u#:^pWP1<\MP7_6 @o>f ~W=z H"C#VnHiO7thB\&#(;_YWwG0o?@a>!@U@kP3@.@jP;/t_xTzC( #_Ot_>M.ZC#~MXT rw UiMfB3VH h#4?& AEhf׿xC tz/ϣ+ }Q(~xYjSnϗEL]y? ^NSCa+~?v0!ӣ I[b[r&^lRx݉|( pѣ)vnc>`a[E Y<"#w00| ;Wln9./]@Z*W%w8i*1G (zTJ[X|tA[ GR'#uYܞ#lDwj٫0Ά2E`yLܺ7:ӈs mX'"_&^<~($l*RQL:lox @AN1|Oeœ9~]POmj*8#kVb{2S1Tˆ;>7~:0/[SMkI1ٜ&Fm piRb 2Wb#/dBeR%O>LR6؉']c:@PZ+]NMhvWE<ş&6O?wyҰgP5nraCƛMo3 !5ְ"XEchR?Ue?H߽gľ;`W ?$"U:A~؄QDDY}#LNk`ےis YݥY/Ek-/(DU⇧Ozb|]{O7CtZp,G4Xόh_ ܩj)CxORnqv{!..t TRw3[1O~pgUoja: bR͵=,)]X>p1x Byl2e8vaeKco~dʎOlef)o\_E s*, ~%ofHӉq~uuYOfg #oIt3Lbq|7,Eܝ˦ӏm!slM$`Mn5k,o@Dǘ{ uF_S<1 D2e>x?dWe׎OQX EMM>eȂߺ.\?閅`;#;`̭Rl|4]eY|#=EÒ3Io<{lJp I&wY \ow'ПwK=Lտ9$LCGݠ*M<8Hvʙ:0 \ʶUSce,y|M{6\dKSM{8{_8+{?w4D.t!t~xE@Xb3q8r2&[[}Ǔ\S<\޹` ԾѶ[6:#׏䦸'9ge(B;Zs*l Pκf ovU|U K\opkqfZxpuֆ;F ~Svs+UUXs EOf}' yLoSTq_/`%o V1Roñ!Y JG)- E=iMˈ)A0KhX ^K<,DĥY)˲R2ъ1_GhhH"Oak5qlLZBm''n.\(a1"+v me6 to☆I>X S0b i8WT8-VÁ4jWݢAef}æjn7/+Aivg|1T$WjU }wi18N!d(O5i@{6=3^$P4/U06ĢBCoVVFN߅# ܷ{gwfSz3>hkn}V^[H!<,rHly韍viضI̖~pՔMlL~/Wda S\dF^W n aQ2¤y@o-4ajk +БX?dchO3Q/_S|cs0(Rf@K ہJA+u S+9@~^86$"E{]u+f~Q( _p{=~0L¼fy~^ SdaĞ+}oW剝0p/,L\|3@s5&JmL5iU$7I`Qx]3\R8ƁD+<+A+c}Lt57[ )`⪠O|8]v2MKtb/npfdcq'j-(^갅1>se]spԹGstCraUDA@mO%jWj&#*יٙv5ؾ9M ,MhtWfAd/ضTǷ_0'uNJ`Q KoSǻ)pъ~0ӕrn yyC}fd| ~z@?|$/W&B˝;b4j?Dy{%R#[k.s?*7y^zjrڦ5[>e VpC鳴$ɹ,4ba_I?0.UŪ:PrZ_W耡d-1 6i GtrGx>-2m!=g gjZuOt-5l}oo~0{|}Ь&g۸$!xJt @Mq灤[G[]'ZrtE⟕Y}2$dN'1_ SdN]bN/!-b\ӄ:3x$3iuh LuzVkT{m>8֣A`|dqCWZ3&&nouҗRz<;Nui &e7q1Ox?jLiY+&eߖwCVs,#^WbzKOsPÁdkeudEMUocL!Yf}6?M3΋URswX3}K*:_$uI|c^"7}(W  $t}@t8^?Ͷ317HB,2ඡe'DBӽ/?9C6߶ UQ`&9<%5; XxyI+!kaO& |lqe `tޯ@+S#刜hc׳%mt`@.^9A(y䶆ꦔ\*e>Do O$bYBO\6ҹsؼ3c1u Us$vNs"&QvT*v~}VG.-#iQy>H;p8ɒV['}ɵ*ndŘc} {q'Ҋze"߻xԅz۰ؚV4nlp!?'``{8$_@mg:HP|TM-& ,bۃڶ*lL^bzk,sjh5$j,#B7{Fz~~^KE]艮oyLDcXE'Y?O~wp) Wve9dvVC( o~|5)ïyTCF)MZ KЫ %^!l ~0M*i'6S{gxYڼA5lC%Yv4¿Q16I jc],~3U-݄JnO{F 㡏 kc;򗶼zVjOb^Gb毕Hh#佬M3{,l ~dM Yy{`M/sQ'!ga[پ>I3l3v ;dp|d6d/7}ݴ^~Ы.=K;xh+^co=/|occF(֌sN!*"?hz_ZϼJ=פR7{)LjXSO6>sADZu[n6\9,W6CgNV{a<| XP4[v] oY 7xd@D/x. KqSֶf|ڴ2xMwrPc#s;$yb.=a}Ky~NǷ1"ѡAPpSkL?JMљ,O6 EͽKf%20k}w}:xGG Raqq~~"~gKf[QƊjL`HL*)P+xC/>ӽt_W՗`J[P{b oq똱 =NΤa4/ed=ɼFK{ys*~ب]"?~yPS'ߝCO_I{i0b}C;DI 7nAk^nm4x){V3/9rEN(3ڏE?|sAcg3+UӈGKB!MS`9~_@gKKVX$D8X0HG1%RG )Y灀3/)bL#m(]KltV凐xWӇJ9fZ"/!8 kDKeC.U ̅iv qЋm ”Ҧc\^Y+4Ĥ>tRYx9i" '6)Kvk3gVӥ&+iIFi+^Ûe'z[ ـW7't(mHXXؑ?J^4Un8j:/ݥUçJ)L%g7ȧyHb8$:J)rO=g. ?yՎ gfJ-h endstream endobj 1557 0 obj << /Length1 1481 /Length2 8465 /Length3 0 /Length 9458 /Filter /FlateDecode >> stream xڍtT6 1tt 1)")"(t}߷Y7}γ3. "xyDrz*<~n>,ff= /; AEs6y⁨;xDyDyx|<<""D  @ñ`.n;{>Zج""B2`75 P!;Z0k)Q ӓ 熹Isyܽ_# @mlaԇB\*sLXفAa>a@Ѓ `b ~<;DX5`@ ?ܿ A~߿]=(u7e48n0// O'zXg-:D*U`{@K\0B7~OM忳?);9E? gߌ#@0 ]u *4@+#Wxm kT]9A`-y/ÐY;>"iqf?UZl~3 pH06`?b0CG- Ŋߦ?w@@^@@r^`k)XCehE '!>ܞG r132m?b.Wv x͗bDfm9F$vj|?T[[M,6vd:_=O9]Ofl+ԗdɍ2I!,̏,\*[!3>Ѣ?Dq2OpgFz#v`yC [ISK6+XȑF]r jw*2XŞ~Md-()Q"P|5Xqgh%BU?s=xrxZ>g:q48l@NÈ N|elfzk]`<g{J"lԁk`++Qpb* 6{ec5BսJ*,ȱ۬G5JR$fZF` G! 4fU(>7?!)NaO+l㣱K]cͭ9ä?%FV?_~ZYUqʔTub`:|v.#>Oϊ ,*r+h?禈~`T(Ĵ":ZN؈D;S[se*].5Շ4H%Tiցv$b]JT$D<&lLCۓFTO _cwfŨAtBFc(i>=حzɧȻ0ǚT\ZAO%gK`-*qn9@s43Ͼ\+q{sPxQMVa:$Or~AL&6IOi8*c/\\э:0q''q l3O2gc^,N(*. C)4479ovzUXt^4!C]r!\Y$QNRZUh;%0p^4Rrp#}G]o6T 4gl5b:r]):2G=@;a.E;@qYG/@}y}ꕓx^gnU^-1YIo0NrSjOnTLu#[gnUj|Kao#̈́s>}٬U8:>4Bl1S$ Un6 P/#9#L@[ԽWg Tn"l Cz_, 3Ť4kVW 4w|~g;ĉߐl u B|LD7vdOrlXY637EYg t5p)u/?՘~ '#7iTԮJLT"?Zณ\@!-4d Q9^Q9uɔ9- P4D/">:+'w,4Rbpao TdgW;S~vb#"o^=}S&)bEgn3ӗ;n Xy^ʨ4!UeFiHq՗mMO*2$mī]Y;-).>g岴",]dKTP  +"NF:?mu_4 'ڋ:<<ΐnM!H}ɏ0 XrN5OL*|bɴKf&hE47yU8<;tJ/_D&VKC|œ# RYSz.K-@p[sw+jvƼ͸y/#s^ln"7#Di^k[RpqK",zJ@R렪eOwN Gr&첏;mܵl%~RC-3*~/zSO+.49hN-R_"h X-=D]3_ÕU U} ?n^V7ɐZY!J,|߬)ō^㟎(zLaK QPwO2 qKp\ҷ97*ܐ}|q-\^w)'`6ϬEԮ| TENV]3L.^Я,K$iOc&>~PD uLXmG{caDU۞CdP4*B07o\s} Zr]"t_ulژo^c/(j[=f$r2[L=l"»2°|a7z]Gv`KKwQIh˕pj>n/1{^/SZ/$L̳h^yצ#Ek ރSƥ%yʙ@>p yv;SnTL >j2:̧%6#~W5rF|Adm2?ꩋKƖ6;j R4HJl|C R֬nJ.?eJ틞U+ء(C8- LHư(F'>].,@H7՗iC VXzj*4$胸CQwO5?08oudZTrLPV @-XUX\ HF%Z0"O Q#C NEx$qݥDJ@y+jdy^5X[[MhwxH2m60r:Pyg╀5aBjgZ񬡞]Velٍ 䒯cp2lCyZ':)7eFa а~@Svt}֯G( ܕ{rzmz 0p'ޑqKm Iɟ߇sx.>❂Ւ=EW)tH;&7L` 0:dBjic,%LgOj{ӇNZe/ k1]ށ4Sdo^5!F >+GqOڛ@PD7qe@dc\8V\L[Y?N;y.*jNxFyO|-w#g3B1Mb=Yر=1)o#^uWsHϢaϓ_zV ߞm¡BVՓ87٫sh R[=Yo@54UViUFdb[nDWƋ%֩_ZlzxzR[ c-wLTꄐP*V|=K+& vR6rrfD<˙JcYQpN=Rr(ʄ+Cz aV`Jq%QT__bʜMFYݯ_G͉  gE)K1:3a^[tvtNn#T?[Pl!`3Pt?a32,N&Id>&u}vIeKO-n`fkGa˅6?:fWT#XۧBQ!4ԓ^\vvŜ"J>Vi* &G?,o~f CȋjցW}Uޣإl#B%[$PSSewχToz3%#3;r'ѝ}9g4~O9Ήxl]s/)G6J)(Xwiȓ,M@ባ롵(e&D2ϒTMSΕ\OdgY5Rm?!",XZ*KM׃S2%3[(l=$,oh )7k&2}7|FȚ]^OR ¬ͩ\^5-ĜՐ:hZZcFyq8@ 6{%fVk6j5` ? tPt lO}τgB*\j~eMiCo%;2 SókU^&f%is1l ovb<ĝ wEa#hL,+]{Y*%̻_Y 4tW'ϺQ?@|MKo 銢Fk\qa#8L}kݬ B~.i.m\A&JWZ0dXB1Cuu*մ YocdpeI^ιv,ܥ%KA\='j+ [` /l>Vс k4g SF9,8;S =\Ňڹa}Ȋt0P;¥܇3 Ra(3G ѕ~:eMi<$8$!!1U~,:\ς({+o zTin{qjJ%vWjYJ>Tr)Md  ޙH/ԹmN;ր%^lP@1LH4qL4(sI#'v>cAjz=R$܌,6LCՏ'o˗E_+6liy٩%'rsALۈT(!{f's2R:oB~k&uz?rˉĹBިSC_'{1~wDpfߵ-G[cy x5bRRh|ʭmÆ[4g׃_ ΐG'TA7OޜhPV Xw 1(D`{(F>=Z dzX(wL>O )gJRݩRQ ceWϳFyOF;&3F׮f D{1kx7{q~(Ծ|CŤdhx/qyi'TtѸ_Y`W8 S~>bɉ]-_$l䴔Jʵ4}g鈤cO^~ X3ç`h:œFt{́M/_$X첊%}vshkiݨOvnF Oe245"ռQi$%46}94+v?3ڎIߏFEE|)ZnW/ixXy΁,rJ;)"x%fŮ #$gF6,AS Ҡ18~8V-V&ʬ{s'zIrhVu>m)+!%j= s/>M|vMZ^NAM1ܗ'[//*ں4W8|h;) f% IԒwߔ]HyF+Y8V_l7Qz#EeڤT%fœ8iah>#-7i+zE> stream xڌPX w Npww!K@pk!{r'nW[T+d~d0 o󿎘EUYMER្U=>L&v(*S ;YH?72@cnjyr7㿢H/  ;, s E0d6UZV Vv6"Z\ͭŚT~,&6V,-p_* dw(`d\SggS/dV$sq| hk,`W RH,D#no`x,E_ `,ҿ;E7F>§A~#§A~#o ` jFv®Au~#bi/X;Bv 29+d%1$ٿR9h;3b[8H1".92Kbo_bPG_z'76vm%`7? &V#BV^V&D i5 dj҉sCJy>H6 Bfo뮴#%4$&/66HG dGs\,1r%'vn  o_п8 @ =G_b6..@q^lsڃ;|\l"$ -7H.v.T;+j c mt{! }q1;>d =XGHP? 9G9C"y?3 ]zb!_ߘ@O9\ Ħ6'Qb7;itL>mn)tՙA7)Cݘ+[E}7#$}0NPiE^(.Z ICdW+C:ɍ]%ΣWڳly4lnGu[+SfA` uY,!+ӫg379dr ~G>zq?fW+4]:_^cNŬfcZ# ?W&`s^kc AEQ7qu>O`!%hw06™B=Qg"ܵkǵHțx+MbN~$W6T5>=6GӞm'nȈ)8ykp8 Z͠ 􇈖4w8Fxz{x4x%Ora7٘'UG1& Q-[TLJA)vbi_{܌^VMIqdtYj % GirceQ9goobR1m-"+3/K # O}|ƈ(|s]?Jғh?mToKoks:6f PFB?a*aeV5T_{zGϔ xl҈ Yên]Gдb4Y]ݪBG+h;8-}X%:}Er Yۭ}'&Dֆ>ghD6=K\=-Uxi6}㝔,~X!Oe(fw12 0lĻl]>]kyr/Z߉~)(qTmd5I܍sgFuy}F+]9N92EY>1޹Gz+U 6[mI81 zW}6]e:ϔTZd w\*3 Zޫ3 M84БsTܑi^~uX`xQ&^(gTGy%zAx@;ݡHb-km]Fp'>2T"&QY|]PFml rI EݍRS!)#R)ӴPi17hr2%7T}9E r6fubiJ3;Y\ 2-+]Tt+6Wm+g̃|=aPfACNoAyI&p1;&Fݨ2@|ċ۞\՛Um c:7plͻ7呹S%,G&4G$>! ŏ@c|2}L83\;-Qz-6hFVSenIy!))9J_#:6 )&ô_uY<`aFbki:ލ4 1䡎^tQze" Bn#žĆ.1T[{"Â;r-`[74yG E˰_¬0wh\Z쁉T2ygw@GIf:ޏ& /*qMv}VWYiCcv%vJ gu: h  QD' Svm=rflv_xF$%gؤ7i#w>MZٛ)s_]*$r*}Aq7`#._s4" ϺOVϭ5}t pP޳'Vg.Mg>ɲon |KB&`"1o螛꡾|d:nbf?CHb >|/|i|%DW48CuÝrQGXO#b9m ng%q{EkO%Z+iJn |KJU S`;v,;[,tw&iL&y+ $͹߫[#cIqlkt(?)/eZT ۆΛՠ;RSZda)3or&y}W'VO ZdP!GW{#沑 o}jNw$nM R{A׭K0݇=Rvv+x'b݇7_5q^Ʀq#AC=:D'_j6zƦ~nEKujBW]y=K8ґerm8)%[ayace-d5?riy& s${G+!BFޞK>Fcદ W$ljy@f!*\Mb`g7T>?`e.J捭qI] G('24sߙ0/K$d@~)r[#Gqq_$[ 3C S Ɨٮ_T]{E5_Q4stE?t:;)ɑ5>EO\?JUVԢ_+to{YP |9;R8>.-kL\W|$RN _G~P/ìxT 䴽Ҽir:ǹE?}ně@s"ƈ\2.A?WY.6[GmHVv&?Eϝ`rڥL&0V]o!ʘ`ygd5w~2?y[UEۇYCᴹ @dּ1o-J4jeTӌA%G,bPG4i]uHGz37@E&C]X+ń,N5@]IÈs$ [Fݲƹ)I2k5a62ʯ?!E'T;_P;px &>NW[I!q 垏!Na D+.Ԉi^6|Ji\ֳLIQ?Hfhy* ^J΄ z eoe%4푔LW7 *JJ8n4kv['@{]2 _oT!8}t'J 11{r R'cwg-e,Rrʬ׭X=[>)MOk _XR:""`lM;US%CT jk@$Cn:n4FÇހUezPli'W)V5#Y}N} dS%!@l/I"D?,w%Wsdrz%,ߨ`]ʗux_=}, YYpk)[& @y=؁Q|v7xgSgk?Fu--mE:7:3`IW9t 1] +48%?|< Ӵ񈠈 K֙3"cdERoq);OCa!1O{`դsfk)7d8ߜ3os-j 9FVFݽu՞*Fk3D]#Iwp-xH/}XjNGqƥ,6R9Q_o(L 0[%} Ck`/ŏ=GUܡ+F-F F#É+̗}N"3Q :3{?Y0iaL&f`;JH[ybdSGM2 W.S?<|G!nb^A_N7̺E#7 rh 6w&aa G3h `@"Gonvb* e;(:6W6` j4θ_`/ȐZm|+AGNgmȪPS-{Ոtw󽌾3`9gI(6E\ >@t⎸U~dU5W .U0oz ԟ9c$HTFK!yM KI 6Y-܂2[&]660ghN*PR"`7nTa\JіK ^&)ɩ jO~,-4},13"mvFI6-g4Bco|[r:EWdW@hԙ{kV-D3#(((eHգH]=9c R^Tr!拉ۊӽ "Ey>f` ])gbYW] jNiK1vsZˆ9 X}u#0O\%JԈ 1Q!NK~K2-E3G^Rl{_9 )N._,xCu9i:vSܦ(ȒY)C\2;[:Qa73ᦉӄ>#Q74~ nYEo 9sG7CK\o߱27 LwO=Tl fݮ|^ G:O 7ꌰFHiژ>Fu0Y6u0N%:#qu6-JXb6+=(Cu-As-;!5\)L~ˊW 6Fm#V9+'~! { K|>hk KQ鶖C zֆ"J۽Kq= l bUX0Ti ^[!i|FK̐1|.nݞ&ZA{TumK'&)0l2a,9˳% S2~M?IK4X2"\fO^bA}gv9Id.wwF.-C9F}z$pH`FyVŶ\)i,#q$ucN(>Ny[&Q?}MѽHpgqCun+^" z~S~D>  # 紴}7MZ\]{:qQ#_V^}i,9P[M91Tm:rN (Hs$λ7zV6~UkYH~sƔO) j[@YWr鋰xvo& 8s~cn$sͧ ޕ KxS_11_U?j<64l pлÍ^s>$6hM1x j/ߓqs놗{[c`ONPϪ%8vȡ;ӬavL|ʰ۟=\w^n|B/x=0>)0TA6]׈mMڌt$(7SO8C3Cs(d)ؽX(Ȥ.3+xkMxFpEUH&YV7O4 ҽmd8s ul5l!+("%zT_a`iYTCj4bQnPf chz q1gp˔JE 6Ԇm.(7is7y?&!ߋ3Ǒf2 2$oېU{^=MzL.MUZٱXU1,Hz8{p_F?,$t0!q#:!K o+uY PuP yߪʀ8pP'6B@ H~XN @j\ R*E*MBBiܺ;ڎ^ZQ+ &gʲkqnƺ/_bT^3훣>3 HH1 HLH2e+t>x~Ou^*4i-E >qt=bPfJk6,'cZ\T-TMʹ஛) p1@,z]HE( : bzx{>!'b[4Nwvw.2TrdA7OTu/`VU(6 Ih;{ <Φ2./N*T__+'^rH7dͻl.ǩVC?ioA鑮}k^|9꼿aUҼgA%ZYnvf) e&M׾_{z! ~ߵNRуҬͩ9V8ODw}bM.blfL[.<62 {t=7E7R&@ZrDS- B$uL?퐋0{}"Qp#5RF#̥ M5'YL:hB \똻,btE̜I`9CC5|߿!c,3&&YnFdճaww !!Am gݞ5tRӌ4xoWaM^uwJJ(U RA٣)+bmT{"zGx5p)3}co4QJ^ Oi'+w(;;?&oW&r lBA;hƾ9v;ylkϮ`l. f ~ Y Ex:Փ'ҫ _LF~1*5L > $\vڕ-K 6."yfw~@HPi͛7 g\>qj Z:m7j_- {9հY MNFۈ-PGnĢn>8 <<T/ٽX\(+6wY~Hj1$J]9FCJjKiRnsoo+Du:yyD㤪/pJKEڬ4/2|0=Ҿm4eQH|B|dheg c]C,qdb߮]XiBF- ^/.uԛ]FFo< c}-J}lN|gt3|D AgS!xZ5F 2EvIUq]k)]s\'^>#6q tNaĜz8H}?']o)sU,(9XEh*VF`~/3EyS^p.bPw|65_^Ue462&UȐ)cUUT¼Ega&)x#mt!lI=ch*Z3 kWIOSΑ[nrj[.66^ o= _ D-{!ɟn QYٖ!H ltOW1#$@*{ ~ފnyc;K,- k FB|5O `"$EzeRY!W Z,00Ξ`͔F\2kga3a?kzB]L+ST$dGϲ jDѠO >tQAT\le4(Tҁ,*(wUQūކmfPE#Ah`e!p]()EZ!4v9D)r#o Ժs(]1HB}'\^<zk&nok{MbF_Dd@@7mw~n%P>iZ*R4Wl֙Q!&,U&.gOQ޷I'bLLЖ.Nn#6XI72d" r%?d*rd^rS&Ά gAZV%y/׍ m4 0 vv{}haA<;\y䝯{+x3nZdU(-Qw79ɆzjgހK~3*-CK 7YMPZ_xET.r=' +Do |l C+T?۵9+~bsVǾ[#?mFף HyvnF|>.2ok,CRq۴YUhU"2 &]$5nlw{Jt1$Ӎ7JUWff^Som;dŹw7?j Q.J%)V6sPA0FǡB4IXB=FNߚϓ:_i07`5hxjT? cy7C-ؓ2V¾afh?[^ɅsDǛLth\ɛ0ȿ?9Y]рJe J:oB#j$fl7z$>`(`3Z-޳u8TpNMm{!h)6Pv`@=lxqv" glJ"&Y:o pҿ>u`GoGKkrX +F26~:EewQ.-3oXCg %0zCג3ȢŏqvmQɟ>e*[8'˳]G*-M[Nwt ӫ)bmJP… @E@*bb KlЃl5gWvk3SDx}䔀h8wlShDrE_T'.KkQ\2wm`Yy]](ۃrMR'irgح OҎ;!k'A?> W)KTb * 1pO dQ0ŗ^nv541:Jhl۝ tSQZI* hWtqe&#olYWr}L4M:%ڔ4[xC9YFy1+{ AD쮋aA)K%njl/)[hUL0ʫcSʡ$]ukE.KCr;{q!  u{dKBdv(sH\ n#/h)~Np 7P5<.g"Yj(ѵYHz:2Dp]H4%Tؒ:v5J)ƭGaK>2`}Cba&Ԡ%P1|hfF6VB "Qwha6M!NYvNBR5^v:a쀢< ͈hU`{i?%fpXbBwP e?“ytՖ"4ɐ+RGܲp/:)z҈rn{;kucduJdEWRM^E'p>K$Ta=2)?ͨ9>qo]R9,YWQ¡I+ܭ)~K;2ԵF[oظpL@z¾pf:+akipSSY̌xuzU(EB-8|XϽG$4VNА~.@d/ V[1Ĺ\lؤ;Kg4YɅ yGXujRF469 y"-T\[RJ}Qv5c/OxըSjR>8Аc8xywʺYpw )qfզbxrϧ<,6LDQ"ܩg1#r;NUWՀO-Wj7ts|,U5=<%5>8u>shk>|zGVswRRF .9=}zzyyb NV1REaG!4T3arUqr guoeLŏM#&f-瓔opZHHʦ xHN/s#@l[MI0gp^r+MN:CR%0ųk H#m-sA~V2M jy盠p-铲DWe0&ņ?Yneq>C-2]|Fav L8R㢴r !%D_P[3~g9'}-CR$@j@NcY# KQ36չxI=bW)@Vϒ1:03G̷. 6*-k>#[}?w}:"4Sh[/.9S /xqZ}MϷk $z_LA,8grl6Imyy{wsDT{qjD,p)[ʞYm bJnlNz["tdUV,%\ ^030Yb(_Cxp?0t)C, j#(eF,\רLP߿tlw[ [h2U)镫1zbkAsO//{v˨c0F#Jvkr &K͢_8q0.HLmp$POb(C/'J⾭DeWt.y.*MyGVDԼ]HO[L?SP)H9<ߙsx_(c.`t< Իإ|.f ʯ^b#ʊx[خ3>.up #Tz :kB}_;a8e;y=|N^׮@61Eeõ_p؅vQ+(_\`-p2/tx֜ÐNSolx?C*x06U)]["֧2xD3-xߜ1){ K?̸(*,z}K✑Dk w;H SYF2Tsprޠ3*]WbWӍYH ԋs:aN.Փ>%/w|O" X:m쩻L鞢o*2Um+țfl`hFbV.'8ug`r* pY0!g`8Rê&*ccij%IkE:lk_кF|kFIq|#rX @c.zޠ љJ/r9jP^~C5^CZr* Ws=Vsu8r48kaYg*Sֶ{Ћ?E}Dn{=u(Sd緢+I;KX۱._݀2"3{3a>Ȧ_~3X̮;4q `8,Fg_(^4n[DMErw.v7HH04Oig73jۃ1uPE kfQN6O5r͈,px̱m ZK9e#Q,T~__/U{4%z1Pn}B,jpaiɘgBE%^;GVRL@UdkR ~k< D0[mʊg- k/špJr>2VS|[cHl=+۴CȠB[e%jAcQÀ]2@1֝@`Ccg3s;ܩ Kb@m}BSņ,3.P#`۽󤵂!jW ϛ4 ~4+CGJ?vD9}n> KJ ;;Z\kdHVX;Rvi[_9?x)k!{yȃJ coI]s(h<".K_L "m4Fu^c@h)v=jfly .DJ _%lNT1EIZ6_aZ,- Ѯq\UyK+}ByPbY@l*<}rOjGs W8錽~d㸢@ S.sgw&j9OK?H Kbzz#6WҐ!/h:1xC0k&$׺yY/,X>} NAScc.d1kKۇ,@eB+F/fQ]l( w?))VZАJOS`13|CmW01n|.1L~Ŷe{TgY'~(MrI`k&Q^x8 vl WԲ^)v˾8{޺`FXPe U93O[hb(H,ȚS4 HN8VvGv9#* Hf:lxS0ڋ> :e8M"1`A ?JF7+-Z9q~P^hV.b5tׇ{x4ͱJX/&԰I@`fףqiQYx>(8݀S05HႽ/,ލmw,{y\oΌޣ—/7FLJ! װ+y SΏQX˫%R^ LW:ZSp˦v!][z̴uEq؁ʖ>%&5ۅbO&i2YjeN0Xw=yj38>Op=گ}V/{ ]މ#:߼'u { tsb2 ; *rw(' 3O 8:ûe 6 ЛKs/zsd 629D:OGj p:R|ujm;+Z"Kߥ] ?wjǶ8ay[Hq MTref;-*ؚ'yB1Ac>ZƍH`3k.|kQjei];4r/jjd%zQlEku-BSɠ솚AɮgBdN,yẺ/ξUƆ#^_nQ#(G ug"n陒Yo:IЦ!Céj!^t1J'AcOAtFq@5%P d9fk"? <1Z6M,qm{a ER7v[6W/֥%j$ZގoH kvT4 3f( m-t֧ `amVL6vpdf= ܏5m5-% -r*F<9bt[$qU*@easS݄^!HXZ+, ZBPatt;BJĸ|d#M R[;kL>xgw"|yȅd/UI *ra Ɏ)/6Ҕ4p>c\1TKtZT+GJ(D-u͖+Ҷ^C": Ot)Z`t q&[É΀bOz7 ꏛjNTf/Ѝr2l!, `R`bE]WqnHTT=ϝ{>c߈:~nQXkf"ٺ0F-W2~/=t^ȳ=ٵzGfaBF?g3P[.=ϵ['$8}kOA8p_7ҏh"i⚎o-~7iQ6I=U)]ePqժ**y*QL *XցKyJ`wM2H@)R)h"zǴ*'&^#'GG ˫dulN7# (D|ڄش_JX[y/JfDK$/gcH _[iWx3&Ȩ" Ҁu_{77"*Q|BWT~lstGt0UTQ[IEVFo9E-gX\ÔEwU^ ՃRů[vjS˺Ԋ>U.-FŜǀ N6>x͐ꏉׁrExGF{}<Q69ھҨVpsPTwm3Gn`ъouz7uJ]t3g R$jLKPBCk^.,>HΰV}rz۹Ef6dRI 񍈪 TdWĭ2"n4呡 #3H]+ۖ7au~䤘c,) vSٟsiErfُ3M},Z& #02 N 3̮G\28ŞdDH%|Q٬KcP7,XՋٶkdbpf˭"һ h 'tVgՀJ?&s5@m񳒸M#.MSp|ɏ)ըBa}v&H.Lnj{4P& ׈IimƼ?E>sPu~%X=]=h2rkW}|' Γ8~Ui@WJ9{H[L8bM5{5b1$<-; PP3׳$Oh8K*&]$ `ȍc@k<"0xq5́+qm-ȗj@Qje`l)32@/}yUpH >7)O(#1]I\ܨFp &_REք6rh09՜Ky(~QًR+I3l'g: _[xjli2f6Ke7z^ Y.U9l^@T0[vw<< lUOU(`_5B1Ϣ*髟[?0eĖHؕSkXTUxz^h+z34g(E{q@ y5`c9;;@w ^/x=CZ=kzmTOv0cȧ79Zͅ([,9 endstream endobj 1561 0 obj << /Length1 2127 /Length2 13081 /Length3 0 /Length 14348 /Filter /FlateDecode >> stream xڍP,XqVXBq8)V{rv9?s0,}zPi2[9Yefv6?F q-F2tC^dR;e'0@ ```cpU e(@7I'goW-%,L Ks0@b t|hit!Nq`ed1wtcqrgx h`#XPhZ NOsW E^>&jLt,N|(!4HYKlW'GŝCW`h{EǪiXYB9"J3Ι N/rDFXR 5ZnDdW8S>i >e1 yl,Pྡྷ3 +kR fF2)(&-CȳU&wJ$Z%6S`6|xƞ뽆}VBj6.LJ tM?Vʡki.>i!tL3y+;]#%f©4f,2l/І*ftmf9`2ywbp18QN`@8. k05sPnĵ/֕Lwi!cmq`쎼lbQaDdHkQ\ۡôƾfM8Sqm6 ]T2Vx2,^+{ӖQݵv(!+?׵rm2fzG-,gH'm^dW4pr=t丁sɑ Ljw8rZ5!:`Rd5 < ž#=ogaDzSwl/=wc6a2M.΅6 { $qCZi[e}h_/W'aYoO/chbl'~%G)oDGYW]ˆ X6"{YDmfoEs5hu!FuMLX氞YEvj[Hldp#N,i1K-SYǪu(]Jm{'KWPb[@sy TCў_e݂z%<dٽ'vQ-? M쒠-DÊE[L(UGtlIж^AR-a1!!R$Xgw1W?a_YsY$||x!ӦW >5i#wS#R7$g/A 7(ޢ&W8wd 3f$HF˄J9v4O59^_4b\VW+؞ E-(Ȏך;/SM|Rs 0;i,]CRPCtv|yPv6L|g8X} ?OnBXvnF M+ N&SuO\r\8'1 YBEٓx j9A}~o}sol] H ݷ/ /7 BzW+f$3l񯣆mg`U˛7i$P)KWd,er_9!g>l#ű԰Jػg2.vu6w=.lO>mN4+ydyPnֵDf%sd/ W%%'|'y$ lAk&uJյJtKJh^ Gi=`D}pmIM.38 7 LʤzmQk]]12TN3:n .L .O5Yo;: f%s; !vVItQI:F8>_žog66@ñ:=5^W I2ik>lF|i7ťm .I` ty-~Z(lňDf4I2.4cg ߢW΍0DgV]«p_v~y ^|a~! *?& #Af;ρR'A1oYqoTk _i8,%v{H x DRΤl;|5-"EG@Y7(p&ڱvo4??5Oqi( ԠWస8|1" w] (VjېZ<2snsEoȠ_ET7ݲ}㬪{X|*Ci92he8 KnZ%# tm#oھ7dDligrOZvͣ^LgRoL'}pXK!alҐVXa@F}+'Ti9+uyڇ*n$C_\ <']팑?agA59U^DTl!.{rԚT{UK;Pk\a52qJ9ɱPX?"HDM=ļǣa"gLJ"0Zۦ9S s [ثv%u9{5}cg-_b*^ȼ6} 9[cD.`c(ACNȀL\7hV F8Jќs`~GNMmŝi3 p=`Ȣs9$>>ݞ"+n{1.DL=(co-b9竊M5ͦQ=gPGU\)L˸ni ڍs墭ˁ^>kj>Wb%Ebi *MxAj>-FߏXCVm,D ýTC|AE ׷H|QľdQMkU. WN5:gϻB3_ǸeTDC1 L󸲯$=_!FuV_ε-y}K|!?ge&=g;J>Hx ژSs26nr`A7-!HsЊ,3m{ %T>s,|!Y+h׏nMʕCCuaꐗi#kHZ)N0,:dѻSA 2i{S,i4rդSfT7۲ɅXw2z1O\֗o ˄ب~G~pQ{ZmJa(KH u-W s,/[jgA~l3QfҢ飳 Qׁa+-pƨ i N5+:MH\&:DvѯKRI~ y^$Ewha3 7OR34z؀ 0'ɁkۙHZQgDQbM9M-n| !]ȏB= |kF0ѲXxE1HZfyf3#Y9d;1ѭuz=T!9aCu=QL ? nf<~p*h}[ũ04.UU1E)M 9,)}{NԔJaUYt2GGLH۶tW~ )楊- Z(5yV2GN!0_8& {qPi|(Wz9kDC7_zHZI9p D׻!_[ *zOlK/sg 5?֪֙ +=f!ςpdfKAN͋)Ѻr58~oT:4% rORgg/Z=1Iufw2Q#TbeJWA.wپ:}2͊u˙m/`;Ngu̯&'AǜYG3c$͋!1+{v=W֗\^IS~ hh.ʇ4c޷6(ĚaEhf2J4b}uIZE7w YX< 05jHy=uZCreM_V46H[mCg0M&QVј&T%(Pry4rE37z/v0ޑn\A yd|tjD:9,{D"2B7=3 ^}hEԲݕ==yI\oIf(V[])@kyWFTy?д(x;-5i"̧>홮Κbrtw[ OV Aksʸt-6jl,cE˽by>=VDj~g ^_/ yV§1C`h:M8bl nI/Fu߷B)zlўM<M=!*M=n;!9b-_鈕 MuPxY#qR "-L ȳQ]5Sm((]lOF3Qd`~hƪkChop--zZWQ8=`[=؜KhWGVhaXBZKdbt kJ]y/ xZUn",\?'k@ޡ};` VԠN1XR; ~1q>>U!ND#+W a.ԚsȤZg4VEq1׻+y%CkK +X>D 4(ߜi6bީ@TT.骺Lսd l{Fc6X4|NE4eyoyZa7PJi.ʿbw"3sdR,V}w r~}ڜmv$9oQ 8nq!O+j&4AYAir΃ v˝ŏ7Ifowͮr|3x05]{Uci6%(2(?`-@f"1K}jߝ{o+k=r7U >Bp6" vc:t#}c lg50P[#ì˞s646K+[1lɥ ȽZpd,""LpDu:Ftf ҄' R>|[hv"{q'[sFϹ"*S_rH#Vx]'Rgvolhe:~%Sf)x5Łp陘}qcT}Y{Cl쐊`LT*&v IfK ʗ*ʷ9l~⤲r{0#v'i:S;-dGjk/\\FEiOx{3HDiwKcz׎[% ʫC,E]To#Ou\eZM0T w<_md4 ہzܟ-+ž*QQ: FM9dqoCߡݜ*N(|oU; E6 G+^qKz-y$Z޶ХZ:CVpϢTCWSvjZuĶKcEQN9jCS|^uh|&sBq]֥0Hwy5<ـx8Im>D^vw{F_}1k֌w/oTT`g"ϑ&F徚/w睘,zb0XG+bz%i-̰ق'yN0-bM>nGYKf82$ 7Rw {:3O BEy~zGަi0vf~+ꇃI&o豦Pkin>I\T[3TԣV,~9}u*]/Ƽ"HeϿBj;3AAu 0ߺGư]y0e "MCEi[9 v^p+Zy'#k"mX=~| x m'/f8'&2D^!FNQۓpYx'1~< 4v2[nxbg/GoC>|gW9$r$=H6T7Qh^:0o[̕3ɭwvM?-(2S u.V8IηI'4ębGO%]b)^TFNhZd9:QI7@y$FȂg{Qj$b{,\#AQVYY®V܎(1i,(z9.cmfb wdIwf9s=A G!+GpQc^ ,©ARJ,!Ż{0ȮBґ 84u6B*[͌`̺둻 Ս0ٵْNfgUcaуuKGi;PEҔh@Ε7IgfuGBjA/s:Er| 8 ڐ^'qYJD-B+aiP <$v#W&M9i8xN(k3Lٛu2w6Q|ʹĒf]2?|qu[ kqxIq=7nE4tʋW:* XWlnTo2Ĕ'*F w (1>t>}^o>%tܗ68l>;p-zO'O}=E:{P}U@_q)ğG_ŷ+dٽ2|#,A&Ob<*tyxI75MѬǁ;zmJʀrV4jp|àWfeË??vyN[~x υM‰8 e"V#Da|f/![BCA(QPZ(}n :૎{0 50цǵw+BvC3~'{=kcWp= %PjК rI't;鼄=@ES&I! OXBJR2U?iPI{]$q O?89>8̇F߳lG9&m=EO ԗ"F8M4g{w`PV#|c|3 9'h5Y| gcmVgZ5 RU>+ʣdѴ @*q0E+%t4Xiٿ|K|4\MZW]6A,U !u&蔾h`[fYX ~#qJ sp-·&ŒoN }\D {XupM&ȰzX<fأ!8(:i\ GDE'phi0uNĂd 9/BU/hOva,S, ]ĕv#$f,59I"I޷p^\d>^S@M]K ^a}sn}])>mT*LHRNCj3->Hg}I?=C#_x_io&_ݹ >JTa0`,\wnF y%FEdzӍqsZZbU4wBM$#)&/ouQM~k+Ue4[uE]h(ֈ`Yw/J"d})c,|E+&iB\2PRϯ:ۓXbDwL5@e 1Q|ho໬F__+ !&h1LqfvD|,AMMx17Ќ7WuGrC)GHΣ[ҽPQ1m(}OoswB# S?긭2pyd裉X& Z"ilxf+q^?gu>3j9sGU8jbnUe#J́> yƴEC ꨂ[ܡ*w1bfo.ifꋑu_ 擽m,R&EC۹ %i "]Nh /;97 5,e 5qWׯzT Kt縏Y?3yء?)8Ӡ*|6l^$w=z(@\vY'ñv.ib0Ғ*-j'K`@QgxΪ%+#B}\2z0rr7V =*x۠cԝS-$@I|v 8J3&f_:`̤*H2XEߏ 6hK0!ׇaj2* lyh슱qM@bz%Aet\jx^b \p %g`7=d1G=`/KSE"eg=*bhsPCؖ4QnϮ,W1NC;ූx ۆg.Y{!agl%Q|Sjn;컚ńf HV?'`;D#kG awa3s_}2z2eòuv3QFtɍ?`sKFdlNǺ}^,rsxX]ǰ{8G 1J۾"ȓI"A&EN"xdʰ-jMburu%24V[CKkj/6Y-K@Eg=O˴U- tn񓉕<EC#܊Ϗ0_rx<ǚ_k&#AV1)Kґ5hK [wF*RԔX,>/$,

HwYk6j~'3 kP6"ϘQFzU?ssB"pnh%q{&,!y5֘]e,U IC6VV 3NwOwXvDqI$_7?V#L㻲}`bH04wVeC_Zn Tݔ)I|"Ku ńH?A!՛n#tS&@᫲~]0Kv'hϞn#e/_C4}Sh_+C;C[W-[[ ɴ~yUh| )NK-""o 1Y.#E-sj/Z_~hs`"#nQg>m;!,+)K<] _a9m4ISq[ա㔴4Qrɵ\<{biiujc]pgZ #< Cn@ЦɃ?u΃ELF\Z|c{US:{[fijC!Q∪c>lILsoNj^* Dž0Sԥ1Xl"U j@0jF۝3rxR um'_MqHDJӀuBM tR%[fa Ĭ`gÃob,y`1Eڦ(xrg q'N>r|?K~g E5k~2/ȶ ( ,V쨳uUcMb(EoxP{+`SiA6!q_d+䡞oͽn!:Nxg y];ۣܶ'*ZaT Z}53doKnk:-1*&˚/"72EO.o,ۃs'_1aLⲆTD9[q,Y mN):J*Tţ/"|zꦔ0r; z;N'g1X10ՐOUe 3[r+~ endstream endobj 1563 0 obj << /Length1 1380 /Length2 1234 /Length3 0 /Length 2088 /Filter /FlateDecode >> stream xڍSiXi<:ʥ$E A4iIcYPpEqpTEtEPDFpe8 ~ު-"'pʉ Wǁ șagd.RTbK0E0EsEU2q7>g63> C U2| bpxَp-GIL @SRTNQ "BvP |6;>>˕,1J P%JQŰ׷P0 (T8.,z o>'pC0,rk1<H0 BXr0艰LIdp M0TkQ)&1d)1M> =i?%r }}D[Éx< D`/5*T(&ƀ-px]PXfV$1AA(nM$(b$(a5 (R&&|@01bX g dͨB 1 hrVRC\- 5uLJЀ'Zl=!׾#qpP+x!.!ުq}\'f8 Z(`9ą7?]J&3PrL#ш hPSɿ )^ o4ŨOihFbpiӭ%fm&"8mmsu3;+r w-Ml#=JղgMQK%aÑbciC0n5za˻FS:N~鵪sNm+q~ŞEʼntUdpĢ#Nbv|*=Sc$I}ç3ra72f*8 k}sV}Tد+*<>{${\l\mUƸ*&+96zCѼY'TۨD2[ENVƭ6sn3k-lo\- (>;:1nn33t;ЦO ߸{%DXTFOA-"NSBvUʯbz>>ض&ЫɅ-'أJ;̐h#f>|sƒH!٪[{9p߳6)-GW6%,h,c4l{Үs?75nmxq>an7XI,o?nq+fA72 YՈŚZR_,%O%y,à5^Z|\/M֝l;=[VO>low!/j&FXq+ܸ2&lFt453SbV^{{z>e}stc9~h8"cm9eM^GD_2aO ;,96y~m&^٥kˤR:Cl}`ٶtkHo1 bkkỊ;Y^I!D(.(lն}?ڈ  endstream endobj 1519 0 obj << /Type /ObjStm /N 100 /First 1001 /Length 3607 /Filter /FlateDecode >> stream x[rI}WNLuEa1 <[`-H ɪa7 P:O橬̬VKk`XǤtLiIԈ8@ \4P,H ͢@0b-Jk+jA$AI*wz(5P LEefJd%)1eTIRSΑu>2=I I Di!Hʹ҄ `K<, (IJ̈=$JLT ꑔёBcF8i /,0B2I{ !X2:/в4{lϜԩ/2H{+sNv;$! Z4 .bS&*żKPG Z$}cC˳0qP-K}ZE Y8l2)#911'[r)aM$7TVnii %JD&t2&51JZR6\RMH'Wt4ZSxu*Q7%Xf-@|:hYd&I4uW ynwOC|ݾ?L/SF {tx1go౅<) m5-׺>q]?90~K_owb:[`ú5y,X*s?2¬܀iTO"Uu]og>$b՘JXk1}Of ]Xق@!f\TAq@`9yZHC !/֛tQ0RCbV=r\\@'L/ բywP+wTHuG&1+D}ͦiSkm!PkDOf &^ WL  Faʞ T^ۗ^Ru0kF0Q3Eb)כzZUp(VXkQ Eqb[Z/1Gq$zj eZQ>9&l+f,.'a\mt̥k8? %i&U(d[1I˒1sJy\:Jj%mV $Ap9oZ=^} TtZfdnPa* t$˛Ÿ?`SHǟϣE jt"}3Mq[}Ա )Z<$~7Ә|Ԃm<ݕ'>I*;sߥq;tڗKcrE+3[ަeECQG=R<0%E5#kL GhmId&*.EvQm`U#%$<GtԤ0Ȕ _f̒ "4r!< jPCJw[Qŷ\ZGh!u z.P)>]G-ly\OqCЫ_5<jC[- V#Cj豤ϑl@nĔ1D4ܓFttζْr7+>vUҳv{{jjހ G ҲM;6dGv3ʤsђP6k-RbKdD~:yvfӥ]T*}=HSM/h'I<єz N:*MS Τq1qHof>h[dU<2kޅYt=yV}|X҃[ ,52Co[Zƽb:4LCǃ\9_H3y3{s,QiQÖ.9Ր{ppjN/qBkw$]|8\. Û&ȸLɿgp~=|?S_L'c>|gdeGV<ϙwdK[o5Y/ :d}~C~,(?姉g9_l$=#{_)՗OW1`x4 t4)o>`v|~5 gg8,﷡v9τЯ7GjjeIq?|2QZV&)דIneۘÓɤ"+{$EzΏ܇E]ngDeXTz;nѿIJ]-Yȋ͠7Pbwt8Na15DDK̇$MgM̱f(&Gk׮wޫa)/O `o Gg''@Wk.%B$ޛ%HWwm+nsVJ:O?{ZoP'f`0b-p O"h:"> )O}1_ɳ1:m²F侍FJ4Ҧj,kdF褡(lb_m_z\o/WWA}O%{gy׵]OrFPn_VtZY;uR+tg[ endstream endobj 1565 0 obj << /Type /ObjStm /N 100 /First 910 /Length 2138 /Filter /FlateDecode >> stream xڭX[o}~߃B;"A%iZF@`\gIЕ6sΙ$~rS7y 'O1zIInQOf˔sȑN:n$Q]T2~&!QHT T*gJdb@`vD i"808MZXp D]*++ǔ'O"Mvr[}pVHؒ1ؙYO%rC2 MÉ28qVE,WHSH.`PwRT*2ībdIOH&,{,)B}I1b=04C"&) nUx#1a>Ov$)aM?)M*,|eRaI1|)a_ [@X'">hQ'eEN߂H(\adFT l, B|$"H!K rUIp"bP'bEE(pjRHsr{{oo&/|#}EOcAD~'NRxo_\Wc~)#<Ľ AMA7_WY4Z3+zl9\5w=(gca-9~SEx\h i퐾6lx^eh__+mƷ`{}Uwu w7_bf<\Ϳ,UЀ0jmNi ٯ%@䫇p]H[W|8}x(־s56,C`ҰXVVX|4¢ kkj5ܔ\JmM5%؍E5N$T;i K$>< ֳky#Y2Wtt`Uۜ׬XMtil*;PxZVzRiکMR6Qju^;祡1Q*Z7yK>iFD+Vcnd5!49 沥!9o$ eTMкq^FΧ|X厰sXq{kC`+Up.W,: #ՂbkB=!0c@GG*E䞲:;y?Ku_кqޏyχXMW7]͏c9~t̹scŚG> stream x}Kd7wgƒ! 1xdL C˩> ~D˩tFWTz= :NEP?nHNdLN`4eF!EPV,g% U!('*pUC *G*-GVO嵮@ sB|ŽD;,Ji9BʇfY-<:yպ"Q(]N/Pu*f]t.ѡ, \4R_e^#/^W{ xDjGg$b fW ˮ||Ƿ߾,}|m_Zu}zu~%Mǟ~YB盹fx\vrl,Rk|orX瓮ΞZKԴ8joZEU31DZ#RMKbkf@;xLKS-vZ%ӢT,ܴiLK 2Q^SUV{MWǽFܫq)׈{5%^q/ƽ܋^"Ÿ{qKĽrώ{gSq/ls=;9➍{N'=GܓqO){2)qO=7=EܓqR"MZ}sܷ{xr.$xxr.$xxr.$xxr.$xxr.$xxr$r_%ަ7I7q_yTqr.uf}7<"Y o`YӲߧ<}h~bx6k}4ױuu>$fZ%ֺ6ɱ~ruN'u[nUUfQ7'Xm/^sV߰;γaFOx咣[!F57IJxK Y%Hmg%HP*qWy_P)Oپn6jh^|Qms.O+vuAo endstream endobj 1604 0 obj << /Producer (pdfTeX-1.40.25) /Creator (TeX) /CreationDate (D:19700101000000Z) /ModDate (D:19700101000000Z) /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.141592653-2.6-1.40.25 (TeX Live 2023) kpathsea version 6.3.5) >> endobj 1573 0 obj << /Type /ObjStm /N 61 /First 563 /Length 2033 /Filter /FlateDecode >> stream xڕYKsF W1>dL&3IiNmŸʒGXc7l{H% lRX> +0R&I)sVWKF/L"$A§ɂ?*H Ȥl Z(m`qǃ*p#e0\.!?L T0&0e$ [p%LD42NheeP"@SL$vNa$J(1ZE4 QKd\3/F,W"ڎzr$Ύi@2&zJ"lJ&1z.nC5adv r8eN;\ )1ƴqXqT*axE7bU,5" ,=b5gXY#*alk&^h3F^30n Ѷ=P5~4+3> eFn )]M:=Sjݨީ:EWGavfcC\zPofmaתz@QY׫ ,ڙ^V{ŌzB/'QQkzԛQu,1aߩϫ̆jW]ۉߟ OS,fe|K|bܢ)?R+ȋxV{lOo`ύ}OLL]ZPly>nZ^?n]L;q[h~775-3ݣH^bׯǾ9}CmOﯗtјzpCw<ᑄ0Ӯ/yUtߟ/u}Qh?5Yl|tpУz0iɁw {.-{u<Zy}q]F~b~iz:C{*Nz괟 !)& ]A*_WsNv}f'X*lhg]~y>7]H<ߟnv;'GTѕ~Lb 念]8dn\;BTi_l6"g:˸ȿ0lpW3..2;dʣ$&lb @J+./e+/ ~vߊUiBWxDp[ wnr~!ص?_}|nxLl>G@|s>@ endstream endobj 1605 0 obj << /Type /XRef /Index [0 1606] /Size 1606 /W [1 3 1] /Root 1603 0 R /Info 1604 0 R /ID [ ] /Length 3706 /Filter /FlateDecode >> stream x%klYdI'qKqc;Nlv'cǗ؎/I HqPU UEj{$PeJ@a(,FUϣ[{sYEQEQ}dQ*kQEؗi9u[MkZ~Ee_+dAw^qv,JiP΀pA#. Z@+.vptN.  5 `78',:f~?ӭt>0` `^&$4p̂{>`<` <@'ZkX`<[`]<{`g98/K UX&|\ ;J2fQ+Rj<ST+RW8΀shea|wDqv :tӡN:tӡN:tӡN:tӡN:tӡN:tӡN:ttӡN:tӡN:tӡN:u&@:ЕCW!9+[4|Q~`\7$wx@>u:PCu:PCu:PCu:PCu:=tӡN:tӡN:tӡN:tӡN:tUu@ Ġ@Ԃc8g@|-էNOq9XAu Qg:;Nz@>0Eo#2f,+g ,8΃Fp4zVX?0ʟʯsH3 &D@BH\&m%jW mo$m&JA 򏫴]$BFiRMu с Ru0JZ]hSoqz 0Iz"=E4 fHs̒JM}R)lsIz H%ч`T]xD*y RI~<& 6İ.Me'@fƒ"/3D!!^upDZG{77*gn!ieRN1ҧD,X^!e9Km%?E,sʘדnQ󼁔%QI~1IY鏧tͤxsL>"9&I)OIrLa29HG?R kKDX#)*ɱFDX#)ʱFy"\")qE~",1Ds c1DrC3DHu2ON5poH F% 8//7Tjn%^HGTxj!yaHzJU!"iW6\6 lz`\6*~R""٠(\yM{IK@6!U@6&:HNQiJtHDgAtHWHz HmD-@O.^[ԟt}3FpaLu"MH5*-H$~MaH爆į^CT z h9o94PGt*=pB:dvLjl <Ah jցl mǜ|6#򂄹BrD KD^HԆBRG\Tp ] 6i'eZ^H8yx!yJĂx!aK\dzz^cZ+BMD (q@cRT`+^! "tZ`u.Pv!GDؠ E)0D!U" Q` 2($ ^HB}uA (0DC"AM(0D2O! C"O!  b-B1ٴγ .0D!;D ^( ?q:dH :B2ID#ƒiZN hZ{ R0DYQ"@֚Eʑ!F$3B(MCDR G 1@! {F+Quw؀!A 1!%*Uz>T-VrEI WD\It4Z}! = <+#rbˤM$٢j~S-}togդ5N~RͭˢZ~kǶԦ>>>oJEJo >st̀)>?*v+DE=?`΢|X?%. f6ն6-JwE_{;Ru;O,z'C̢o~\xaѷ-٧Ϋ j,WJy7Z_+Z:Rb|Q'-(EzMY Jy4+mMfg~U^jثCAը\1kR^+YזR^+=f?Q: }Ukh \!`lwr JA2aF)ؕ)>VZ^+vF,/+孼_)}V>Ju]7˼eO{6؇+Uv~yٛL4伶 (wVgEjAgu62ײcfaղ:/T6{RnY͸WPrE?s ]Ū:i%fXQ[h7{Gx:޽4=[66^HcaO+0NI a~u٨ٿ_Q:n}J&Qz̘Ρ5єa,3{҇`rRe+Զ,>kJE dL;)Cٖō("۵"Ք=fƦSRhݿBם*-T٦ţT[eǿ yD[<-c @9jC9s={f,^)Q`k:g^|bR@T?P@T? pX w&+Q)(""("s`,TPI@%eyb5V#hj>#E~EVΑ +}[Ѧ>vUc+}c^і~hʍv<]+|_+=EOh?znz[B6.q]nCA .}()`h;h:жmK?m_߹HM endstream endobj startxref 398135 %%EOF arduino-0.12.1/doc/arduino.qch0000644000000000000000000046000014545566645013111 0ustar00SQLite format 3@ &.j  oA $ 3 ? oX''qtableMetaDataTableMetaDataTableCREATE TABLE MetaDataTable(Name Text, Value BLOB )t ##/tableFolderTableFolderTableCREATE TABLE FolderTable(Id INTEGER PRIMARY KEY, Name Text, NamespaceID INTEGER )| ''7tableFileNameTableFileNameTable CREATE TABLE FileNameTable (FolderId INTEGER, Name TEXT, FileId INTEGER, Title TEXT )t ++tableFileFilterTableFileFilterTable CREATE TABLE FileFilterTable (FilterAttributeId INTEGER, FileId INTEGER )f '' tableFileDataTableFileDataTable CREATE TABLE FileDataTable (Id INTEGER PRIMARY KEY, Data BLOB ) 77#tableFileAttributeSetTableFileAttributeSetTable CREATE TABLE FileAttributeSetTable (Id INTEGER, FilterAttributeId INTEGER )33/tableContentsFilterTableContentsFilterTable CREATE TABLE ContentsFilterTable (FilterAttributeId INTEGER, ContentsId INTEGER ){''5tableContentsTableContentsTableCREATE TABLE ContentsTable (Id INTEGER PRIMARY KEY, NamespaceId INTEGER, Data BLOB )x--#tableIndexFilterTableIndexFilterTableCREATE TABLE IndexFilterTable (FilterAttributeId INTEGER, IndexId INTEGER ) !! tableIndexTableIndexTableCREATE TABLE IndexTable (Id INTEGER PRIMARY KEY, Name TEXT, Identifier TEXT, NamespaceId INTEGER, FileId INTEGER, Anchor TEXT )h##tableFilterTableFilterTableCREATE TABLE FilterTable (NameId INTEGER, FilterAttributeId INTEGER )l++tableFilterNameTableFilterNameTableCREATE TABLE FilterNameTable (Id INTEGER PRIMARY KEY, Name TEXT ){55tableFilterAttributeTableFilterAttributeTableCREATE TABLE FilterAttributeTable (Id INTEGER PRIMARY KEY, Name TEXT )h)) tableNamespaceTableNamespaceTableCREATE TABLE NamespaceTable (Id INTEGER PRIMARY KEY,Name TEXT ) =octave.community.arduino   &%$B  P arduino.htmlArduino Toolkit - a somewhat Matlab compatible arduino toolkit for GNU octave. ManualFarduino.html#Installing-and-loading01 Installing and loadingDarduino.html#Online-Direct-install21.1 Online Direct installBarduino.html#Off_002dline-install(1.2 Off-line install(arduino.html#Loading1.3 Loading6arduino.html#Hardware-setup 2 Hardware setupHarduino.html#Programming-the-Arduino62.1 Programming the ArduinoLarduino.html#Known-Arduino-Board-Types:2.2 Known Arduino Board TypesJarduino.html#Connecting-to-an-arduino43 Connecting to an arduinoVarduino.html#Connecting-to-a-single-arduinoD3.1 Connecting to a single arduinoZarduino.html#Connecting-to-a-specific-arduinoH3.2 Connecting to a specific arduinoParduino.html#Querying-available-arduinos>3.3 Querying available arduinosXarduino.html#Basic-Input-and-Output-OverviewB4 Basic Input and Output OverviewNarduino.html#Performing-Digital-I_002fO44.1 Performing Digital I/OHarduino.html#Performing-Analog-Input64.2 Performing Analog InputXarduino.html#Protocol-based-I_002fO-Overview:5 Protocol based I/O Overview<arduino.html#SPI-communication*5.1 SPI communication<arduino.html#I2C-communication*5.2 I2C communication@arduino.html#Servo-communication.5.3 Servo communication8arduino.html#Shift-Registers&5.4 Shift Registers8arduino.html#Rotary-Encoders&5.5 Rotary Encoders>arduino.html#Ultrasonic-Sensors,5.6 Ultrasonic SensorsBarduino.html#Serial-communication05.7 Serial communication8arduino.html#Addons-Overview"6 Addons Overview>arduino.html#Addon-Introduction,6.1 Addon Introduction<arduino.html#Creating-an-addon*6.2 Creating an addonHarduino.html#Addon-package-directory:6.2.1 Addon package directoryLarduino.html#Addon-package-_002em-file66.2.2 Addon package .m fileLarduino.html#Addon-package-header-file>6.2.3 Addon   uu'RxAn0EbdY5ICZ%gYz %U]F[1i5Kd/*mE%kIYt,YIgV'P%Ag5sa30˗+N7[!џKY1Jޞ_Ar8h$ ̑ݗrďF xn^u1lok>4JI Nq!L}w ځ_! e* 5tl::j속jeʺy';:)xkw8(]'δȒ_;$8^D{IwYxl"Vd6*٫\DWr"fh^Y#fe! A.2~h_4K m%shz".8$-V_^(̓3>8MEr~I5g"go rmc '欽JOD]Gdq(6;H{G;Ko8ӁҌq;Al1l#.l#_NL8# /и}Do9 xa׋}>GWg_#dB_2>3lVfQ^^y<7fc 17| ?aq o賺{qS/ Mћ+q?dd%_lnvsG22S(-2s&o"<'Rc9aMK|g/q<:;fhpFna_ϙ7mfpOH(OUyO|9< ^}t樯f3{xk{dנ5[ ≃xe+߀lhZjG#:f|F8F-՞MC͸j^8`8sQUeE,EK !9e[1K.)o= l}ht Ӱ" (=~}0'acaN>ztv"en-o*;I}>B6ܣƪNzx6$ &!stsٸʾNTEsSއ 3CeD5xx O{!vmZ./*=:;ey{w/.y~vI&N6l(qA).M5&Aǡxq+GBon;2TT|cw8p("-g)ߦGUkOyoBuo)jf\{3ba/=e)SO;3&VqܜcՋ\ :zH9Zن~&L= B}\hTKD0ewp\y6˟w6spȜm)}^y&J3\>wn~-k@8C/ILVn{.FE.Lt:/fCr=Q`=lrI:-V H߬}qL+qk|Ij ׉?l&._$jfI qjM|-3Z4L-v }C^~A2klҬC2/-٠C_^ Є0O,y? Ֆ0`6җ$}Hvn_Of،]7ŷy ԡcCv] 6*K'V+_q-:;Ԙs~ 3-uf.}cHxo֤nҥGd%/lƞߴCO(_ef]mK`҅%!jjնkIZgn,ɾ51uʐnԡc_D=wY7ķ|mGs"ݒ:`lu^thJxjCґE4OَΪc e{Eܼl<0qmq:?ϖ(74f  xx ##arduino.cssarduino.cssa %)arduino.htmlArduino Toolkit - a somewhat Matlab compatible arduino toolkit for GNU octave.  doc !qchVersion1.0C/ E}}i'd -"G[658/L3hCx a(^y'e(ܶC : :.l<ԟS?f= On[job*"M{T]Vƪ} w]GD(I|h fQ}vcmܒBOlQYnL m[ Z)`i'« -bBޕ8JؕC_W}׮c[8YTcQ3AޘOB:d>Wd֭:A]rv+y7tpKJ h!E @>F,%PZh .")}fs*qƿ{v(DSH 94(:n&KֻNXrE4/"Kб^Lf^NkEf6hت O*Ca P qO]ܡPp];~XxO\k= svձ[u%vҕk8q;9ʒ˗|Oܸ|ӛ87wqmtmu#'Xn}Wp!C(P 7G7i# P^GDQ$`&D:Q蟶S ;Z# MSMI}]jޜkd$@M[[#@d<Q D6F]/m&j‡,2V@\G?n$nMI"l^P%6O]Ӏ%:nD7( "c6Z idDRm\<j֍h{U6ϤnOz$Mi6MlXv8댠A Kfi4x4L_3d+iQv&e Tn!D]>׆NĺG~E--ajlб//f;XS[a/Aԝ8jQPTs~%ujKȵrq>>݆MC$$ Ce% --so78Ʉ9]IRλͽ~AV;iއtlN;oۡkoޝkB\=OkO;tNݧvz6ѽ-Պn0'=-kytgˬƎ|B=W6WM&)nx1oU3i}wv`ͧ,|Sz#UɍbA^qaQW`_lР5`=:oB=qP/A6mDE\]{f$WBB6YėQy[P&|B/_B]r5kBgU[ty7PlAHmm+7qI1D ja7T}A.wRaI9VMh/p>b:oc0cl&euG2w^ve<9+'c*GG$F?7X$tI 0 ĪLn4 2{byc3.,@aFQA R,XU>:Ԩ"]\S>0()<(9$r&,K RQLZ'W)8[b%A"KKf(SM=VYGg7j IpLl[r,@XBZ.8 ) CS$+@a᭮TK,Ed1\YN ܽ1<~6[9Ǫ;>:M9 8$ xOϷlֆ#Z jYs~~/t\*_]6Dbh2nVg[z\sM@DSWuT =\7/Uh[LЋWг1 $_-xF k  h@30cy!l&k $tMUruV% (=jFeʇO:T)yR:302}d˕[hviK(W@ΏߨpH$Xl zպ,A-$r9iz|rXw bk>E}@=q)Pf.2bGHOZIҬ4 ŪՂxJ{&ľSAPT29X掟Wbw;.Sר[ݮ D7,6/_%),]*T_+gY?my|Et cu aL5:u?Ӣ ؟5<8'!K9Ṕ1}h ^Q 4U]Cj\M<.A\)X2͘t$dEE m$LO;]\(&:o>ՇyMWGxF\x^qsW`< ?3?籷_]L<*{)~JMr0ٽ,h1'b$r/E,ܪC]ԓ,^$mzJM]Pb N4{YD*.3cB^\N H0;&}"?wՉ7)Tc~H]ZK_f8d+f?aAc>d,F6S3LʌP E>2FCh;@6L101\pn옰*Q7bS_k1DoO'ۛd:%QNF=yqAAE()lL<1]sia)nbJOWeA iZãxLƋ PpBT.ʯȧ7WhSY乧Ql Kc3D2hu+"TxaK ->Ow1^j6L MGӊSdu). V{X31cU+V 6a*ŵzfb~ʜwq ?5Na%klvk"\/ź, 5H{rCvG?RGm)8!E"z5пC*,G{+[(LnB װF[p*O:'>y7ZQnUa( ֖t ِ2Ss4N`a-X] Z6K3,7o(k&W.ĎFE',:L jJPeBi#Xe)> @g S g#x =ld*+uR.+Yf9-Y^BuȮsI fJuCHl5S X=$B9 HTO֔J;d_`!z]ŮbC9ztfSb&GgF1#HJdL'HN-*u=LAIlHo4oQs5*ұ\%| ͽ&"^AhTMGT7ڨNxGx+n;J2y$&_- ?x3d`Q xm̌I>g@T'|~@8m[b<[Y|qNwO>TZWAW96rfAK\iFV/zBo[q8G'r)OmW Gbq<@22m;-v +6bR,0DŽ^73fyEJbJ 7wSyIW䂲t_&t`Hs. |ޓOqrダZB nPyݿ:!1,1R\/!?0E&Wid>ÀåFE/lVuU`0n~ S0Zu`n)x$n1&/NogLJ_=mV:WQ-ct$˒W viBfbB&d+2)k7Mdṧ:~:b_(?(,v},9%;A^9}yI}f7D ppUTwKw0T4g\zuy|!ҳU< 2Z|F^&U`|fnՍ)Evmxv˷d[nGEzQ7'B 3u psHBڔӮxV"4&8agw䧧)e kgEHK+6f}^iWav;sW0u2|{{'qb'yGJ*aޛr5#tR|% y]6Fh 0Ԉ6kfJL,XeYZjayuE)^Ke UA2w E}uW4)hf#s6] `|{C-XFGbVv)džQ eHETvϘ< ?t!Z͚)kK#t*=[SpdP޵.C>R.S| .\ 'mDRTBg TqP,D03{F<&꺎h*aL~4H2{ZoCʵenx8p "pg'o8{jXU _%3tHOpo(!dP'1~<噏]U!X'[&#sh m*1_'"q Jo۴ (rCYL3JZF"ذ vE /d1K`+Z }-Ȓ(ȓ[򵆈]aI \|ECF! !F?txԝ,rHYHl[X0lw1Ȗ1yX)b?_ 9߉OndB!( )6T*Y2wU.4 JT:u|WG~ď\ǤEUE5GDb}jjS QU(䙜6h|v@,E/paҾ[q6%AkF߸DZkC9\:a5 Zx-^hV&TRܤʤNRxKL%E BTO(I9?'xΞRic+?Fl4فR aU$Z<׽iVT rJ+aPrOP5lB\_Z Bjf o9۞/MdxF G ê{ƾ񋯰j_GA2Ȣ9{Kx x"8 k}_Fa<`DNΥ.FNxwW4Jx8?xҌ3|S:H®:&Ѣ+S'LUDT|Nݰ椩#VoQ•.f5?Dfjd0hZѠcIh ,guc{ޛ'b$=pOx.~JH2p`ĘH zn|2ǓG<ǐ,rxdgF:NTnT4uas0 Y("e- 2 /2I/$ی̐z@'v̰]a7a{E+tօ'+gϷHK jJɱC[! _̇ÐgDrH lxH$!$\CƇu{t-G]+9ur!?_Ȏ}^u#ZS׺(u'f$lHd E.V[;q!Be:u Sb enc-+ЧQ6Uu 1 Tz߿|W_'xx,o䀚)2sj;4DDLZ9nA@sAu7 g%PZ3 ?#¬6byYW 3_p!I-h+ g/z~P?u}[:؛q42N\q.n>ЧtY*B߂(MqA8-J+UmzDlΥ\?7MRuW>-R|$ڊuT U q>\V&갘Zhr+g2pmb~f]#Hi ]QIxw m$8ZD\Ko OmUqcve*`71v49|fWfvq#Esw'g"a3T[3 3~~q_ablq<Í HjǗl%7j_| ՄMƲFem4 )v" C@=SOi|'KV8IL/_XaX5b5G r I!jHbTDP(~`ػQqN=:o2v[؛`uSf{#{dg lUSGe*GdO #}kQ&6ɩOCfh̄L/ZTP~Wuxvp{ތ:~C[NZQCEG @%Vr_>ϾPb34,Z'"VyG9x V%>ԓ柲 (3ТZ/u3vq0SGwPN4B̑ ˮ{&fͲ`lf$63nၲ4w|g#̩FHt5"M`B%]d "^ G"4#i@lA |Tg߼ \ʅ H UI} d~HxCSɗ~7.,*涼7 'ȗBMJWC5:mfTe5DV H۴ԿrzBqbɴ^Y+1֢6FB&]H|0ţCDdUr *7`rTn$UD=b %meYPuȵ'w%j]NX$Nh?2XN va"p/]If3(G凝6luYj^ON&.sf ؊ ) p/za%5_MazM_^CHK%9 9C̔Lf|:O÷/w#ÏL^XSvGn^ݨvW6ߊIpy#3ո1K}Rȑs+Ћ=7$}/b}{qjW5D9 cki&fAxq+WA.OQc)ϚBe/r?:^=@`oPDH~=voX(v@tHA9ٹp1$ ۩P1oǯؽʝ"NmMRlx8=U)?B0 ET-NjPsޣHZ=ER][^T[ Kgkc~To[%b{)cNDYM:Z8'j NFOh즮Mk5tؐ#'xNnylTD»VX+ $e5Comq@S$hnQǵ_iӃd8{v ,aTakUX H^ \FW*8TVa+e5 QhK")dkw"r@ Nw.0pUcv:mEn9'}SsR nu&ATNw1 n2۩:YklUG7Auڋ-흿} {KI3&xe#&xu#i3>q?oR~|}?sQ:^8(Dj&]l}'I.~|*AW8ɟZlĔQبohh}*J*55I|r:3os{Xh J R77r[W[>%ւ שjNEZ/'l 6}\QT o 0AIAy%=[z I7ۿ}^_|Me?~0?cǁE Ucf?/ϼ ?U&Ifgz=RqE [*Ď50|B0,q5K<P]#>>|J$F*^cT7+@oGp9ja/J*E%" ijѬ\CPd΀;8FpB| *x<~pcK#n,N34S0o^Ǟ:/: u~3УE&"J(hAm~ l3Gt\ γ5| bVI<[S`83v)yhp~NOv ٩:epeB|lP9S^@B7(]1˓+Q4_ 1`%xF!&[Ɠ]~H~ (ЦJCC?2xܲ háBO#l ?!a 5Z;ȑ4hT6pfԲ (lHN5tw\n\7,3ʓ2R숹F DqӉmmD_왯;^ c#AUnml6qƹGx7\7]B}=ӊiȮgp7<]&hqEݗZKkS̊fh^Ȝם#,E<aA"6I}'D|'{&@~dj 2=99O=5g sDi8ዿPb+x#,)Z+ݤYm#=>5p]4l$j+jďG&xbLi#dĝNn*Ƅ/v {e6bYc\*7VW0\BIޛCF?.e&BxN#64oя ow2F[Idf(A|r˩BF5X˫$hV``Y+'#!Wy5 W|8cEZ>eJx(`B!yHC}rs׉M"^\*и Srgtc1 !u2^3_!,GH`΂J0qΌ\ v 6) mVU 3ԶP}ŀ=MŠjv)6nXr.ME ngrG >4%ήLj*-?"6HJ%=cF{nn_&N TA&?`k' lɳ RHBJɵs o(9g[JWs}u~*mobSt~J^ʔ y&nHj&)E"f18bG0-NvGm~J`g*4U\[1_ʪpۊ& al`r٠Ia8mC.{Q6;wFyA_o>`)8MHrri9MKbxi:ڨGcbq_@ SpAr~ͬq`BA۰:e( -sTv7b SRHN _Qä9&Zp+~Z{k̘lH[@pWǮ+>T|0Xg8T|isw db׋Hl ]M) eڝ`u( Ҫn/ )&~L<#hUNcD~VE=0#L!عyT`bȶUfnnc^~ױCyqVaJ(^i Ju<>K;(xqx/xd$ڋ8=PzׅMvڵB!/nF] ym:t+t.Vtu+\rݸ58 |Γ(u}Dբ%X3Ӌm7۵EJWFdo7h6ߴOjei 4I/(X=(;a%x[X;yw|W-|YCM[Rz-T'%MKDеog m'w Z(d)Ճ y H+޵ GwYjΟ| DSӨ@WѰmܒD-)hց'Vĥn*sSxU_ۦ "'K| ,S=V $259oZź?-b *+;o:4Pzjcʃ+:8Te7Q*Nށ[dmҳM\B}~7i߯1\B}FOI_qeŰ?Mas !$wIͻ3/^Y$ޅ:g!GF+| nkFzX0,f23Ț]?l]1<,C4 q@ׯ~kPAj; C5&i&zFVetЖYvu=r#b"JDk* +8I TB,^ GÜ,Qۻ+1caIS*jcǎ17"X(JL>#'g_@bA\Ū ~4V3;Wz5fxU`1"BxV3sYjči뛊Q86NYZ/xs@%QeB+}UHBla}V r .*BՏZocVj\s̉\e6VR&9T6uB}v?ĝS!y.j@U+o@Tp]e]x|*5dȡJ˲j3,$, d@YeH&/JE-8Ɣeā!ڡ`0C*)TWͶo5ScϷ7| Uo7[=KtX,fWYE~xtANT޼1'G{8O,J<(YGNH.8Y]y3Z,kvl@WFKQmio\0Ra:W]ȕnW) ̓:9_b`BL8lAtjYl#xkNCiy>ߏ֋, d$ 3 Kɓ:MAJYhn$|8盿$ZNQ|v( ,!ʚyVfl?#^/8| avk|ӫO+QħYqou˗̓A)ڏ$i?C7@x&^}Hh~PbO Y&.Hg SCŔt1ZT?E% vuj$6 Gm;TUDBxWu EPWAp `FM) E '#]F.;T35v?7휺~/syf l'6zn-z -6G)&L@'Q!Hǀg"{DyNtDN<1T a& b\*34 :y5̸8:'[Nl.3Rۤڟ?m\ [suu)RSʐ+&3>Y7~3$\K=jvGhWzCyG<#]vJnpBz!?[=Dp j3}F-9myo6 ]5L%l&i}YE gUn(>GH aFtl g.p| Iz@BUmNJſ͒}yɪ!A&:Us͒ȴ'b֔`E=0,zرZ* a#2yC_e{FC镵ss~jTcrqIgg aP4TGptFsW!(t H_G nlJk 7qxqUVK-v.A-d_A@ePbL}'eIY.$@}cJnDP2]+Wpxj ;W a#EP w#.)sۈ @Cpd2B߉GC z.s[ほ IIh27P T]uk=u{ CP>q3|Z>m]6Қ+ןvZ쉍)uƶT$Wl#=G{HYD[(Al*8Z}A?HЄ׿v`;joce͛ j 9ֹM}Ncg{8qle'[|uycU=V5"n~/kCz7HϱZ77u6; [!e8t_6ol2z7ש^|-l|0Mϱm îN:6\rɰq˵ֲʣ߸uY S?W֭"ȃ YGr ڀU.pn ۉ@Q:gC]ҿk\dcthJ)wH` ɦPA+\X¯W !cS31 ,Fv}CvLމ*ȕTTģ"<})3#UD(P}t$]r`ÚK"̖"U 0('%ӄhTPK[hP! 7/Q9O+` &95ȩ萡~L+sӥm ^*n8 ␲Z':䐥8)CL'^%[o 1S_<)S:M}Ѓ 1s— GzmnEFU@܂_Tw_J wg KlFutijDʸ씳Wm o Tz;[;CΩH0euшD*+ VNШ2>P A烆ܻU,,FD*v% [yXcWg/uU)t xv/JI;kqRkg1ޮ(@(WNrE' W^ մ(\ڭ6\t +E7Ӌ Hd_>.C;[5U^WĻE?B MS\RԔ t*5>v*}(\dhb[ =)͜= <&tqڂJyWQ$p.G&!$Kή651"L;ZGPAވD L2bv.Fdo4R܇Y+t6=ize2p*ټV&ov^Lr.?i^hCzMNG+bnm˞F4\"*#%@MhxAPspԣ/(q:{yМeQ@T~lCyl84%߇ :ۋD?pެóph|VSVNHvA;:b*uHt: lN?<)D~BUp ;+.~*Bble! up7Yqb2\jE 6xt@v&!]Ѳ'A/(S 5VeD᧜xl!=St{ՀYC\D6ـ ET FH,3'r-wɧ!>gfG<[?^aO*MrS|_;_$Bl|~{\o:Kb>VHE>t(9uNNe+yi8ϘTl//.V~iQIkD;B6ؖvPaG p;r-"ʃQkͻ6ig{*~hRԛ.x7 cbmU>A:R9w$xnE¹@@Cq@-l"'6c(c). f|yvWP?..|4<'m`në(-L3nWGyTrQ$ -f _$W:Xɼ(k @NrgCvBV:sBO'%Y*m mBr@tO5-sW_c\.sOCQJ#!eqA}PfŜqUyvKg7y\Y_)W<tYĻNbq$rI5ffjZjäDɻ&4:̃ V!Bph & C4{C$$bORa֏ҖIOr \8ϝQ(#8hy#JL삜NaөRnЋ>~‚۸9mN4:<6dk_rh7)P kOwxmKnxzQ&E=+U@_T\le(z̿V=kWq 46aӿ?T^a':z݆ ǢỻVNvsić|Da\: A.$דq*I0y84ݢ4$P]O$I3?YSej ]x[]q΅Њˍ TPAh AqԈ2>  'է!v!6 EkƘK-;Q?wvECصK}y8^p|+_Ȟ?B+'Ebm홋4fkM CujTк u#BY ,HZs;G[/wڋ;9d6l%w]"Є 1_h?Dž#]t_,l.sIG̊ڕ 3xZ_c *]b6ɮO8]#{7\b^Mze3X:*j  Jnjջr! Q#v?n#N>RBLN)X͵Zp^NG,ÈrId|%rx MVF\HaEY\{W_љѧL|ԧR!cY ,Xcq2ʗ71d"Hgq- WdS@X}~0߾8ƨp`Zd /qW&gK;S0?W1`Q7Y=-(PG&x V&c$N;=:_/EXNAI-?&}}~ͩ$}u]+*ۯuu'L)=Zî:~V͌*?:3Q@ȧɜM:O7fgepZ i7 \ԢMM4s ɐ& ԫ/s mSgÔ4n[(0!50DӉ_I2slPxz]:(R9p"f)\뵬I\ͣH,K4E:tUTXKuhP~PպhT[RBEHC*=!WKB ¸$|^KmdazSZ#)Qbec.R"u͐CKE/s/ :Wp],|H1,NՑY$=W;̫+IGj_EHcϛ˺Ҩ 0;J R?Ax<\ؓ}`OH$߉i>;: owI=ӕǿlJuwpW׃ GvuoQFrI@ al9!F6d解rd!J@U.QE5%j)?(D)`+*t`гo1yt;=/Dѓ®5DuSjtI"erM2)g΁cFNɋ-tᤋ8޴`0G{N-7m<{D6мXŮUmMm;LN?mo|J}oקDoZԔjaܗo sV[ImCWxGJ* lEaypȆO*پ<|O*HifC!dhvHiz3H!ƾHXP-OlS ¸Fr62ab}Iƭ8t2l;)DC_eTDY qjNWo=SXy~hݠqLc m<~X/]T~Fc)#@;AO BHpMMω)hsġAȐhMO%ŕ##a8hmEEeY(@vf hE;L$}p Em<ڜ<N̓,k| |E~ &-NQ9qΡ$T;O74#sFm=\װfu)9_q8Y{V8Z-gltV־f@h1e0OKIRĹT$0U#-@y<4'pjI 8gL)O~?SVcbSC˶wž.:]'<\aUt4(n^*n06xvD}@n PQÝNE|S4'# I,U0 S$U&'%Xx#ڟ配Wt]. GE$>6>jy8hjK{  wo+y;Ce!GMx >\YV%wi3Մ]\ZتžGMWZӕ%|~&MzP!"`9F?J5ݹ8vn d[X/gӮx(2a3þncnBϫ `3OcR/+|:uuf30KM]rrlu{0Xkl-ڗ/ٱ/_^7edYU7=٬Fgֶ:^koH2d-ljӮڶm!6 `,/Vq[S{\ںjPX:ُH͊bI5ktfw/4i~'7oJ53X=PT% mU^R&ںt6 EPAQv'?abWހٷ.!I5߹'i[}(nK{E@fEɭoO^N1ז59;53ڗ 35/ξ|t:?CLlt:)i;yU2ƙm;n#phkGZ F?gf>Հ5i#H^K'ȥ}иܥ\6l=L`C!̦nB eSl"W ~KÚM~ݴ,;[O]lpnwb~@s{]d|#)Lo/h;ߎP W֠9dӴU$*gZR'٦hO{q8n &%D9Y;ڶw睃/[L Y^0zBS?WQstnCzX1֝XMn|LwyNzN{~K{[^jNjJ7<0J)~V6rhcF+7~ m;> b8[^n} xICR^DYNrS2gR(Lgs ;'3mm^؁wѧ9E:Vja5N譽mkL)uc6&@t.Kp>0^V<@G\$no\'C R5ݻJ'u虌-B} p,[?i}j TMG7h7' ^}zANO:yAKݟOZ&{ټDTZL;amb/{bϚl3J7tdO іvǨzn)mzWm?xͷ99qg\?F#g2:Jp=]CϚpz]v櫤]][]^L')[t.{*{xPՒ?t{ 0N?9`_RTF?!oh۹ykS:+-=iU}`odΉIdOiPT*%L,(^>SUbJw*vƶŽ8mh|.ybLPۇu.~<ɫus8^d_>K:9CmO6xm>i6XoYoOA)Pa|' ⟵0pR*z.n|e `([8WL*.9E:&o1]'`'OnZ .d2Ã)r=p`[bVk VY4ۉ mW-D49[̙z#"DW6t o|]Ć-L94պh29l`oRXGX4&s[_I1,B`)t6dK5RF$ءٚHݻS&++ZceRKreӌwʶ!]d8#Z3#bhĩ{dqk)0r0ؐꉎfvD@&\[q!@;Dy"(5OǕNN lhx<<>N]XE`l`81p~L'&%ϥYd- 6BqyۙmIa `.Kנ-\':JP9OӋ?m Fƞ.5`0dnϷMc%ZQ|Jp4WBZLbEDm AָsnTa6X1#2'>9uVݮ'uw0F:9X8F4 7n0(mt5Irs0¾yzJ蠫h~NnT. ֓z-~fICPZs܄x`&Ľrw]ߴq4 G\x!P$^SX"ћ?qF?1 ڤ&"͎[zIÕوҒhykXJ}<EF!+w* 99Ho%ĿvX\ޔ)>ʓN-ҧZ'^ll'm&ףGi*ԓh>WVZ'躜z. }fiD]61(;댦 RGj,p۟WO8۪"C-UQ|:N'xiP_RM*kJ51WhBOMSvsU.7E~RSژ(Ôm(q.-hZRy~k_i]fPPf[/ ]n,}VشJ +g ;v'խ + dSUCv`,7E-UƍJ̧(Q;TQ6o~p?"""%mL/;XJoGi]y)ln)]͆_J7@=^NG H[N7˼uD8^r9TGּPBtSλek+, r y,YNg9r/;_U9ݻtPNςM.YRBIϢEu ͈},TTg'A,X]ZT7+ܱXY`j_Mm5gW3.%b6µ *_YXwuS+{knk^Xgay f 贯j%_rPGkN:N=ݐRHզLN6LK.>/Zl4}(!ӛdTW05mLST^LyA2,b2Vhg,h9h`5PBp'ur8if.8pԦYɒZ |J1x9cV7ZՔԅQvus-wQwhvSpLT0)ɶ0uv%NE |{bɓˑZ. dA֑pvd׌,zr %j@Jr% yUW+9$KY9xxWADD# ;fo}enNnY7GJNjK릯zNgTeWs5֐ZI +-12x^& $u"<⃂"ٽULF/қQ1j+lJS:d : ?iF^M fs!H+hZVĕ0vM$x-E'0w:ՠC55 aή\=}3] NJlD' _.kiL6xMDXO*S eܒZ%@G0\ɷE'0Z2|~Gݜ7<|! @_N G~"z*Acο49{sxK5_`Aa7 C/ s>¿ ;:cܝ˧SuF p#gQ|A~Oufun<FD(~$\ߘ{Lz?~Xpj⸙;)!Q}euƟzsETŝ,J8،Ƣ?vbޏk DU}x `.x-z l&GXnD =A(W< kT2{Hӭ``$!=n)Q縂]U>΋c; M'j YGkmzIX)#^ h nЌ*+^Y :U=}H:[!JOTiE֔V:(v+Z>AM]dK|+2 5p~Ƨ`ok}2!߫n^8˟ѕ;R_?KUiQ/\-r% Դ\FfGՙTI(2*;KKF^<2/{2'Rŋho!U%K<(K&2r]\*YAW(w]}/;.pРëoo%RT\?@IдiQh} &3 f83A_WD>vUT*cZɩG{ΐcek.L7w1Rˑk.`q˻l3/ ڮDzHa~h|Cj 4l b]kZ& $KdݞS5eK0[MvU6, hZJ㒿5B tnb”^t^d#1֥U,gaj'P]񸥈 1V=9UTpZOp%d[Sң,>w:kFaV0BgdCjVc’if-vM+ :J =Cq# @^bpM+ft]$]EgnTUThf<}E X/\S1$|lxa0w(J(j麒SsG  ,^@S`؋PJ܁%u>>}>}>}~.^ + Ź c0cz%܇%,o_"&&a7~/UTW+҃ƹoSh&tXj;ͦU'-QQg;l)cNVHخ*TROe-; \'qBsZz~j,8ݙ0f؛ c&0f8U#*bIL؄E NoOLU]0jmDżm4EmbWT.5xOd/ÂOP`S)k/TZ {Jf>[bc&ǟlzx),œ*іp]ݢOy-e#4ZLɅN`Gk~fzs)!t$MyR9΂nٴ6[0ZEܴWDv/tS;DxÙA u_GnpT$,\*N|fVc]t×IQ}un[:I㍪ǀiR%=גE{V%{ṿٴXH8RO;S(TS(ګr?sf[KaGѧ{xe{x ?'2J½Rt{oeES/O Qҡ+xdh0I~ּMIk۵ ɮo{W/ȖieCX(Nק.y9bB bW{ccD Bu`v/Gz-di/>;e~uoPʣqA,%j2\볕:.3 { ]pGc|sۂ!Rb AB|QʂTO˪(l]>|`ܝHp֒2kIjJF^m6qa [q3bhhY= ȋp [l'˦:;XBA3kPiJg114Q"612&Z_bRV+Rc]lDf=;*DϦ6IMZ~ 2*z\D}#Z{vяBh%!r}/%o-v(oBշFauN3-@~д(rE|QN0[q?+"7uAGS݃};FfH^F8D|`[\\lKcom R齷.JffA7MxO`ڏoq5LYn)4[ʗxh-idf)WS*\] "o8^s3uyEFue8^`BVAkcjXm&8. LLwh+84.4FmƇ9 etXأY>g۩o G97P2y/𘫢 Vr`x2)H¯aK|S  EcqSW;X քLzQ H@/qy}N!HRtd=6=I{U<v4<Yu/Nce.˄{'mhL~AW+_RcqbޝҶTo*UWUo8<{@MR._"G Q'-x=T_S  2ebju CU) 1 q -)8(q) MF~ $'z#էve*Jrm&wgul*% @*7ZymJ<&֭썏=+Zzսї ȏؠ7 G [_a m!PfgcL~ֵ:o//e8Dicg+R_ӛͳ@g[G6 Yܬv@U;|@+T'ڵEF9 Ŧu,p]7WBxʴLpTp`QhjʍY܍W)kĐ9w4ɒg}7lgcԼ8,iB9'G^BY=J7-^ǥ)P4[xeu)^C質BUقb:'kzvdСJI?ȥiC9i^ଵ%^ipK暤u5o1ˡj'XK/25FX[̍4=US@EAe+ّ:ou*֥nɹ0]2g06͡'w7s];EcXwGrOAX!@y0~?uf]65[՞+T|7S9+?3NaJt,9Qlv^qwlW sl$:$xN' EVJ&xK/sAV*'PVȹ%w*?{felYO5 [nB*MQۤR ڤn =bX Fg5ek-(6/Kh7_J:PxbYه:< Mk Lw:K\G^)q{T]AЎ#7e\VQK'>UZTLynFtO) JY+ϷД#7Oq,gl-zY" ]؞bɥqsj4l'+Y7ؾ*E4itNQ2 fwxG|"ΝjQpr1cb'MoQck1GkuطFXſʀRyK ]ӿܚSkũ4$o0[BqӉp|W{<^ԭ/qWlOߒt?gLwNT7WOxty_=pf8cK]brMut-A͵+@n47]%%]u9u;~{`_5*cJ\|ٌZë/- -tel浃qz]=9Eo^W@up+k~ϫ/_՗͈Եo˃^y\0]iX[xr+0{&^ik,x r<^k0KiCEZh1T"툑A# ivO7Lݧأ m֬WA ǠD9)wԏuTBnXzyxH67x8sVaRU>H7Ga%71U#B1Gw!]Rw',MȆ%NȪrSa7;U>F~=\Uǩ_qa{ת471@U.<}T`ӓ$IJ++i{v`xxZ\Oz"ס%l_62n.ö%Pvqdh˻$zrlu9DUg8o|ZƧֹfu.pTHz%Yԓc2OüٖCLѪ 8n:x.h )g{z~ỷk򕹯+jM>llrYe/̒ʃ'{Noxƥ#+KH̗*Ǫ;[&9B~52i{%`[;>7S sm.B,w(q2R<2&dʵ̮d75t=>8TB_Gc;WZ3r4mE!Ji*һF'*9Y^ɺWdN,_%$i (%nͣ騚֑ Höm)$49=ea6mo<:ykiϦcZ'IY-:+ӪS6 \RBi6oTHYnf(7{;ձ[%+icu, VlKΌh rʘUd|Z\ٸI@~oJ:YV7Փ =/󊬢BoXB/Etͥ薣JC\;Tl (xZ;tvh{E.66+>RvuAb"yOeZ\7W\W @B7@vSmiqя|^0CyEͩ :b'xto_yKuA#NklJ~veߟ7{g` ]?_s3V`^`f`W\`luةnğO]>x??XGfz:@D5x{|! '*ËHP5~3j|h>h"NƲZk c<6/0f7g4Ag]'1.w%wI Y5T5x9A8َ~hJ?q1ՊdTv@Q/=x'5=.)GB>̹?‘&pwLzF/.P㺃1."P?zD/y`g0?LAl8(6( @_dz ؗKt  &FOJ>hJeΊW=bgѯ0!| ܏ڞ=Z]"L4JrŁM!_gQ&ܭ-[~|Sc`F?a_NCO+QJ~IElHWĠ H#nqoI[+W-}ҽ%8tPH󁏪:i~@jixQ$[rp8R4AǼXcUu4`< DO)oݲ1 [.4 † ϤoEEzޟ -arKdh32s; HM81+U2<rnIP/k,! I\ 1ֵ­k"-$GugT͒CS%&nN|:bf[;Ɣ W̴Ξ;kvs\>V?ΠA-RyW0*W=j%)YDZAYOOOԋKm/Uϊ~΀MKtX/9JNMtQF\Tڎݬ}")#kFcl8;[ _Ӿw6;)5>v w@tz$wv;dwOc' :IQ'5v8S/e^zum ˒LtUkTբU`7e?R5y _.AP9ay1XxM-92jkַ'eoI)V%(v}KJ 9gِTW\V["E0ٚ=Oy2Ghv"&.#w8~%M]d'bŻiPEژOKP*42:sYnRvniqEuv񒻨oJ_N1Dݞ6?M쫲n/%ʒVlq/ʂb*_<_u5u˼^J꼮Z,^կE:BVKӪem"C21Vzl+3omJzq1Ь?oªUpGuWKTKjQTqa< ME)WNsn{2jV2cI;p=ꨅwjRrg]Yt?˺nfQXOiD6o;s[Vhjq7W^~#s6 vpqEqq+!?6Y#_[ Kn폓qҖ"Tq37G|eBKO;\_,oQI^7Y"VUT+HQzIoaY®[I *G6A4Fe_A <\24j4PYh6Mn4 OV͞Mfr ~Ff;Wda }@ѿ[ќNԕ? J4zy%,?]Ij _@o΀a:a{~,`~y)01`rqr/Uոo"ayOO \gqW>, yŒtĆø~^RH36OR g(Kۯ%6sH+B?~c>eL,?HV^xh Sx?rUX7pS8H]srROs-^SvϚ6:5-$Qh=P$4G:WzQX(h;gZZVV|*Yd#YkzUU`eHxQQ f2ۃOf>ɽl&2k˓[U^+O@ɵK-%ɽj'Urܻf$ Zʾ_EdNL4k(1J;Zj2N.PH ",ǃ*YւkYF3W_|-5QJ YB $F::goJyPJ$_C,44'+qbG/W--¤Ua[v׻OxVaf!Vۺ9yVv=楘u zybӼze[v>m>m~x"y,W!I9gY Ie?k}>R*jG8̭O/!\â74*-~gsW.-,.5LK>>Y(|&nvʸX]N&_fFKذTs3g٠pfnŨ?dq1:kzǟl>^jad t%z{c,PxO%OK?Y%ş5㥦Vбn9 ?sgv3C{Vhb75 v{f|/'b C C3BkIY Bi,a! \t)! @3 ye/=U ?3 ?[ :Wi|Vt&;Oxg+=7sK=0 =ϓȻs-J5 =cϵMY%j{Q=v)- dWosKƯ0RM鞣Gt<[,V۫z DjΗa#v(Xٳ!v |gĨF ؋17\1w`hZ ?M0t9J_F+ټ<=C@'.>ڃy>vj㹴:k)1Sk&ƈm +`<I\Y&`}D;g$&Bt#$ FV`ĩ>9w'qp4bzjc8dw/nd0:-^®:i182 d3VNt㇬1x~!_J=es5-4 z =7pBϣN'-5 *-TG,\'?HJWxDe24P4'_Pf:D5t3&(k`痌W߶{}?hoڠv?'A:cOD:O{ 0~x {ɨf">=d~`sDlDTWHDAKz;?ݖ+Na@ $8q`?|V&234ajWҧl.8tH eI8e:Ĭ.Njzh&7B$"$B<'OS -ɣH x򒢮oNp1 _(gF8?=2 f26lOJ>~xHPqphfK,R 3=psӋp|4^g 07qs! 'fW4i82k?WiBKLH<)3y$8WQq L0?'ڬvĠ`%AL$+%v 􆰯+.]*ꤜy~xu.2/ExhLnpp)y>@IiMF2nR)BA9XFdv}a{=L qBl*sL.)X7"1;L{(4K'9ѓ%u3(^Iu%*2ٌ\hx=aj50‘ P_Ab0Y8?`, i rXepoHb dן-TND"?4o 4! j}byW\ FF$30&&C9/Aȁ[` OK<3O1 z aSx /&\y (hFj>l3vр(K6JFTz2P>=N|P2^:}>j#Y1qףaDcDBu A^3hvq3+@c-8ZfiDsg`y iA  v#uv{"ɘh̐nQ[(y *0QߒZ0Cr8,O8]YQ΅2Xm._4;y1Es|VCtUh6{"\2^eV1P{tMYwL<[j:X*!jaRA8J#AG=J o>}ҙ43=2wIE9`sGJ #!覚xm8"SaW [8Q"GB'"zRdԘVbUul8mBpDP?#.NGc'`?'<;(Qs.VE;(BLf_!rvDz}v }·n2"Cu2w<֮rs<2@3+2jwhh$ڀV`(M=j#,0l:p fjaRWZ,bhI7 .aKkMs FGذ:\4ސhRkob~]L*1?xaQM X#0BLnE uŎ7$L;w$Oz&5}ȁuI3 nf/<=EW++Z'f `,zN-&|E8A5e&ؿRޣil8C?&(|#fC~li\~A9BHeN$#c9eAR $,_HYB#P#Ii ', r .=D}NtG:bT\C>_VmFwiZ8m)3 _ ˋ)+ 9IoEgN=!Chي%fY="_ K H Rhp$~BL0nzRgJ.$+nz\XKT#l$pX> 8 =>8, :X*B7_c#4HKe Mw0zT cm }m ,ћn,$d;Qz^^QSft;&s -^q/ foQ (8T5=Y=oyFgQKQzJҨPDG)AP{@Ssm f-`/ 8L(+ O[Non$\Rr;짧}= ;*!FZE@x(_(1 mz,0= `9d;=tl+E~y/)[.[|b~\:˔Vnas>ф/2J6/!O>!a;L]̖m̤@"? %_AxR8~--4υDcG!`߳(f+H*LAv8Z&"SxXk)_;"0!Ŗc:U]/>EOhyۉ|jC*"J&Z-Qa!?&Iym`G9{b:0XIʩىuҗ;,.H/[SGkYIKv@u A?JdEIHnq$c$'Qy0v0S e^F)ڠQ{j:erԩ/ثTv0qV`#TAc{u y31I!yGN܋%[ WaB٭QQ+1dص6q D()݈QJDR ɐP1bJk8#V3tT.֎$` lAI*6wDyGH0Uڽd,9 x=R0lHJh<3 0zg]/x$*Og>IJ@MP#ߙ/0qrr)j}T~w[+v(׬LEpczQJTxWwRāqT#TYDLxHΘhq{<@MLV2 m4>]MX* 2?BYg(d}yzA)F$;m0@=)dV]N;wJr {aԏ{ףtJ3Õpey@oSGՏ+C00;`jGuρ,{x}7DF׊oJ<:H$NrYx둼JR?yH XϰdceA5"nPU>[Pwv@\$$iR} u"&(59G,փ2Av#cuyB6Y Qiw13-enf )[4yifQ9H(䌋X`2;x*RNR^SN±( Y۱*\RANA8Ec8Ӽ4 h ~Q:uE ++*Kލ@TKQ~AӳLjߖ1} c&AP4:=ttOIh! d~63 IG)&T1Y,J|d*YyD-w*% ^\4Z~Kn9a&ZU')6 a ^Rz4<){`/EI'*Kc=renaS;eqC35"%`0?$;}iN(o'nÓ22sE)DQgMLcH%/#)PIJIJ!8%]$U9܌ջ4ܞL)$X7Ȏ31+DZc.?;BQFp' '=L)9?K0}9TZa2LxE< Bv|@XUYh#+BQHd!)ʙjFx8B hNcL1dQc+,m`Fc`Cvf1JP&풪3d2WTU{dIpi΄l3a-$lA)_anyA;oe(@S⯠muӔ8c镀8xzLN.=q <ҹe#yg='KZ*閃5nAS (yi(Ps63uey?!tH$7f=^~f9l9] bb/ Nu Maq.I R:OZ7)esx%Tͳ`*q&xA[$Τeop/!ƅ8B\V0$3-aUiL^gy꨼IxV=fSZ0㥌U )RUc}&)+r1:2Q%!IAwR|D؆)2+{"o}}m|/mP>"g(1my/x-R>1TBV*HIz;q~G^wJ:ʇϙY8o @@9!59qtwxwH$N@ϯ%Ģ*q RK⚛:ҍCZqMFhN,[ֺYDN7ˣf7K"fKzpxBYخ4¿YcN ʑ$c#&U˜܇CߏG6l:Ѥ}T`ѧVI$i]ҲKB^E*/Ô}8w:O\`+Iim s>@b8<3|'>ȄAyCl< ʳЗZOl*NvrFXrL$^``epzOT;KsNŪu~G2^ApÒ4T*5`(*{^ɣ`|?b$/ _`ð#/B{D:^4>H+3@+̯ JRQ&$|AY';yQrY SDȎL?UPj\_Ӎ~HGAe/AvZ8SCQ*1D*r=x@*x[ 7r}?Rܮ[pW%Hf˴d6qܑF〯iZR)(3ӛ2\UL&Py8AGMP\OL|ǜ1P ()qT~hY#NZ!Pb0h%{ML YSo^H`fbuaAҚ~LuUcrLJ96z&IK5|^)؟5ip,I57JIױX6)_U3;ÄZ $QD%ιMaSޝݰXbQ[~1kFl6FCY_B(+uJS)S^΃31_hsu6D°&_"LpʎGݓrU yeAF'Af/90 9hP]9Ӝ?G  3Qdʮ`0q^M`Ӝ-F\E/+ψhǰ#Tg |3ľѕ 2[Վb'0P 7R!O(үZUiĹU?N/ d/xAU $ q WRds:C쫳18S=[IJeopMEMHu(]7W+ <+Ta^v |3WDŽH7I@QNNas * p Y*B9*KA\2mhTN5,pE<oSW4t'e,6 و?Q6k;=(yB_|МY9.|]ٸG:-Pʙ[-U:2!+d OaMl/zfv\cWE}Rjd3vJz Vkj}hk^b2ȬfEp#rcBx,&mQ[H FG ߞuc8z4G7D] Ι`gqh&#T/ڮ拾|ṽ߆(3+,5I6~9uZW 9&5\y;ɉTX#ir݁/C3EddL9b 4+ eO[7UWblJQ5MՏؠQYsvHd9${ 0#"}%bbt4jQ tZ`>Bz"ۨb`_nZJKL4Dv$3v8O%BU9|m&E=giy*wD@"J9E@=vG?Fzl2KjnO*Oq6aX&Jt?Trq^7(Ù3FMZͳI @O6T3ub$Hϖ@nƵ31-6"D#!58#Z '9_oAx7zf\ctOR-d?®M._'+G1M6@ڗ\L eGV`gE%CҼ>ڢGY (/b>x7Zs)rK$ڧ D3Oee%cȴymX 'gKkv:e/B~bn;kơiu?AP^FӦ'+n'xo}@a2Ejd'bf<Қ81蹩Us4M0 WI{6͂qS񺏄4O@"&g丬bt@ȯϓ䭫T,Q4R;,U"#ILu&I;iNMwDz5ҎSnVFJ ~ AQE4ܴ0|}`Cg{V!Dz)o$ˊtkHf]nX(_ca(7rL&dM[٢ l|L=c|e~ LE6]K cdvc؜ GM$[їk7$E-hFk;{Rk5"II!M+[zz>蜴3J7"{4G-$!Җt cArTZJ`/ k9:x@Qm?DFeq1[$sI[qn|Xi̅VcFUL9g\,;:0^R2oEN”ZDS(y彶J7_fF#ä~H^O7qzssՍ ?7Wߜ~iwW]|s/n\]pN?_~|~>;ǧqy{ޝ _7w_'gW\tn{Ӌ-9'}-L^w9_[%?70 ~z9̫~vԸs>_UFgpb'x% W} C SS@HNĿ xTr׳  u <9xqvwO0߾\o@?_/`77/ψ7ק7 BZ-Q*=\Vߑi}$7@YͲ.7DqQ0C\F-.sK^Rnru~ׇ S>>p \O~qr4И_|9ro/.83 Ƽ\q b#R`w '~Ucwd_cw:nʝ[bӻSf ~o.h㝞}M oynʫҾ9; ~<&ρ|$DĉJ[G,+ 6=~|*c7^BZ~*7Surd [Hsr&5 7n_}.@~$rp?sa̋<﷣x3RJ|̀#Zi2dLdJݓ!:)T+SL՜lrĨٽ z+uѪ\ uvhdNFySTϰ߿]DNla G28 qE9ޘLΏ1G"-+R?~M)f.b'vDjI @q.:$+pgek ѣgNSSwcrj&FBI\CjQ efbKDjקz|$2Jiz<p#=#ӑ8%$_EēyNDY"gL'suJħ:KL?| {Ѱ ? ;Ѡ_^0]Fqvgmz'&?0/X/uNR6M gfBSrۛDQE~ =#gvs@/] G@'~ ^OO@?v~!_"Wv^k@E@e  zG@F@~ Q ~o||CjcՋdƹLlI!J05S5EJd{ )偨fgePTA j.B*)L/UAi\:ŗߊ6:I'tpE2\! 40>Eg?( ۦuB߹y j#6 dU_4\}>v "Vf>ER"RƯ0e ӶxнRM+E&КA \- a{>J},_^gp2ع=/ˈɿdijz#7,pf*6]zʨ _7Ulݛ!vfODsDXl& ?g[h34oz2h%yqA ٕ KQ+ڽ;liP*/24HY/K'q} *)6|3o!%'[JOEfF =,v_BOF&~9UU) -W4azЛa C z?x p8m{agr  ~MhBIDt_:͠>."$W"J &z.x+Pw/ iq3HT`VӞ¶7ҟSG$%¾ :/ڽƀn2_\\D@LJ}H47w~ rǠ_{#BnFϋ9 s^ݾ5zzwG†8 n⪹'>D^9$ x!n p? !e~ax<,|h~8"h~٨}9FuG}x.n0¿7c #K?F-e w\9fPF-_m8z=/;j*}f4Kpt/ski|٨)4DP3xa^?#立{`?7i {6F;Ű-k{(iv-fWE PZÀgn+[b%hOHZKp4T2;!})+AX^P 0y>t_v~7?͵Mt͛sAS_Xe`LQ9 ;j}s 7x3BݚwCO~r駍n~ X*c.e8>=܅?6DJ]m%X Jnu^1cvtm|"׫0d(.[xYrx,b\{=ڢ4 ee(!5B 1{wQk.WUsd=_(Z~OzfFYCRx1}8s5klk",ZƿDY ?*ff j-87o6)o_@@KBgt֤XPE~п>G%D6\L|lMGeH)iUTbw[v"['aY6u_W['~S}J h0c~S`h^zaOp`UKsȄ*ҋ4[qo?/Va C՜Xk=Mno+[e~/^ #'(;v74;0  wSEގ-q#SMs`|0 eZ~oDd̘ H/^cLo q)TCuE6Bms=l{A%"ɽ&P[YSvj)m֤'OF&n~٣Xٷol}${]yon4 hֲ|LpDiZ%T%}2̧ `^eYpEKddz}.hBEz,8jFoC,ݾFۧg6wܽ]qecn}{"%6X|=Gޣ݆͒Y Ԅf ~['?'/#T/{%Yg*?,/S^@Bh!H4ۆZ1jr_X #_ǣv_ __tb{MG/qClAV{ 9Lm1d~6v7t0GOk<tS;S`m& ( ͼy ON{s8 ]g.szn #hw@?Ov^K@I@ig./]W.kzm!7v[@]7@v ?J5=XtGxD!Q_ package header fileXarduino.html#Verify-octave-can-see-the-addonJ6.2.4 Verify octave can see the addon2arduino.html#Using-addons 6.3 Using addonsfarduino.html#Programming-the-arduino-with-the-addonX6.3.1 Programming the arduino with the addonHarduino.html#Creating-a-addon-object:6.3.2 Creating a addon object:arduino.html#Sensors-Overview$7 Sensors OverviewLarduino.html#Matlab-Compatible-Sensors:7.1 Matlab Compatible Sensors*arduino.html#Overview7.1.1 Overview<arduino.html#Available-Sensors.7.1.2 Available SensorsParduino.html#Lightweight-Arduino-Sensors>7.2 Lightweight Arduino Sensors.arduino.html#Overview-17.2.1 Overview@arduino.html#Available-Sensors-1.7.2.2 Available Sensors*arduino.html#Examples8 Examples8arduino.html#Blinking-an-LED&8.1 Blinking an LEDharduino.html#Using-I2C-to-communicate-with-an-EEPROMV8.2 Using I2C to communicate with an EEPROM~arduino.html#Using-SPI-to-communicate-with-a-mcp3002-10-bit-ADCl8.3 Using SPI to communicate with a mcp3002 10 bit ADC>arduino.html#Function-Reference(9 Function Reference<arduino.html#General-Functions*9.1 General Functions2arduino.html#arduinosetup$9.1.1 arduinosetup,arduino.html#isarduino9.1.2 isarduinoBarduino.html#listArduinoLibraries49.1.3 listArduinoLibraries8arduino.html#scanForArduinos*9.1.4 scanForArduinos<arduino.html#Arduino-Functions*9.2 Arduino FunctionsParduino.html#g_t_0040arduino_002farduino,9.2.1 @arduino/arduino`arduino.html#g_t_0040arduino_002fcheckI2CAddress<9.2.2 @arduino/checkI2CAddressZarduino.html#g_t_0040arduino_002fconfigurePin69.2.3 @arduino/configurePinjarduino.html#g_t_0040arduino_002fconfigurePinResourceF9.2.4 @arduino/configurePinResourcenarduino.html#g_t_0040arduino_002fdecrementResourceCountJ9.2.5 @arduino/decrementResourceCountNarduino.html#g_t_0040arduino_002fdelete*9.2.6 @arduino/deleteJarduino.html#g_t_0040arduino_002fdisp&9.2.7 @arduino/dispTarduino.html#g_t_0040arduino_002fgetEndian09.2.8 @arduino/get Endian`arduino.html#g_t_0040arduino_002fgetI2CTerminals<9.2.9 @arduino/getI2CTerminalslarduino.html#g_t_0040arduino_002fgetInterruptTerminalsJ9.2.10 @arduino/getInterruptTerminals`arduino.html#g_t_0040arduino_002fgetLEDTerminals>9.2.11 @arduino/getLEDTerminalsNarduino.html#g_t_0040arduino_002fgetMCU,9.2.12 @arduino/getMCU`arduino.html#g_t_0040arduino_002fgetPWMTerminals>9.2.13 @arduino/getPWMTerminalsXarduino.html#g_t_0040arduino_002fgetPinAlias69.2.14 @arduino/getPinAliasVarduino.html#g_t_0040arduino_002fgetPinInfo49.2.15 @arduino/getPinInfojarduino.html#g_t_0040arduino_002fgetPinsFromTerminalsH9.2.16 @arduino/getPinsFromTerminalsbarduino.html#g_t_0040arduino_002fgetResourceCount@9.2.17 @arduino/getResourceCountbarduino.html#g_t_0040arduino_002fgetResourceOwner@9.2.18 @arduino/getResourceOwner`arduino.html#g_t_0040arduino_002fgetSPITerminals>9.2.19 @arduino/getSPITerminalsdarduino.html#g_t_0040arduino_002fgetServoTerminalsB9.2.20 @arduino/getServoTerminalstarduino.html#g_t_0040arduino_002fgetSharedResourcePropertyR9.2.21 @arduino/getSharedResourceProperty`arduino.html#g_t_0040arduino_002fgetTerminalMode>9.2.22 @arduino/getTerminalModejarduino.html#g_t_0040arduino_002fgetTerminalsFromPinsH9.2.23 @arduino/getTerminalsFromPinsnarduino.html#g_t_0040arduino_002fincrementResourceCountL9.2.24 @arduino/incrementResourceCountbarduino.html#g_t_0040arduino_002fisTerminalAnalog@9.2.25 @arduino/isTerminalAnalogdarduino.html#g_t_0040arduino_002fisTerminalDigitalB9.2.26 @arduino/isTerminalDigitalRarduino.html#g_t_0040arduino_002fplayTone09.2.27 @arduino/playTone\arduino.html#g_t_0040arduino_002freadAnalogPin:9.2.28 @arduino/readAnalogPin^arduino.html#g_t_0040arduino_002freadDigitalPin<9.2.29 @arduino/readDigitalPinXarduino.html#g_t_0040arduino_002freadVoltage69.2.30 @arduino/readVoltageLarduino.html#g_t_0040arduino_002freset*9.2.31 @arduino/resetXarduino.html#g_t_0040arduino_002fsendCommand69.2.32 @arduino/sendCommandtarduino.h!tml#g_t_0040arduino_002fsetSharedResourcePropertyR9.2.33 @arduino/setSharedResourcePropertyNarduino.html#g_t_0040arduino_002fuptime,9.2.34 @arduino/uptimeXarduino.html#g_t_0040arduino_002fvalidatePin69.2.35 @arduino/validatePinParduino.html#g_t_0040arduino_002fversion.9.2.36 @arduino/version`arduino.html#g_t_0040arduino_002fwriteDigitalPin>9.2.37 @arduino/writeDigitalPindarduino.html#g_t_0040arduino_002fwritePWMDutyCycleB9.2.38 @arduino/writePWMDutyCycle`arduino.html#g_t_0040arduino_002fwritePWMVoltage>9.2.39 @arduino/writePWMVoltageDarduino.html#Arduino-I2C-Functions29.3 Arduino I2C FunctionsLarduino.html#g_t_0040device_002fdelete(9.3.1 @device/deleteHarduino.html#g_t_0040device_002fdisp$9.3.2 @device/dispHarduino.html#g_t_0040device_002fread$9.3.3 @device/readXarduino.html#g_t_0040device_002freadRegister49.3.4 @device/readRegisterNarduino.html#g_t_0040device_002fsubsref*9.3.5 @device/subsrefJarduino.html#g_t_0040device_002fwrite&9.3.6 @device/writeZarduino.html#g_t_0040device_002fwriteRegister69.3.7 @device/writeRegisterLarduino.html#g_t_0040i2cdev_002fdelete(9.3.8 @i2cdev/deleteHarduino.html#g_t_0040i2cdev_002fdisp$9.3.9 @i2cdev/dispLarduino.html#g_t_0040i2cdev_002fi2cdev*9.3.10 @i2cdev/i2cdevHarduino.html#g_t_0040i2cdev_002fread&9.3.11 @i2cdev/readXarduino.html#g_t_0040i2cdev_002freadRegister69.3.12 @i2cdev/readRegisterNarduino.html#g_t_0040i2cdev_002fsubsref,9.3.13 @i2cdev/subsrefJarduino.html#g_t_0040i2cdev_002fwrite(9.3.14 @i2cdev/writeZarduino.html#g_t_0040i2cdev_002fwriteRegister89.3.15 @i2cdev/writeRegister.arduino.html#scanI2Cbus"9.3.16 scanI2CbusZarduino.html#Arduino-Rotary-Encoder-FunctionsH9.4 Arduino Rotary Encoder FunctionsZarduino.html#g_t_0040rotaryEncoder_002fdelete69.4.1 @rotaryEncoder/deleteVarduino.html#g_t_0040rotaryEncoder_002fdisp29.4.2 @rotaryEncoder/disp`arduino.html#g_t_0040rotaryEncoder_002freadCount<9.4.3 @rotaryEncoder/readCount`arduino.html#g_t_0040rotaryEncoder_002frea"dSpeed<9.4.4 @rotaryEncoder/readSpeedbarduino.html#g_t_0040rotaryEncoder_002fresetCount>9.4.5 @rotaryEncoder/resetCountharduino.html#g_t_0040rotaryEncoder_002frotaryEncoderD9.4.6 @rotaryEncoder/rotaryEncoder\arduino.html#g_t_0040rotaryEncoder_002fsubsref89.4.7 @rotaryEncoder/subsrefHarduino.html#Arduino-Servo-Functions69.5 Arduino Servo FunctionsJarduino.html#g_t_0040servo_002fdelete&9.5.1 @servo/deleteFarduino.html#g_t_0040servo_002fdisp"9.5.2 @servo/dispVarduino.html#g_t_0040servo_002freadPosition29.5.3 @servo/readPositionHarduino.html#g_t_0040servo_002fservo$9.5.4 @servo/servoLarduino.html#g_t_0040servo_002fsubsref(9.5.5 @servo/subsrefXarduino.html#g_t_0040servo_002fwritePosition49.5.6 @servo/writePositionXarduino.html#Arduino-Shiftregister-FunctionsF9.6 Arduino Shiftregister FunctionsZarduino.html#g_t_0040shiftRegister_002fdelete69.6.1 @shiftRegister/deleteVarduino.html#g_t_0040shiftRegister_002fdisp29.6.2 @shiftRegister/dispVarduino.html#g_t_0040shiftRegister_002fread29.6.3 @shiftRegister/readXarduino.html#g_t_0040shiftRegister_002freset49.6.4 @shiftRegister/resetharduino.html#g_t_0040shiftRegister_002fshiftRegisterD9.6.5 @shiftRegister/shiftRegister\arduino.html#g_t_0040shiftRegister_002fsubsref89.6.6 @shiftRegister/subsrefXarduino.html#g_t_0040shiftRegister_002fwrite49.6.7 @shiftRegister/writeDarduino.html#Arduino-SPI-Functions29.7 Arduino SPI FunctionsParduino.html#g_t_0040device_002fdelete-1(9.7.1 @device/deleteLarduino.html#g_t_0040device_002fdisp-1$9.7.2 @device/dispRarduino.html#g_t_0040device_002fsubsref-1*9.7.3 @device/subsrefRarduino.html#g_t_0040device_002fwriteRead.9.7.4 @device/writeReadLarduino.html#g_t_0040spidev_002fdelete(9.7.5 @spidev/deleteHarduino.html#g_t_0040spidev_002fdisp$9.7.6 @spidev/dispLarduino.html#g_t_0040spidev_002fspidev(9.7.7 @spidev/spidevNarduino.html#g_t_0040spidev_002fsubsref*9.7.8 @spidev/subsrefRarduino.html#g_t_0040spidev_002fwriteRead.9.7.9 @spidev/writeR#eadJarduino.html#Arduino-Serial-Functions89.8 Arduino Serial FunctionsParduino.html#g_t_0040device_002fdelete-2(9.8.1 @device/deleteLarduino.html#g_t_0040device_002fdevice(9.8.2 @device/deviceLarduino.html#g_t_0040device_002fdisp-2$9.8.3 @device/dispJarduino.html#g_t_0040device_002fflush&9.8.4 @device/flushLarduino.html#g_t_0040device_002fread-1$9.8.5 @device/readRarduino.html#g_t_0040device_002fsubsref-2*9.8.6 @device/subsrefNarduino.html#g_t_0040device_002fwrite-1&9.8.7 @device/writeJarduino.html#Arduino-Device-Functions89.9 Arduino Device FunctionsParduino.html#g_t_0040device_002fdelete-3(9.9.1 @device/deleteParduino.html#g_t_0040device_002fdevice-1(9.9.2 @device/deviceLarduino.html#g_t_0040device_002fdisp-3$9.9.3 @device/dispNarduino.html#g_t_0040device_002fflush-1&9.9.4 @device/flushLarduino.html#g_t_0040device_002fread-2$9.9.5 @device/read\arduino.html#g_t_0040device_002freadRegister-149.9.6 @device/readRegisterRarduino.html#g_t_0040device_002fsubsref-3*9.9.7 @device/subsrefNarduino.html#g_t_0040device_002fwrite-2&9.9.8 @device/writeVarduino.html#g_t_0040device_002fwriteRead-1.9.9.9 @device/writeRead^arduino.html#g_t_0040device_002fwriteRegister-189.9.10 @device/writeRegisterRarduino.html#Arduino-Ultrasonic-FunctionsB9.10 Arduino Ultrasonic FunctionsTarduino.html#g_t_0040ultrasonic_002fdelete29.10.1 @ultrasonic/deleteParduino.html#g_t_0040ultrasonic_002fdisp.9.10.2 @ultrasonic/disp`arduino.html#g_t_0040ultrasonic_002freadDistance>9.10.3 @ultrasonic/readDistance`arduino.html#g_t_0040ultrasonic_002freadEchoTime>9.10.4 @ultrasonic/readEchoTimeVarduino.html#g_t_0040ultrasonic_002fsubsref49.10.5 @ultrasonic/subsref\arduino.html#g_t_0040ultrasonic_002fultrasonic:9.10.6 @ultrasonic/ultrasonic6arduino.html#Arduino-Addons&9.11 Arduino Addons$arduino.html#addon9.11.1 addonnarduino.html#arduinoioaddons_002eEEPRomAddon_002eEEPRomR9.11.2 arduinoioaddons.EEPRomAddon.EEPRomlarduino.html#arduinoioaddons_002eExampleAddon_002eEchoP9.11.3 arduinoioaddons.ExampleAddon.Echofarduino.html#arduinoioaddons_002eExampleLCD_002eLCDJ9.11.4 arduinoioaddons.ExampleLCD.LCDharduino.html#arduinoioaddons_002eRTCAddon_002eDS1307L9.11.5 arduinoioaddons.RTCAddon.DS1307arduino.html#arduinoioaddons_002eSimpleStepper_002eSimpleStepperd9.11.6 arduinoioaddons.SimpleStepper.SimpleSteppernarduino.html#arduinoioaddons_002eadafruit_002edcmotorv2R9.11.7 arduinoioaddons.adafruit.dcmotorv2varduino.html#arduinoioaddons_002eadafruit_002emotorshieldv2Z9.11.8 arduinoioaddons.adafruit.motorshieldv2jarduino.html#arduinoioaddons_002eadafruit_002estepperN9.11.9 arduinoioaddons.adafruit.stepper8arduino.html#Arduino-Sensors(9.12 Arduino SensorsJarduino.html#arduinosensor_002eDS130769.12.1 arduinosensor.DS1307Parduino.html#arduinosensor_002eGUVAS12SD<9.12.2 arduinosensor.GUVAS12SDLarduino.html#arduinosensor_002eMPC300289.12.3 arduinosensor.MPC3002Jarduino.html#arduinosensor_002eSI702169.12.4 arduinosensor.SI7021Harduino.html#Arduino-I_002fO-package09.13 Arduino I/O packageHarduino.html#arduinoio_002eAddonBase49.13.1 arduinoio.AddonBaseFarduino.html#arduinoio_002eFilePath29.13.2 arduinoio.FilePathFarduino.html#arduinoio_002eLibFiles29.13.3 arduinoio.LibFilesLarduino.html#arduinoio_002eLibraryBase89.13.4 arduinoio.LibraryBaseRarduino.html#arduinoio_002egetBoardConfig>9.13.5 arduinoio.getBoardConfigRarduino.html#Matlab-Compatibility-ClassesB9.14 Matlab Compatibility Classesfarduino.html#matlabshared_002eaddon_002eLibraryBaseJ9.14.1 matlabshared.addon.LibraryBase(arduino.html#Sensors9.15 Sensors&arduino.html#bme2809.15.1 bme280&arduino.html#bno0559.15.2 bno055&arduino.html#lis3dh9.15.3 lis3dh(arduino.html#lps22hb9.15.4 lps22hb(arduino.html#lsm6dso9.15.5 lsm6dso(arduino.html#mpu60509.15.6 mpu6050&arduino.html#si70219.15.7 si70216arduino.html#Test-Functions&9.16 Test FunctionsDarduino.html#arduino_005fbistsetup09.16.1 arduino_bistsetup BT ~d8 ~ V ! N `  R Fs*=Z#b1h+h#[(\+1B+ A@i2cdev/subsrefg_t_0040i2cdev_002fsubsref;A5 K@i2cdev/readRegisterg_t_0040i2cdev_002freadRegister+@% ;@i2cdev/readg_t_0040i2cdev_002fread/?) ?@i2cdev/i2cdevg_t_0040i2cdev_002fi2cdev+>% ;@i2cdev/dispg_t_0040i2cdev_002fdisp/=) ?@i2cdev/deleteg_t_0040i2cdev_002fdelete=<7 M@device/writeRegisterg_t_0040device_002fwriteRegister-;' =@device/writeg_t_0040device_002fwrite1:+ A@device/subsrefg_t_0040device_002fsubsref;95 K@device/readRegisterg_t_0040device_002freadRegister+8% ;@device/readg_t_0040device_002fread+7% ;@device/dispg_t_0040device_002fdisp/6) ?@device/deleteg_t_0040device_002fdeleteC5= S@arduino/writePWMVoltageg_t_0040arduino_002fwritePWMVoltageG4A W@arduino/writePWMDutyCycleg_t_0040arduino_002fwritePWMDutyCycleC3= S@arduino/writeDigitalPing_t_0040arduino_002fwriteDigitalPin32- C@arduino/versiong_t_0040arduino_002fversion;15 K@arduino/validatePing_t_0040arduino_002fvalidatePin10+ A@arduino/uptimeg_t_0040arduino_002fuptimeW/Q g@arduino/setSharedResourcePropertyg_t_0040arduino_002fsetSharedResourceProperty;.5 K@arduino/sendCommandg_t_0040arduino_002fsendCommand/-) ?@arduino/resetg_t_0040arduino_002freset;,5 K@arduino/readVoltageg_t_0040arduino_002freadVoltageA+; Q@arduino/readDigitalPing_t_0040arduino_002freadDigitalPin?*9 O@arduino/readAnalogPing_t_0040arduino_002freadAnalogPin5)/ E@arduino/playToneg_t_0040arduino_002fplayToneG(A W@arduino/isTerminalDigitalg_t_0040arduino_002fisTerminalDigitalE'? U@arduino/isTerminalAnalogg_t_0040arduino_002fisTerminalAnalogQ&K a@arduino/incrementResourceCountg_t_0040arduino_002fincrementResourceCountM%G ]@arduino/getTerminalsFromPinsg_t_0040arduino_002fgetTerminalsFromPinsC$= S@arduino/getTerminalModeg_t_0040arduino_002fgetTerminalModeW#Q g@arduino/getSharedResourcePropertyg_t_0040arduino_002fgetSharedResourcePropertyG"A W@arduino/getServoTerminalsg_t_0040arduino_002fgetServoTerminalsC!= S@arduino/getSPITerminalsg_t_0040arduino_002fgetSPITerminalsE ? U@arduino/getResourceOwnerg_t_0040arduino_002fgetResourceOwnerE? U@arduino/getResourceCountg_t_0040arduino_002fgetResourceCountMG ]@arduino/getPinsFromTerminalsg_t_0040arduino_002fgetPinsFromTerminals93 I@arduino/getPinInfog_t_0040arduino_002fgetPinInfo;5 K@arduino/getPinAliasg_t_0040arduino_002fgetPinAliasC= S@arduino/getPWMTerminalsg_t_0040arduino_002fgetPWMTerminals1+ A@arduino/getMCUg_t_0040arduino_002fgetMCUC= S@arduino/getLEDTerminalsg_t_0040arduino_002fgetLEDTerminalsOI _@arduino/getInterruptTerminalsg_t_0040arduino_002fgetInterruptTerminalsC= S@arduino/getI2CTerminalsg_t_0040arduino_002fgetI2CTerminals71 G@arduino/getEndiang_t_0040arduino_002fgetEndian-' =@arduino/dispg_t_0040arduino_002fdisp1+ A@arduino/deleteg_t_0040arduino_002fdeleteQK a@arduino/decrementResourceCountg_t_0040arduino_002fdecrementResourceCountMG ]@arduino/configurePinResourceg_t_0040arduino_002fconfigurePinResource=7 M@arduino/configurePing_t_0040arduino_002fconfigurePinC= S@arduino/checkI2CAddressg_t_0040arduino_002fcheckI2CAddress3- C@arduino/arduinog_t_0040arduino_002farduino&+ +scanForArduinosscanForArduinos0 5 5listArduinoLibrarieslistArduinoLibraries  isarduinoisarduino % %arduinosetuparduinosetup, / 3Available SensorsAvailable-Sensors-1  !OverviewOverview-1*/ /Available SensorsAvailable-Sensors OverviewOverview6; ;Creating a addon objectCreating-a-addon-objectTY YProgramming the arduino with the addonProgramming-the-arduino-with-the-addonFK KVerify octave can see the addonVerify-octave-can-see-the-addon:? ?Addon package header fileAddon-package-header-file67 ?Addon package .m fileAddon-package-_002em-file6; ;Addon package directoryAddon-package-directory Ct5p) l A  k , y , { L  Q T%]*\'|CIJD;67 ?arduinosensor.MPC3002arduinosensor_002eMPC3002:; Carduinosensor.GUVAS12SDarduinosensor_002eGUVAS12SD45 =arduinosensor.DS1307arduinosensor_002eDS1307PM ]arduinoioaddons.adafruit.stepperarduinoioaddons_002eadafruit_002estepper\Y iarduinoioaddons.adafruit.motorshieldv2arduinoioaddons_002eadafruit_002emotorshieldv2TQ aarduinoioaddons.adafruit.dcmotorv2arduinoioaddons_002eadafruit_002edcmotorv2fc sarduinoioaddons.SimpleStepper.SimpleStepperarduinoioaddons_002eSimpleStepper_002eSimpleStepperN~K [arduinoioaddons.RTCAddon.DS1307arduinoioaddons_002eRTCAddon_002eDS1307L}I Yarduinoioaddons.ExampleLCD.LCDarduinoioaddons_002eExampleLCD_002eLCDR|O _arduinoioaddons.ExampleAddon.Echoarduinoioaddons_002eExampleAddon_002eEchoT{Q aarduinoioaddons.EEPRomAddon.EEPRomarduinoioaddons_002eEEPRomAddon_002eEEPRomz addonaddon?y9 O@ultrasonic/ultrasonicg_t_0040ultrasonic_002fultrasonic9x3 I@ultrasonic/subsrefg_t_0040ultrasonic_002fsubsrefCw= S@ultrasonic/readEchoTimeg_t_0040ultrasonic_002freadEchoTimeCv= S@ultrasonic/readDistanceg_t_0040ultrasonic_002freadDistance3u- C@ultrasonic/dispg_t_0040ultrasonic_002fdisp7t1 G@ultrasonic/deleteg_t_0040ultrasonic_002fdelete?s7 Q@device/writeRegisterg_t_0040device_002fwriteRegister-17r/ I@device/writeReadg_t_0040device_002fwriteRead-1/q' A@device/writeg_t_0040device_002fwrite-23p+ E@device/subsrefg_t_0040device_002fsubsref-3=o5 O@device/readRegisterg_t_0040device_002freadRegister-1-n% ?@device/readg_t_0040device_002fread-2/m' A@device/flushg_t_0040device_002fflush-1-l% ?@device/dispg_t_0040device_002fdisp-31k) C@device/deviceg_t_0040device_002fdevice-11j) C@device/deleteg_t_0040device_002fdelete-3/i' A@device/writeg_t_0040device_002fwrite-13h+ E@device/subsrefg_t_0040device_002fsubsref-2-g% ?@device/readg_t_0040device_002fread-1-f' =@device/flushg_t_0040device_002fflush-e% ?@device/dispg_t_0040device_002fdisp-2/d) ?@device/deviceg_t_0040device_002fdevice1c) C@device/deleteg_t_0040device_002fdelete-25b/ E@spidev/writeReadg_t_0040spidev_002fwriteRead1a+ A@spidev/subsrefg_t_0040spidev_002fsubsref/`) ?@spidev/spidevg_t_0040spidev_002fspidev+_% ;@spidev/dispg_t_0040spidev_002fdisp/^) ?@spidev/deleteg_t_0040spidev_002fdelete5]/ E@device/writeReadg_t_0040device_002fwriteRead3\+ E@device/subsrefg_t_0040device_002fsubsref-1-[% ?@device/dispg_t_0040device_002fdisp-11Z) C@device/deleteg_t_0040device_002fdelete-1;Y5 K@shiftRegister/writeg_t_0040shiftRegister_002fwrite?X9 O@shiftRegister/subsrefg_t_0040shiftRegister_002fsubsrefKWE [@shiftRegister/shiftRegisterg_t_0040shiftRegister_002fshiftRegister;V5 K@shiftRegister/resetg_t_0040shiftRegister_002freset9U3 I@shiftRegister/readg_t_0040shiftRegister_002fread9T3 I@shiftRegister/dispg_t_0040shiftRegister_002fdisp=S7 M@shiftRegister/deleteg_t_0040shiftRegister_002fdelete;R5 K@servo/writePositiong_t_0040servo_002fwritePosition/Q) ?@servo/subsrefg_t_0040servo_002fsubsref+P% ;@servo/servog_t_0040servo_002fservo9O3 I@servo/readPositiong_t_0040servo_002freadPosition)N# 9@servo/dispg_t_0040servo_002fdisp-M' =@servo/deleteg_t_0040servo_002fdelete?L9 O@rotaryEncoder/subsrefg_t_0040rotaryEncoder_002fsubsrefKKE [@rotaryEncoder/rotaryEncoderg_t_0040rotaryEncoder_002frotaryEncoderEJ? U@rotaryEncoder/resetCountg_t_0040rotaryEncoder_002fresetCountCI= S@rotaryEncoder/readSpeedg_t_0040rotaryEncoder_002freadSpeedCH= S@rotaryEncoder/readCountg_t_0040rotaryEncoder_002freadCount9G3 I@rotaryEncoder/dispg_t_0040rotaryEncoder_002fdisp=F7 M@rotaryEncoder/deleteg_t_0040rotaryEncoder_002fdeleteE! !scanI2CbusscanI2Cbus=D7 M@i2cdev/writeRegisterg_t_0040i2cdev_002fwriteRegister-C' =@i2cdev/writeg_t_0040i2cdev_002fwrite  a.gP9" ./ 7arduino_bistsetuparduino_005fbistsetup si7021si7021 mpu6050mpu6050 lsm6dsolsm6dso lps22hblps22hb lis3dhlis3dh bno055bno055  bme280bme280L I Ymatlabshared.addon.LibraryBasematlabshared_002eaddon_002eLibraryBase< = Earduinoio.getBoardConfigarduinoio_002egetBoardConfig6 7 ?arduinoio.LibraryBasearduinoio_002eLibraryBase0 1 9arduinoio.LibFilesarduinoio_002eLibFiles01 9arduinoio.FilePatharduinoio_002eFilePath23 ;arduinoio.AddonBasearduinoio_002eAddonBase45 =arduinosensor.SI7021arduinosensor_002eSI7021arduino-0.12.1/doc/arduino.qhc0000644000000000000000000040000014545566645013103 0ustar00SQLite format 3@ # #.j $  w h z H"f| b''tableVersionFilterVersionFilterCREATE TABLE VersionFilter (Version TEXT, FilterId INTEGER)n++tableComponentFilterComponentFilterCREATE TABLE ComponentFilter (ComponentName TEXT, FilterId INTEGER)u--tableComponentMappingComponentMappingCREATE TABLE ComponentMapping (ComponentId INTEGER, NamespaceId INTEGER)q))tableComponentTableComponentTableCREATE TABLE ComponentTable (ComponentId INTEGER PRIMARY KEY, Name TEXT)VtableFilterFilterCREATE TABLE Filter (FilterId INTEGER PRIMARY KEY, Name TEXT)b%%tableVersionTableVersionTableCREATE TABLE VersionTable (NamespaceId INTEGER, Version TEXT)))mtableTimeStampTableTimeStampTableCREATE TABLE TimeStampTable (NamespaceId INTEGER, FolderId INTEGER, FilePath TEXT, Size INTEGER, TimeStamp TEXT)551tableOptimizedFilterTableOptimizedFilterTableCREATE TABLE OptimizedFilterTable (NamespaceId INTEGER, FilterAttributeId INTEGER)(77otableFileAttributeSetTableFileAttributeSetTableCREATE TABLE FileAttributeSetTable (NamespaceId INTEGER, FilterAttributeSetId INTEGER, FilterAttributeId INTEGER) 33/tableContentsFilterTableContentsFilterTableCREATE TABLE ContentsFilterTable (FilterAttributeId INTEGER, ContentsId INTEGER )w --!tableIndexFilterTableIndexFilterTable CREATE TABLE IndexFilterTable (FilterAttributeId INTEGER, IndexId INTEGER)s ++tableFileFilterTableFileFilterTable CREATE TABLE FileFilterTable (FilterAttributeId INTEGER, FileId INTEGER)z ''3tableContentsTableContentsTable CREATE TABLE ContentsTable (Id INTEGER PRIMARY KEY, NamespaceId INTEGER, Data BLOB) !! tableIndexTableIndexTable CREATE TABLE IndexTable (Id INTEGER PRIMARY KEY, Name TEXT, Identifier TEXT, NamespaceId INTEGER, FileId INTEGER, Anchor TEXT)''MtableFileNameTableFileNameTable CREATE TABLE FileNameTable (FolderId INTEGER, Name TEXT, FileId INTEGER PRIMARY KEY, Title TEXT)e'' tableSettingsTableSettingsTableCREATE TABLE SettingsTable (Key TEXT PRIMARY KEY, Value BLOB )9M'indexsqlite_autoindex_SettingsTable_1SettingsTableh##tableFilterTableFilterTableCREATE TABLE FilterTable (NameId INTEGER, FilterAttributeId INTEGER )l++tableFilterNameTableFilterNameTableCREATE TABLE FilterNameTable (Id INTEGER PRIMARY KEY, Name TEXT ){55tableFilterAttributeTableFilterAttributeTableCREATE TABLE FilterAttributeTable (Id INTEGER PRIMARY KEY, Name TEXT )u##1tableFolderTableFolderTableCREATE TABLE FolderTable (Id INTEGER PRIMARY KEY, NamespaceId INTEGER, Name TEXT )x))+tableNamespaceTableNamespaceTableCREATE TABLE NamespaceTable (Id INTEGER PRIMARY KEY, Name TEXT, FilePath TEXT ) '=#octave.community.arduinoarduino.qch  doc    #{fS>#9FullTextSearchFallback%CreationTimee+) HideAddressBar- EnableAddressBarA EnableDocumentationManager; HideFilterFunctionality? EnableFilterFunctionality*-;LastRegisterTime2024-01-04T12:43:07.889 ?Z~?k9FullTextSearchFallback%CreationTime)HideAddressBar-EnableAddressBarAEnableDocumentationManager;HideFilterFunctionality?EnableFilterFunctionality- LastRegisterTime  ##arduino.cssarduino.css` %)arduino.htmlArduino Toolkit - a somewhat Matlab compatible arduino toolkit for GNU octave.C P arduino.htmlArduino Toolkit - a somewhat Matlab compatible arduino toolkit for GNU octave. ManualFarduino.html#Installing-and-loading01 Installing and loadingDarduino.html#Online-Direct-install21.1 Online Direct installBarduino.html#Off_002dline-install(1.2 Off-line install(arduino.html#Loading1.3 Loading6arduino.html#Hardware-setup 2 Hardware setupHarduino.html#Programming-the-Arduino62.1 Programming the ArduinoLarduino.html#Known-Arduino-Board-Types:2.2 Known Arduino Board TypesJarduino.html#Connecting-to-an-arduino43 Connecting to an arduinoVarduino.html#Connecting-to-a-single-arduinoD3.1 Connecting to a single arduinoZarduino.html#Connecting-to-a-specific-arduinoH3.2 Connecting to a specific arduinoParduino.html#Querying-available-arduinos>3.3 Querying available arduinosXarduino.html#Basic-Input-and-Output-OverviewB4 Basic Input and Output OverviewNarduino.html#Performing-Digital-I_002fO44.1 Performing Digital I/OHarduino.html#Performing-Analog-Input64.2 Performing Analog InputXarduino.html#Protocol-based-I_002fO-Overview:5 Protocol based I/O Overview<arduino.html#SPI-communication*5.1 SPI communication<arduino.html#I2C-communication*5.2 I2C communication@arduino.html#Servo-communication.5.3 Servo communication8arduino.html#Shift-Registers&5.4 Shift Registers8arduino.html#Rotary-Encoders&5.5 Rotary Encoders>arduino.html#Ultrasonic-Sensors,5.6 Ultrasonic SensorsBarduino.html#Serial-communication05.7 Serial communication8arduino.html#Addons-Overview"6 Addons Overview>arduino.html#Addon-Introduction,6.1 Addon Introduction<arduino.html#Creating-an-addon*6.2 Creating an addonHarduino.html#Addon-package-directory:6.2.1 Addon package directoryLarduino.html#Addon-package-_002em-file66.2.2 Addon package .m fileLarduino.html#Addon-package-header-file>6.2.3 Addon      ' #3arduino.qch`2024-01-04T12:43:07   doc    CWk@% d 0 `  v 2 l ( d LbL ^"\(X(b4j>,C' =@i2cdev/writeg_t_0040i2cdev_002fwrite0B+ A@i2cdev/subsrefg_t_0040i2cdev_002fsubsref:A5 K@i2cdev/readRegisterg_t_0040i2cdev_002freadRegister*@% ;@i2cdev/readg_t_0040i2cdev_002fread.?) ?@i2cdev/i2cdevg_t_0040i2cdev_002fi2cdev*>% ;@i2cdev/dispg_t_0040i2cdev_002fdisp.=) ?@i2cdev/deleteg_t_0040i2cdev_002fdelete<<7 M@device/writeRegisterg_t_0040device_002fwriteRegister,;' =@device/writeg_t_0040device_002fwrite0:+ A@device/subsrefg_t_0040device_002fsubsref:95 K@device/readRegisterg_t_0040device_002freadRegister*8% ;@device/readg_t_0040device_002fread*7% ;@device/dispg_t_0040device_002fdisp.6) ?@device/deleteg_t_0040device_002fdeleteB5= S@arduino/writePWMVoltageg_t_0040arduino_002fwritePWMVoltageF4A W@arduino/writePWMDutyCycleg_t_0040arduino_002fwritePWMDutyCycleB3= S@arduino/writeDigitalPing_t_0040arduino_002fwriteDigitalPin22- C@arduino/versiong_t_0040arduino_002fversion:15 K@arduino/validatePing_t_0040arduino_002fvalidatePin00+ A@arduino/uptimeg_t_0040arduino_002fuptimeV/Q g@arduino/setSharedResourcePropertyg_t_0040arduino_002fsetSharedResourceProperty:.5 K@arduino/sendCommandg_t_0040arduino_002fsendCommand.-) ?@arduino/resetg_t_0040arduino_002freset:,5 K@arduino/readVoltageg_t_0040arduino_002freadVoltage@+; Q@arduino/readDigitalPing_t_0040arduino_002freadDigitalPin>*9 O@arduino/readAnalogPing_t_0040arduino_002freadAnalogPin4)/ E@arduino/playToneg_t_0040arduino_002fplayToneF(A W@arduino/isTerminalDigitalg_t_0040arduino_002fisTerminalDigitalD'? U@arduino/isTerminalAnalogg_t_0040arduino_002fisTerminalAnalogP&K a@arduino/incrementResourceCountg_t_0040arduino_002fincrementResourceCountL%G ]@arduino/getTerminalsFromPinsg_t_0040arduino_002fgetTerminalsFromPinsB$= S@arduino/getTerminalModeg_t_0040arduino_002fgetTerminalModeV#Q g@arduino/getSharedResourcePropertyg_t_0040arduino_002fgetSharedResourcePropertyF"A W@arduino/getServoTerminalsg_t_0040arduino_002fgetServoTerminalsB!= S@arduino/getSPITerminalsg_t_0040arduino_002fgetSPITerminalsD ? U@arduino/getResourceOwnerg_t_0040arduino_002fgetResourceOwnerD? U@arduino/getResourceCountg_t_0040arduino_002fgetResourceCountLG ]@arduino/getPinsFromTerminalsg_t_0040arduino_002fgetPinsFromTerminals83 I@arduino/getPinInfog_t_0040arduino_002fgetPinInfo:5 K@arduino/getPinAliasg_t_0040arduino_002fgetPinAliasB= S@arduino/getPWMTerminalsg_t_0040arduino_002fgetPWMTerminals0+ A@arduino/getMCUg_t_0040arduino_002fgetMCUB= S@arduino/getLEDTerminalsg_t_0040arduino_002fgetLEDTerminalsNI _@arduino/getInterruptTerminalsg_t_0040arduino_002fgetInterruptTerminalsB= S@arduino/getI2CTerminalsg_t_0040arduino_002fgetI2CTerminals61 G@arduino/getEndiang_t_0040arduino_002fgetEndian,' =@arduino/dispg_t_0040arduino_002fdisp0+ A@arduino/deleteg_t_0040arduino_002fdeletePK a@arduino/decrementResourceCountg_t_0040arduino_002fdecrementResourceCountLG ]@arduino/configurePinResourceg_t_0040arduino_002fconfigurePinResource<7 M@arduino/configurePing_t_0040arduino_002fconfigurePinB= S@arduino/checkI2CAddressg_t_0040arduino_002fcheckI2CAddress2- C@arduino/arduinog_t_0040arduino_002farduino%+ +scanForArduinosscanForArduinos/ 5 5listArduinoLibrarieslistArduinoLibraries  isarduinoisarduino % %arduinosetuparduinosetup+ / 3Available SensorsAvailable-Sensors-1  !OverviewOverview-1)/ /Available SensorsAvailable-Sensors OverviewOverview5; ;Creating a addon objectCreating-a-addon-objectSY YProgramming the arduino with the addonProgramming-the-arduino-with-the-addonEK KVerify octave can see the addonVerify-octave-can-see-the-addon9? ?Addon package header fileAddon-package-header-file57 ?Addon package .m fileAddon-package-_002em-file5; ;Addon package directoryAddon-package-directory Dg-_ { A  k 1 o / _ ) k 5 wIS#So+mZeYs713 ;arduinoio.AddonBasearduinoio_002eAddonBase35 =arduinosensor.SI7021arduinosensor_002eSI702157 ?arduinosensor.MPC3002arduinosensor_002eMPC30029; Carduinosensor.GUVAS12SDarduinosensor_002eGUVAS12SD35 =arduinosensor.DS1307arduinosensor_002eDS1307OM ]arduinoioaddons.adafruit.stepperarduinoioaddons_002eadafruit_002estepper[Y iarduinoioaddons.adafruit.motorshieldv2arduinoioaddons_002eadafruit_002emotorshieldv2SQ aarduinoioaddons.adafruit.dcmotorv2arduinoioaddons_002eadafruit_002edcmotorv2ec sarduinoioaddons.SimpleStepper.SimpleStepperarduinoioaddons_002eSimpleStepper_002eSimpleStepperM~K [arduinoioaddons.RTCAddon.DS1307arduinoioaddons_002eRTCAddon_002eDS1307K}I Yarduinoioaddons.ExampleLCD.LCDarduinoioaddons_002eExampleLCD_002eLCDQ|O _arduinoioaddons.ExampleAddon.Echoarduinoioaddons_002eExampleAddon_002eEchoS{Q aarduinoioaddons.EEPRomAddon.EEPRomarduinoioaddons_002eEEPRomAddon_002eEEPRomz addonaddon>y9 O@ultrasonic/ultrasonicg_t_0040ultrasonic_002fultrasonic8x3 I@ultrasonic/subsrefg_t_0040ultrasonic_002fsubsrefBw= S@ultrasonic/readEchoTimeg_t_0040ultrasonic_002freadEchoTimeBv= S@ultrasonic/readDistanceg_t_0040ultrasonic_002freadDistance2u- C@ultrasonic/dispg_t_0040ultrasonic_002fdisp6t1 G@ultrasonic/deleteg_t_0040ultrasonic_002fdelete>s7 Q@device/writeRegisterg_t_0040device_002fwriteRegister-16r/ I@device/writeReadg_t_0040device_002fwriteRead-1.q' A@device/writeg_t_0040device_002fwrite-22p+ E@device/subsrefg_t_0040device_002fsubsref-3X9 O@shiftRegister/subsrefg_t_0040shiftRegister_002fsubsrefJWE [@shiftRegister/shiftRegisterg_t_0040shiftRegister_002fshiftRegister:V5 K@shiftRegister/resetg_t_0040shiftRegister_002freset8U3 I@shiftRegister/readg_t_0040shiftRegister_002fread8T3 I@shiftRegister/dispg_t_0040shiftRegister_002fdispL9 O@rotaryEncoder/subsrefg_t_0040rotaryEncoder_002fsubsrefJKE [@rotaryEncoder/rotaryEncoderg_t_0040rotaryEncoder_002frotaryEncoderDJ? U@rotaryEncoder/resetCountg_t_0040rotaryEncoder_002fresetCountBI= S@rotaryEncoder/readSpeedg_t_0040rotaryEncoder_002freadSpeedBH= S@rotaryEncoder/readCountg_t_0040rotaryEncoder_002freadCount8G3 I@rotaryEncoder/dispg_t_0040rotaryEncoder_002fdisp7.2 Lightweight Arduino Sensors.arduino.html#Overview-17.2.1 Overview@arduino.html#Available-Sensors-1.7.2.2 Available Sensors*arduino.html#Examples8 Examples8arduino.html#Blinking-an-LED&8.1 Blinking an LEDharduino.html#Using-I2C-to-communicate-with-an-EEPROMV8.2 Using I2C to communicate with an EEPROM~arduino.html#Using-SPI-to-communicate-with-a-mcp3002-10-bit-ADCl8.3 Using SPI to communicate with a mcp3002 10 bit ADC>arduino.html#Function-Reference(9 Function Reference<arduino.html#General-Functions*9.1 General Functions2arduino.html#arduinosetup$9.1.1 arduinosetup,arduino.html#isarduino9.1.2 isarduinoBarduino.html#listArduinoLibraries49.1.3 listArduinoLibraries8arduino.html#scanForArduinos*9.1.4 scanForArduinos<arduino.html#Arduino-Functions*9.2 Arduino FunctionsParduino.html#g_t_0040arduino_002farduino,9.2.1 @arduino/arduino`arduino.html#g_t_0040arduino_002fcheckI2CAddress<9.2.2 @arduino/checkI2CAddressZarduino.html#g_t_0040arduino_002fconfigurePin69.2.3 @arduino/configurePinjarduino.html#g_t_0040arduino_002fconfigurePinResourceF9.2.4 @arduino/configurePinResourcenarduino.html#g_t_0040arduino_002fdecrementResourceCountJ9.2.5 @arduino/decrementResourceCountNarduino.html#g_t_0040arduino_002fdelete*9.2.6 @arduino/deleteJarduino.html#g_t_0040arduino_002fdisp&9.2.7 @arduino/dispTarduino.html#g_t_0040arduino_002fgetEndian09.2.8 @arduino/getEndian`arduino.html#g_t_0040arduino_002fgetI2CTerminals<9.2.9 @arduino/getI2CTerminalslarduino.html#g_t_0040arduino_002fgetInterruptTerminalsJ9.2.10 @arduino/getInterruptTerminals`arduino.html#g_t_0040arduino_002fgetLEDTerminals>9.2.11 @arduino/getLEDTerminalsNarduino.html#g_t_0040arduino_002fgetMCU,9.2.12 @arduino/getMCU`arduino.html#g_t_0040arduino_002fgetPWMTerminals>9.2.13 @arduino/getPWMTerminalsXarduino.html#g_t_0040arduino_002fgetPinAlias69.2.14 @arduino/getPinAliasVarduino.html#g_t_0040arduino_002fgetPinInfo49.2.15 @arduino/getPinInfojarduino.html#g_t_0040arduino_002fgetPinsFromTerminalsH9.2.16 @arduino/getPinsFromTerminalsbarduino.html#g_t_0040arduino_002fgetResourceCount@9.2.17 @arduino/getResourceCountbarduino.html#g_t_0040arduino_002fgetResourceOwner@9.2.18 @arduino/getResourceOwner`arduino.html#g_t_0040arduino_002fgetSPITerminals>9.2.19 @arduino/getSPITerminalsdarduino.html#g_t_0040arduino_002fgetServoTerminalsB9.2.20 @arduino/getServoTerminalstarduino.html#g_t_0040arduino_002fgetSharedResourcePropertyR9.2.21 @arduino/getSharedResourceProperty`arduino.html#g_t_0040arduino_002fgetTerminalMode>9.2.22 @arduino/getTerminalModejarduino.html#g_t_0040arduino_002fgetTerminalsFromPinsH9.2.23 @arduino/getTerminalsFromPinsnarduino.html#g_t_0040arduino_002fincrementResourceCountL9.2.24 @arduino/incrementResourceCountbarduino.html#g_t_0040arduino_002fisTerminalAnalog@9.2.25 @arduino/isTerminalAnalogdarduino.html#g_t_0040arduino_002fisTerminalDigitalB9.2.26 @arduino/isTerminalDigitalRarduino.html#g_t_0040arduino_002fplayTone09.2.27 @arduino/playTone\arduino.html#g_t_0040arduino_002freadAnalogPin:9.2.28 @arduino/readAnalogPin^arduino.html#g_t_0040arduino_002freadDigitalPin<9.2.29 @arduino/readDigitalPinXarduino.html#g_t_0040arduino_002freadVoltage69.2.30 @arduino/readVoltageLarduino.html#g_t_0040arduino_002freset*9.2.31 @arduino/resetXarduino.html#g_t_0040arduino_002fsendCommand69.2.32 @arduino/sendCommandtarduino.html#g_t_0040arduino_002fsetSharedResourcePropertyR9.2.33 @arduino/setSharedResourcePropertyNarduino.html#g_t_0040arduino_002fuptime,9.2.34 @arduino/uptimeXarduino.html#g_t_0040arduino_002fvalidatePin69.2.35 @arduino/validatePinParduino.html#g_t_0040arduino_002fversion.9.2.36 @arduino/version`arduino.html#g_t_0040arduino_002fwriteDigitalPin>9.2.37 @arduino/writeDigitalPindarduino.html#g_t_0040arduino_002fwritePWMDutyCycleB9.2.38 @arduino/writePWMDutyCycle`arduino.html#g_t_0040arduino_002fwritePWMVoltage>9.2.39 @arduino/writePWMVoltageDarduino.html#Arduino-I2C-Functions29.3 Arduino I2C FunctionsLarduino.html#g_t_0040device_002fdelete(9.3.1 @device/deleteHarduino.html#g_t_0040device_002fdisp$9.3.2 @device/dispHarduino.html#g_t_0040device_002fread$9.3.3 @device/readXarduino.html#g_t_0040device_002freadRegister49.3.4 @device/readRegisterNarduino.html#g_t_0040device_002fsubsref*9.3.5 @device/subsrefJarduino.html#g_t_0040device_002fwrite&9.3.6 @device/writeZarduino.html#g_t_0040device_002fwriteRegister69.3.7 @device/writeRegisterLarduino.html#g_t_0040i2cdev_002fdelete(9.3.8 @i2cdev/deleteHarduino.html#g_t_0040i2cdev_002fdisp$9.3.9 @i2cdev/dispLarduino.html#g_t_0040i2cdev_002fi2cdev*9.3.10 @i2cdev/i2cdevHarduino.html#g_t_0040i2cdev_002fread&9.3.11 @i2cdev/readXarduino.html#g_t_0040i2cdev_002freadRegister69.3.12 @i2cdev/readRegisterNarduino.html#g_t_0040i2cdev_002fsubsref,9.3.13 @i2cdev/subsrefJarduino.html#g_t_0040i2cdev_002fwrite(9.3.14 @i2cdev/writeZarduino.html#g_t_0040i2cdev_002fwriteRegister89.3.15 @i2cdev/writeRegister.arduino.html#scanI2Cbus"9.3.16 scanI2CbusZarduino.html#Arduino-Rotary-Encoder-FunctionsH9.4 Arduino Rotary Encoder FunctionsZarduino.html#g_t_0040rotaryEncoder_002fdelete69.4.1 @rotaryEncoder/deleteVarduino.html#g_t_0040rotaryEncoder_002fdisp29.4.2 @rotaryEncoder/disp`arduino.html#g_t_0040rotaryEncoder_002freadCount<9.4.3 @rotaryEncoder/readCount`arduino.html#g_t_0040rotaryEncoder_002freadSpeed<9.4.4 @rotaryEncoder/readSpeedbarduino.html#g_t_0040rotaryEncoder_002fresetCount>9.4.5 @rotaryEncoder/resetCountharduino.html#g_t_0040rotaryEncoder_002frotaryEncoderD9.4.6 @rotaryEncoder/rotaryEncoder\arduino.html#g_t_0040rotaryEncoder_002fsubsref89.4.7 @rotaryEncoder/subsrefHarduino.html#Arduino-Servo-Functions69.5 Arduino Servo FunctionsJarduino.html#g_t_0040servo_002fdelete&9.5.1 @servo/deleteFarduino.html#g_t_0040servo_002fdisp"9.5.2 @servo/dispVarduino.html#g_t_0040servo_002freadPosition29.5.3 @servo/readPositionHarduino.html#g_t_0040servo_002fservo$9.5.4 @servo/servoLarduino.html#g_t_0040servo_002fsubsref(9.5.5 @servo/subsrefXarduino.html#g_t_0040servo_002fwritePosition49.5.6 @servo/writePositionXarduino.html#Arduino-Shiftregister-FunctionsF9.6 Arduino Shiftregister FunctionsZarduino.html#g_t_0040shiftRegister_002fdelete69.6.1 @shiftRegister/deleteVarduino.html#g_t_0040shiftRegister_002fdisp29.6.2 @shiftRegister/dispVarduino.html#g_t_0040shiftRegister_002fread29.6.3 @shiftRegister/readXarduino.html#g_t_0040shiftRegister_002freset49.6.4 @shiftRegister/resetharduino.html#g_t_0040shiftRegister_002fshiftRegisterD9.6.5 @shiftRegister/shiftRegister\arduino.html#g_t_0040shiftRegister_002fsubsref89.6.6 @shiftRegister/subsrefXarduino.html#g_t_0040shiftRegister_002fwrite49.6.7 @shiftRegister/writeDarduino.html#Arduino-SPI-Functions29.7 Arduino SPI FunctionsParduino.html#g_t_0040device_002fdelete-1(9.7.1 @device/deleteLarduino.html#g_t_0040device_002fdisp-1$9.7.2 @device/dispRarduino.html#g_t_0040device_002fsubsref-1*9.7.3 @device/subsrefRarduino.html#g_t_0040device_002fwriteRead.9.7.4 @device/writeReadLarduino.html#g_t_0040spidev_002fdelete(9.7.5 @spidev/deleteHarduino.html#g_t_0040spidev_002fdisp$9.7.6 @spidev/dispLarduino.html#g_t_0040spidev_002fspidev(9.7.7 @spidev/spidevNarduino.html#g_t_0040spidev_002fsubsref*9.7.8 @spidev/subsrefRarduino.html#g_t_0040spidev_002fwriteRead.9.7.9 @spidev/writeR eadJarduino.html#Arduino-Serial-Functions89.8 Arduino Serial FunctionsParduino.html#g_t_0040device_002fdelete-2(9.8.1 @device/deleteLarduino.html#g_t_0040device_002fdevice(9.8.2 @device/deviceLarduino.html#g_t_0040device_002fdisp-2$9.8.3 @device/dispJarduino.html#g_t_0040device_002fflush&9.8.4 @device/flushLarduino.html#g_t_0040device_002fread-1$9.8.5 @device/readRarduino.html#g_t_0040device_002fsubsref-2*9.8.6 @device/subsrefNarduino.html#g_t_0040device_002fwrite-1&9.8.7 @device/writeJarduino.html#Arduino-Device-Functions89.9 Arduino Device FunctionsParduino.html#g_t_0040device_002fdelete-3(9.9.1 @device/deleteParduino.html#g_t_0040device_002fdevice-1(9.9.2 @device/deviceLarduino.html#g_t_0040device_002fdisp-3$9.9.3 @device/dispNarduino.html#g_t_0040device_002fflush-1&9.9.4 @device/flushLarduino.html#g_t_0040device_002fread-2$9.9.5 @device/read\arduino.html#g_t_0040device_002freadRegister-149.9.6 @device/readRegisterRarduino.html#g_t_0040device_002fsubsref-3*9.9.7 @device/subsrefNarduino.html#g_t_0040device_002fwrite-2&9.9.8 @device/writeVarduino.html#g_t_0040device_002fwriteRead-1.9.9.9 @device/writeRead^arduino.html#g_t_0040device_002fwriteRegister-189.9.10 @device/writeRegisterRarduino.html#Arduino-Ultrasonic-FunctionsB9.10 Arduino Ultrasonic FunctionsTarduino.html#g_t_0040ultrasonic_002fdelete29.10.1 @ultrasonic/deleteParduino.html#g_t_0040ultrasonic_002fdisp.9.10.2 @ultrasonic/disp`arduino.html#g_t_0040ultrasonic_002freadDistance>9.10.3 @ultrasonic/readDistance`arduino.html#g_t_0040ultrasonic_002freadEchoTime>9.10.4 @ultrasonic/readEchoTimeVarduino.html#g_t_0040ultrasonic_002fsubsref49.10.5 @ultrasonic/subsref\arduino.html#g_t_0040ultrasonic_002fultrasonic:9.10.6 @ultrasonic/ultrasonic6arduino.html#Arduino-Addons&9.11 Arduino Addons$arduino.html#addon9.11.1 addonnarduino.html#arduinoioaddons_002eEEPRomAddon_002eEEPRomR9.11.2 arduinoioaddons.EEPRomAddon.EEPRomlarduino.html#arduinoioaddons_002eExampleAddon_002eEchoP9.11.3 arduinoioaddons.ExampleAddon.Echofarduino.html#arduinoioaddons_002eExampleLCD_002eLCDJ9.11.4 arduinoioaddons.ExampleLCD.LCDharduino.html#arduinoioaddons_002eRTCAddon_002eDS1307L9.11.5 arduinoioaddons.RTCAddon.DS1307arduino.html#arduinoioaddons_002eSimpleStepper_002eSimpleStepperd9.11.6 arduinoioaddons.SimpleStepper.SimpleSteppernarduino.html#arduinoioaddons_002eadafruit_002edcmotorv2R9.11.7 arduinoioaddons.adafruit.dcmotorv2varduino.html#arduinoioaddons_002eadafruit_002emotorshieldv2Z9.11.8 arduinoioaddons.adafruit.motorshieldv2jarduino.html#arduinoioaddons_002eadafruit_002estepperN9.11.9 arduinoioaddons.adafruit.stepper8arduino.html#Arduino-Sensors(9.12 Arduino SensorsJarduino.html#arduinosensor_002eDS130769.12.1 arduinosensor.DS1307Parduino.html#arduinosensor_002eGUVAS12SD<9.12.2 arduinosensor.GUVAS12SDLarduino.html#arduinosensor_002eMPC300289.12.3 arduinosensor.MPC3002Jarduino.html#arduinosensor_002eSI702169.12.4 arduinosensor.SI7021Harduino.html#Arduino-I_002fO-package09.13 Arduino I/O packageHarduino.html#arduinoio_002eAddonBase49.13.1 arduinoio.AddonBaseFarduino.html#arduinoio_002eFilePath29.13.2 arduinoio.FilePathFarduino.html#arduinoio_002eLibFiles29.13.3 arduinoio.LibFilesLarduino.html#arduinoio_002eLibraryBase89.13.4 arduinoio.LibraryBaseRarduino.html#arduinoio_002egetBoardConfig>9.13.5 arduinoio.getBoardConfigRarduino.html#Matlab-Compatibility-ClassesB9.14 Matlab Compatibility Classesfarduino.html#matlabshared_002eaddon_002eLibraryBaseJ9.14.1 matlabshared.addon.LibraryBase(arduino.html#Sensors9.15 Sensors&arduino.html#bme2809.15.1 bme280&arduino.html#bno0559.15.2 bno055&arduino.html#lis3dh9.15.3 lis3dh(arduino.html#lps22hb9.15.4 lps22hb(arduino.html#lsm6dso9.15.5 lsm6dso(arduino.html#mpu60509.15.6 mpu6050&arduino.html#si70219.15.7 si70216arduino.html#Test-Functions&9.16 Test FunctionsDarduino.html#arduino_005fbistsetup09.16.1 arduino_bistsetuparduino-0.12.1/doc/arduino.texi0000644000000000000000000007627214545566645013325 0ustar00\input texinfo @c -*-texinfo-*- @c Copyright (c) 2018-2024, John Donoghue @c Octave Arduino - a somewhat Matlab compatible Arduino toolkit for GNU octave. @c For manually generating the documentation use @c LANGUAGE=en makeinfo --html --no-split arduino.texi @c %*** Start of HEADER @setfilename arduino.info @settitle Arduino Toolkit - a somewhat Matlab compatible arduino toolkit for GNU octave. @afourpaper @paragraphindent 0 @finalout @set COPYRIGHT_DATE 2018-2024 @c @afourwide @c %*** End of the HEADER @include version.texi @include macros.texi @macro boxnote {args} @cartouche @strong{NOTE} \args\ @end cartouche @end macro @c %*** Start of TITLEPAGE @titlepage @title Arduino Toolkit @value{VERSION} @subtitle a somewhat MATLAB compatible Arduino toolkit for @acronym{GNU} Octave. @author John Donoghue @page @vskip 0pt plus 1filll Copyright @copyright{} @value{COPYRIGHT_DATE} John Donoghue Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. Permission is granted to copy and distribute translations of this manual into another language, under the same conditions as for modified versions. @page @heading Distribution The @acronym{GNU} Octave arduino package is @dfn{free} software. Free software is a matter of the users' freedom to run, copy, distribute, study, change and improve the software. This means that everyone is free to use it and free to redistribute it on certain conditions. The @acronym{GNU} Octave arduino package is not, however, in the public domain. It is copyrighted and there are restrictions on its distribution, but the restrictions are designed to ensure that others will have the same freedom to use and redistribute Octave that you have. The precise conditions can be found in the @acronym{GNU} General Public License that comes with the @acronym{GNU} Octave arduino package and that also appears in @ref{Copying}. To download a copy of the @acronym{GNU} Octave arduino package, please visit @url{https://github.com/gnu-octave/octave-arduino/releases}. @end titlepage @c %*** End of TITLEPAGE @c %*** Start of BODY @dircategory Math @direntry * Arduino for Octave: (arduino). Arduino Toolbox for Octave @end direntry @contents @ifnottex @node Top @top Introduction The Arduino toolkit is a somewhat Matlab compatible arduino toolkit for GNU octave. @end ifnottex @menu * Installing and loading:: Installing and loading the Arduino toolkit * Hardware setup:: Setting up the Arduino hardware * Connecting to an arduino:: Making a connection to an arduino device * Basic Input and Output Overview:: Performing basic I/O * Protocol based I/O Overview:: Performing protocol based I/O * Addons Overview:: Arduino Addons * Sensors Overview:: Sensors * Examples:: Examples using the Arduino toolkit * Function Reference:: Arduino toolkit functions * Copying:: Copying * Index:: Index @end menu @c ------------------------------------------------------------------------- @node Installing and loading @chapter Installing and loading @cindex Installing and loading The Arduino toolkit must be installed and then loaded to be used. It can be installed in @acronym{GNU} Octave directly from octave-forge, or can be installed in an off-line mode via a downloaded tarball. @boxnote{The toolkit requires the @url{https://www.arduino.cc/en/software, Arduino IDE} in order to program Arduino devices.} @boxnote{The toolkit has a dependency on the instrument-control package, so it must be installed in order to successfully install the Arduino toolkit} The toolkit must be then be loaded once per each @acronym{GNU} Octave session in order to use its functionality. @section Online Direct install @cindex Online install With an internet connection available, the Arduino package can be installed from octave-forge using the following command within @acronym{GNU} Octave: @example pkg install -forge arduino @end example The latest released version of the toolkit will be downloaded and installed. @section Off-line install @cindex Off-line install With the arduino toolkit package already downloaded, and in the current directory when running @acronym{GNU} Octave, the package can be installed using the following command within @acronym{GNU} Octave: @example pkg install arduino-@value{VERSION}.tar.gz @end example @section Loading @cindex Loading Regardless of the method of installing the Arduino toolkit, in order to use its functions, the toolkit must be loaded using the pkg load command: @example pkg load arduino @end example The toolkit must be loaded on each @acronym{GNU} Octave session. @c ------------------------------------------------------------------------- @node Hardware setup @chapter Hardware setup @cindex Hardware setup In order to use the arduino hardware with the toolkit, it must be programmed with special firmware. @section Programming the Arduino @cindex Programming the Arduino To program the hardware, using a default configuration, run the arduinosetup command: @example arduinosetup @end example A temporary Arduino project will be created, with the Arduino toolkit files copied to it and the Arduino IDE will open. Set the board type and port correctly for the connected Arduino and press the upload button on the IDE. The sources will be compiled and then uploaded to the connected arduino board. After successful upload the Arduino IDE should be closed. @boxnote{The arduino programming is not compatible with the Matlab arduino library, so must be programmed by the Octave Arduino toolkit to communicate to the arduino, even if it was previously used to work with Matlab.} @boxnote{The toolkit requires the @url{https://www.arduino.cc/en/software, Arduino IDE} in order to program the Arduino device. The binary can set using the 'arduinobinary' property when running setup. For arduino IDEs before version 2, if the toolkit can not find the IDE, run the IDE manually, close it and retry programming the Arduino. Otherwise, use the 'arduino' binary property.} @section Known Arduino Board Types @cindex Known Arduino Board Types The board type must be known in order to successfully detect and connect to the Arduino board after programming. Currently, known boards are: @itemize @bullet @item Arduino Due @item Arduino UNO @item Arduino Mega 2560 @item Arduino Nano @item Arduino Nano Every @item Arduino Nano 33 BLE @item Arduino Nano RP2040 Connect @item Arduino Pro/Pro Mini @item Arduino Pro Micro @item Arduino Leonardo @item Arduino Micro @item Arduino MKR1000 @item Arduino MKRZero @item Sparkfun SAMD21 @item Arduino Lilypad @item Arduino UNO WiFi rev2 @boxnote{The Arduino servo library code may require modifications to eliminate conflicts between servos and the tone library} @item Arduino UNO WiFi r4 @item Arduino UNO Minima r4 @item Raspberry Pi Pico @item EPS32 Dev @end itemize Additional boards can be added easily, however require minor code changes. @c ------------------------------------------------------------------------- @node Connecting to an arduino @chapter Connecting to an arduino @cindex Connecting to an arduino To control an arduino device, a connection must be made to it by creating an arduino object. @section Connecting to a single arduino @cindex Connecting to a single arduino Assuming a single arduino device is connected to the computer, creating an arduino object with no arguments will find the connected arduino and connect to it: @example ar = arduino() @end example @section Connecting to a specific arduino @cindex Connecting to a specific arduino Where multiple arduinos may be connected to the computer, a specific board can be connected by specifying the name of the port it is connected to: @example ar = arduino("/dev/ttyACM0") @end example The port name will be operating system dependent. @section Querying available arduinos @cindex Querying available arduinos To list the ports of all @emph{programmed} available arduinos, the scanForArduinos function can be used: @example scanForArduinos @end example It will provide a list of all available boards it can find with the port they are connected to. @boxnote{The scanForArduinos function will only detect boards that have been programmed using the arduinosetup command} @c ------------------------------------------------------------------------- @node Basic Input and Output Overview @chapter Basic Input and Output Overview @cindex Basic Input and Output Overview Basic input and output can be performed on a connected arduino device using by calling the read and write functions for a specific named pin on the arduino. A list of available pins can get found from the pins property of the connected arduino object and are also displayed as part of the default shown properties: @example ar = arduino(); % get the pin names pins = ar.availablepins @end example Pin generally follow a naming scheme of D for digital pins and A for analog pins. Digital pins can be used to read and write digital data, but can not read analog voltages. Analog pins can perform digital I/O as well as reading voltages. @section Performing Digital I/O @cindex Performing Digital I/O A pin's digital logic value can be true (1) or false (0) and can be set using the writeDigitalPin function. The following example attempts to set the D2 pin of the connected arduino object "ar" to true, waits 5 seconds and then sets it to false: @example writeDigitalPin (ar, "d2", true); pause 5 writeDigitalPin (ar, "d2", false); @end example Using the readDigitalPin will read the current logic state of the pin. @example value = readDigitalPin (ar, "d2"); @end example @section Performing Analog Input @cindex Performing Analog Input For analog pins, the voltage level can be read using a analog to digital conversion and will return a voltage level between 0 and the boards voltage (nominally 5V): @example value = readVoltage (ar, "a0"); @end example The raw digital value of the pin can also be read instead of a voltage, giving a value between 0 and 2^x where x is the number of bits used by the analog to digital converter. @example value = readAnalogPin (ar, "a0"); @end example @c ------------------------------------------------------------------------- @node Protocol based I/O Overview @chapter Protocol based I/O Overview @cindex Protocol based I/O Overview The arduino toolkit supports more complex I/O for SPI, I2C, Servo control and more. @section SPI communication @cindex SPI communication SPI communication can be performed by creating a SPI device object and then calling the writeRead function: @example spi = device (ar, "spichipselectpin", "d2"); @end example The function call expects a connected arduino object as the first argument, followed by the chip select pin of the SPI device. After a device is created, a write to device followed by read can can be made using the writeRead function: @example spi = device (ar, "spichipselectpin", "d2"); data = writeRead (spi, 100); @end example @section I2C communication @cindex I2C communication I2C communication can be performed by creating an I2C device object for a specific I2C address. The following example creates an I2C device that will communicate with a I2C device at address 100" @example i2c = device (ar, "i2caddress", 100); @end example After creating an I2C device, data can be read and written using read, write, readRegister and writeRegister. The data to send and receive will be device dependent. @section Servo communication @cindex Servo communication Servo communication can be performed after creating a servo device object to operate on a PWM pin: @example servoobj = servo(ar, "d9", "minpulseduration", 1.0e-3, ... "maxpulseduration", 2e-3); @end example The servo function expects the connected arduino object and the PWM pin that the servo is connected to. Optional properties can be specified to control the setup of device. In the example, the min and max pulse width values are set. Using the servo object the current position and be read or set with values ranging between 0 to 1, with 0 being the minimum pulse width and 1 being the maximum. The following example sets the servo to its middle position. @example servoobj = servo(ar, "d9", "minpulseduration", 1.0e-3, ... "maxpulseduration", 2e-3); writePosition (servoobj, 0.5); @end example @section Shift Registers @cindex Shift Registers A shift register can be controlled by creating a shiftRegister object: @example registerobj = shiftRegister(ar, '74hc164', "d2", "d3"); @end example The parameters required are dependent on the type of shift register created. Once a register object has been created, it can be read and written to using the read and write functions. @section Rotary Encoders @cindex Rotary Encoder A rotary encoder can be created by creating a rotaryEncoder object. @example encoder = rotaryEncoder(ar, "d2", "d3", 180); @end example Using the created object, the rotary encoder value and speed can be read. @section Ultrasonic Sensors @cindex Ultrasonic Sensors An ultrasonic sensor can be read by creating an ultrasonic object. @example sensor = ultrasonic(ar, "d9", "d10"); @end example Using the created object, the sensor distance and echo time and be read. @section Serial communication @cindex Serial communication Serial communication can be performed on devices that support multiple serial devices such as the leonardo and mega2560 boards. The communications port to Octave is reserved and can not be used as a user controlled communications port. Serial communication can be performed by creating a serial device object and then calling the read and write functions: @example ser = device (ar, "serial", 1); @end example The function call expects a connected arduino object as the first argument, followed "serial" and serial id. After a device is created, the device can be read and written: @example ser = device (ar, "serial", 1); write(ser, "hello"); data = read(ser, 100); @end example @c ------------------------------------------------------------------------- @node Addons Overview @chapter Addons Overview @cindex Addons Overview This chapter provides an overview of the arduino package addon functionality for adding additional addons to arduino. @section Addon Introduction @cindex Addon Introduction Addons provide a way of adding additional functionality to the arduino toolkit that provides Matlab access directly to the arduino hardware. Addons are implemented in two parts. @enumerate @item code running on the arduino that implements the required functionality @item a octave wrapper class that provides the Matlab interface and communication to the code. @end enumerate Both parts are required to create a plugin. The arduino toolkit provides a number of pre-created addons. These can be seen using the following command: @example @code { listArduinoLibraries } @end example The command will display all known arduino libraries (addons as well as core libraries), however addons typically use a "foldername/classname" for this naming. @xseealso{listArduinoLibraries} @section Creating an addon @cindex Creating an addon An addon requires at minimum 3 things: @enumerate @item A addon package directory that will contain the addon files @item A Matlab file within that directory that is a subclass of arduinoio.LibraryBase @item A arduino source/header file that contains the arduino code to load, sub-classed for LibraryBase @end enumerate So the addon directory structure at a minimum will be: @example @code { +arduinoioaddons (dir) [somewhere in the octave load path] +MyAddons (dir) MyAddon1.m MyAddon1.h } @end example @subsection Addon package directory @cindex Addon package directory The addon architecture looks for plugins in the octave load path in a package directory called +arduinoioaddons So this directory must be created somewhere within the paths that octave will check for functions. In addition, the addon architecture expects plugins to be contained in a sub directory within the +arduinoioaddons folder. The subdirectory must begin with a '+'. Multiple plugin .m files can be within the same sub directory. @subsection Addon package .m file @cindex Addon package .m file The Matlab interface file within the addon directory provides the Matlab interface for the arduino code as well as provides information about the addon. @subsubheading Class inheritance and required properties The interface file must be a subclass of arduinoio.LibraryBase and must contain some constant properties values that provide the information. A minimum example of required is below: @example @code { classdef MyAddon1 < arduinoio.LibraryBase properties(Access = protected, Constant = true) LibraryName = 'MyAddons/MyAddon1'; CppHeaderFile = fullfile(arduinoio.FilePath(mfilename('fullpath')), 'MyAddon1.h'); CppClassName = 'MyAddon1'; endproperties . . . endclassdef } @end example The following constant properties can be set within the addon: @table @asis @item LibraryName (Required) The name of the addon. My convention this is usually the directoryname / theclassname @item CppHeaderFile (Required) The header file for the arduino code @item CppSourceFile (Optional) The source file (if any) for the arduino code @item CppClassName (Required) The classname used within the cppheaderfile for the arduino library @item DependantLibraries (Optional) Any additional addons or cores that are needed for this library to be used @item ArduinoLibraryHeaderFiles (Optional) Any additional header files that need to be included @end table @subsubheading Class constructor The Matlab class constructor will be called from the addon function when creating a instance of the addon and should initialize at least two properties in inherited from arduinoio.LibraryBase: @enumerate @item Parent should be set to the first input argument (the arduino class) @item Pins should be set to a list of pins that are used for the plugin @end enumerate @example @code { classdef MyAddon1 < arduinoio.LibraryBase . . methods function obj = MyAddon1(parentObj, varargin) obj.Parent = parentObj; # no pins being used obj.Pins = []; # send any command to the arduino during setup ? endfunction . . endmethods endclassdef } @end example @subsubheading Class functions The class functions will usually communicate to the arduino and use the response for what is returned to the user. By convention, the commands sent to the arduino are defined as constants in the class file but do not have to be. @example @code { classdef MyAddon1 < arduinoio.LibraryBase properties(Access = private, Constant = true) INIT_COMMAND = hex2dec('00'); FUNC1_COMMAND = hex2dec('01'); endproperties . . methods function obj = MyAddon1(parentObj, varargin) obj.Parent = parentObj; # no pins being used obj.Pins = []; # send any command to the arduino during setup ? sendCommand(obj.Parent, obj.LibraryName, obj.INIT_COMMAND, []); endfunction function retval = func1(obj) cmdID = obj.FUNC1_COMMAND; retval = sendCommand(obj.Parent, obj.LibraryName, cmdID, []); endfunction . . endmethods endclassdef } @end example @boxnote{the sendCommand uses the objects parent for the arduino, the objects library name and the command id} @xseealso{sendCommand} @subsection Addon package header file @cindex Addon package header file The header file should contain a class that matches the functionally and information of the matlab file and provides the ability to register the code on the arduino. The following things should occur in the arduino class files: @enumerate @item The class name within the file must be the same as the one set in the .m file CppClassName property. @item The libName variable must be the same as the LibraryName property. @item The constructor should call registerLibrary @item the commandHandler function to act on cmdID values that match the commands that will be sent from .m file and send data back using sendResponseMsg @item on receiving unknown cmdID values, the commandHandler should use sendUnknownCmdIDMsg @end enumerate An example, matching the previous .m file code is below: @example @code { #include "LibraryBase.h" #define MYADDON1_INIT 0x00 #define MYADDON1_FUNC1 0x01 class MyAddon1 : public LibraryBase @{ uint8_t cnt; public: MyAddon1(OctaveArduinoClass& a) @{ libName = "MyAddons/MyAddon1"; a.registerLibrary(this); @} void commandHandler(uint8_t cmdID, uint8_t* data, uint8_t datasz) @{ switch (cmdID) @{ case MYADDON1_INIT: @{ cnt = 0; sendResponseMsg(cmdID, 0,0); break; @} case MYADDON1_FUNC1: @{ // func 1 is just returning a uint8 count of number of times called cnt ++; sendResponseMsg(cmdID, &cnt, 1); break; @} default: @{ // notify of invalid cmd sendUnknownCmdIDMsg(); @} @} @} @} }; @end example The body of functions can be in the CppSourceFile file is it is defined or within the header file as illustrated above. @subsection Verify octave can see the addon @cindex Verify octave can see the addon Use the listArduinoLibaries command to verify that the new addon appears in the list of known libraries. If it does not, ensure that the +arduinoioaddons directory is within one of the octave class paths, and that the directory structure and inheritance requirements have been met. @section Using addons @cindex Using Addons @subsection Programming the arduino with the addon @cindex Programming the arduino with the addon To use a addon, the code must be programmed onto the arduino. Using the libraries command, when creating a arduino object, the arduino can be reprogrammed if the library does not already exist on the arduino. @example @code { ar = arduino([],[], 'libraries', 'MyAddons/MyAddon1', 'forcebuild', true) } @end example The libraries property of the arduino object should list the libraries programmed on the arduino. Alternatively, the library can be added using the libraries property and arduinosetup @xseealso{arduino, arduinosetup} @subsection Creating a addon object @cindex Creating a addon object An object of the addon type can be created using the addon command. @example @code { ar = arduino([],[], 'libraries', 'MyAddons/MyAddon1', 'forcebuild', true) obj = addon(ar, "MyAddons/MyAddon1"); } @end example @c ------------------------------------------------------------------------- @node Sensors Overview @chapter Sensors Overview @cindex Sensors Overview There are two types of sensors available: @enumerate @item Matlab compatible(ish) sensors for environment and IMU. @item Additional lightweight wrappers for some chips in a arduinosensor namespace. @end enumerate @section Matlab Compatible Sensors @cindex Matlab Compatible Sensor @subsection Overview Matlab compatible functions are provided for a number of sensors, using a similar function naming as provided by the Matlab arduino package. @subsection Available Sensors @cindex Available Sensors The functions for each sensor is listed in the function reference, @ref{Sensors} and provides for: @table @asis @item bme280 BME280 temperature, pressure and humidity sensor @item bno005 BNO055 acceleration, angular velocity, orientation and magnetic field sensor @item lis3dh LIS3DH acceleration sensor @item lps22hb LPS22HB temperature and pressure sensor @item lsm6dso LSM6DSO acceleration, angular velocity sensor @item mpu6050 MPU-6050 acceleration, angular velocity sensor @item SI7021 SI7021 temperature and humidity sensor @end table @section Lightweight Arduino Sensors @cindex Arduino Sensor @subsection Overview Arduino sensors are a collection of lightweight wrappers around other underlying protocols for providing specific sensor functionality. For instance a DS1307 chip communicates using I2C protocol and so a DS1307 class exists that provides the conversion/commands in order to communicate to the chip. Using the class, providing the functionality is very easy: @example @code { a = arduino() rtc = arduinosensor.DS1307(a) # get and display rtc time as a date string datestr(rtc.clock) } @end example It is lightweight compared to the addon functionality, as it only requires a wrapper class rather than add on code, however it is limited to then using available addon and core codes rather than creating new ones. Currently the are only a small number of sensors available, however this will be built upon in future versions. @subsection Available Sensors @cindex Available Sensors The functions for each sensor is listed in the function reference, @ref{Arduino Sensors} and provides for: @table @asis @item DS1307 DS1307 RTC clock using i2c. @item MPC3002 MPC3002 ADC using SPI @item SI7021 SI7021 temperature and humidity sensor @item GUVAS12SD GUVAS12SD analog UV-B sensor @end table @c ------------------------------------------------------------------------- @node Examples @chapter Examples @cindex Examples @section Blinking an LED @cindex Blinking an LED This example shows blinking the inbuilt LED on the Arduino board. Code is available by running: @example edit examples/example_blink @end example @heading Hardware setup This example uses in the builtin LED, so requires only a connection of the Arduino board to computer for communication. @heading Create an Arduino object @example ar = arduino (); @end example If you have more than one Arduino board connected, you may need to specify the port in order to connect to the correct device. @heading Query Device for pins connected to builtin LED The pin connected to the Arduino UNO built in led if D13. @example led_pin = "d13"; @end example The connected pins can be queried programatically if desired. @example pins = getLEDTerminals (ar); @end example Connected to a Arduino UNO would return a list pins containing only one item '13'. The terminal number can be converted to a pin using getPinsFromTerminals: @example led_pin = getPinsFromTerminals (ar, pins@{1@}); @end example @heading Turn the LED off Write a 0 value to the pin to turn it off. @example writeDigitalPin (ar, led_pin, 0); @end example @heading Turn the LED on Write a 1 value to the pin to turn it on @example writeDigitalPin (ar, led_pin, 1); @end example @heading Making the LED blink Add a while loop with a pause between the changes in the pin state to blink. @example while true writeDigitalPin (ar, led_pin, 0); pause (0.5) writeDigitalPin (ar, led_pin, 1); pause (0.5) endwhile @end example @section Using I2C to communicate with an EEPROM @cindex Using I2C to communicate with an EEPROM This example shows using I2C to communicate with a EEPROM chip. Code is available by running: @example edit examples/example_i2c_eeprom @end example @heading Hardware setup Using an Arduino UNO, the board should be configured with the following connections between the board and a 24XX256 EEPROM chip: @table @asis @item A4 Connected to pin 5 of EEPROM @item A5 Connected to pin 6 of EEPROM @item 5V Connected to pin 8 of EEPROM @item GND Connected to pin 1,2,3,4 of EEPROM @end table @heading Create an Arduino object @example ar = arduino (); @end example If you have more than one Arduino board connected, you may need to specify the port in order to connect to the correct device. @heading Query I2C pins Display the I2C terminals of the board: @example getI2CTerminals(ar) @end example @heading Scan the arduino for the connected device @example scanI2Cbus(ar) @end example The devices listed should contain 0x50, the address of the EEPROM chip. @heading Create an I2C object to communicate to the EEPROM @example eeprom = device (ar, "i2caddress", 0x50) @end example @heading Write data to the EEPROM The EEPROM expects the first byte to be the page number, the second the offset, followed by data, so to write 1 2 3 4, starting address 0 (page 0, offset 0): @example write(eeprom, [0 0 1 2 3 4]) @end example @heading Reading from the EEPROM Reading from the EEPROM requires first writing the address to read from, in this case, if we want to read the 3, 4, this would be page 0, offset 2: @example write(eeprom, [0 2]) @end example Next read the 2 bytes: @example data = read(eeprom, 2) @end example @c ------------------------------------------------------------------------- @section Using SPI to communicate with a mcp3002 10 bit ADC @cindex Using SPI to communicate with a mcp3002 10 bit ADC This example shows using SPI to communicate with an mcp3002 10 bit ADC. Code is available by running: @example edit examples/example_spi_mcp3002 @end example @heading Hardware setup Using an Arduino UNO, the board should be configured with the following connections between the board and a mcp3002 chip: @table @asis @item D10 Connected to pin 1 (CS) of MCP3002 @item D11 Connected to pin 5 (DI) of MCP3002 @item D12 Connected to pin 6 (DO) of MCP3002 @item D13 Connected to pin 7 (CLK) MCP3002 @item VCC Connected to pin 8 (VDD) MCP3002 @item GND Connected to pin 4 (VSS) MCP3002 @item Analog input Connected from pin 2 of the MCP3002 to a LOW (< 5V) voltage to measure @end table @heading Create an Arduino object @example ar = arduino (); @end example If you have more than one Arduino board connected, you may need to specify the port in order to connect to the correct device. @heading Create an SPI object to communicate to the MCP3002 @example adc = device(ar, "spichipselectpin", "d10") @end example The d10 is the chip select pin connected from the Arduino to the MCP3002. @heading Read the ADC The MCP3002 expects specific commands in order to read a channel. For illustration for the command to read chan 0 in single ended mode: @example command (bits) in MSB mode to device: [START SGL ODN MSBF X X X X] [ X X X X X X X X ] 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 [chan 0 ] MSB data back: X X X X X 0 D D D D D D D D D D @end example D is a output data bit X is a don't care what value is input/output The first byte contains the command and start of the data read back, the second bytes is written to clock out the rest of the ADC data. In hex, this corresponds to 0xDF 0xFF, @example data = writeRead(adc, [hex2dec("DF") hex2dec("FF")]) @end example Of the data returned, the last 10 bits is the actual data, so convert data to a 16 bit value: @example val = uint16(data(1))*256 + uint16(data(2)) @end example Then bitand it to remove the non value parts, to get the ADC value: @example val = bitand (val, hex2dec('3FF')) @end example To make the value correspond to a voltage it needs to be scaled as 0 will be 0 Volts, 1023 will be 5 Volts. @example volts = double(val) * 5.0 / 1023.0; @end example @c ------------------------------------------------------------------------- @node Function Reference @chapter Function Reference @cindex Function Reference The functions currently available in the Arduino toolkit are described below; @include functions.texi @c ------------------------------------------------------------------------- @include gpl.texi @c ------------------------------------------------------------------------- @node Index @unnumbered Index @printindex cp @bye arduino-0.12.1/doc/functions.texi0000644000000000000000000037703514545566645013675 0ustar00@c --------------------------------------------------- @node General Functions @section General Functions @cindex General Functions @c General Functions arduinosetup @c ----------------------------------------- @subsection arduinosetup @cindex arduinosetup @deftypefn {} {@var{retval} =} arduinosetup () @deftypefnx {} {@var{retval} =} arduinosetup (@var{propertyname}, @var{propertyvalue}) Open the arduino config / programming tool to program the arduino hardware for usage with the Octave arduino functions. arduinosetup will create a temporary project using the arduino IDE and allow compiling and programming of the code to an arduino. @subsubheading Inputs @var{propertyname}, @var{propertyvalue} - A sequence of property name/value pairs can be given to set defaults while programming. Currently the following properties can be set: @table @asis @item libraries The value should be the name of a library, or string array of libraries to program on the arduino board. @item arduinobinary The value should be the name/path of the arduino IDE binary for programming. If not specified, the function will use getpref preferences of arduino.arduino_binary, and if not found, the function will attempt to find the binary itself. If provided, the value will be saved to preferences for future calls. @end table @subsubheading Outputs @var{retval} - return 1 if arduino IDE returned without an error @xseealso{arduino, __arduino_binary__} @end deftypefn @c General Functions isarduino @c ----------------------------------------- @subsection isarduino @cindex isarduino @deftypefn {} {@var{retval} =} isarduino (@var{obj}) Check if input value is an arduino object Function is essentially just a call of @code { retval = isa(obj, "arduino"); } @subsubheading Inputs @var{obj} - The object to check @subsubheading Outputs @var{retval} is true, if obj is an arduino object, false otherwise. @xseealso{arduino} @end deftypefn @c General Functions listArduinoLibraries @c ----------------------------------------- @subsection listArduinoLibraries @cindex listArduinoLibraries @deftypefn {} {@var{retval} =} listArduinoLibraries () @deftypefnx {} {@var{retval} =} listArduinoLibraries (@var{libtypes}) Retrieve list of all known arduino library modules that are available. @subsubheading Inputs @var{libtypes} - optional specifier for type of libraries to list. Options are: @table @asis @item all List core and addons @item core List core only libraries @item addons List addons only @end table When no libtypes is specified, all libraries are shown. @subsubheading Outputs @var{retval} is an cell array of string library names that are available for programming to the arduino. @xseealso{arduino, arduinosetup} @end deftypefn @c General Functions scanForArduinos @c ----------------------------------------- @subsection scanForArduinos @cindex scanForArduinos @deftypefn {} {@var{retval} =} scanForArduinos () @deftypefnx {} {@var{retval} =} scanForArduinos (@var{maxCount}) @deftypefnx {} {@var{retval} =} scanForArduinos (@var{"debug"}) @deftypefnx {} {@var{retval} =} scanForArduinos (@var{maxCount}, @var{type}) @deftypefnx {} {@var{retval} =} scanForArduinos (@var{propertyname}, @var{propertvalue} ...) Scan system for programmed serial connected arduino boards. scanForArduinos will scan the system for programmed arduino boards and return at most @var{maxCount} of them as a cell array in @var{retval}. @subsubheading Inputs @var{maxCount} - max number of arduino boards to detect. if @var{maxCount} is not specified, or is a less than 1, the function will return as many arduino boards as it can detect. @var{type} - optional board type to match. If specified, the board type must match for the arduino to be added to the return list. @var{"debug"} - if single input parameter is "debug", the scanForArduinos will display debug information as it scans all available ports for arduinos. @var{propertyname}, @var{propertyvalue} - property name/value pairs to match search with. @table @asis @item 'BaudRate' Numeric BaudRate to use when trying to scan for arduinos. @item 'MaxCount' Max number of arduinos to scan for. @item 'BoardType' Boardtype to match. @item 'Debug' Logical flag for debug mode. @end table @subsubheading Outputs @var{retval} structure cell array of matching detected arduino boards. Each cell value of the cell array will contain a structure with values of: @table @asis @item port the serial port the arduino is connected to @item board the board type of the arduino @end table @xseealso{arduino} @end deftypefn @c --------------------------------------------------- @node Arduino Functions @section Arduino Functions @cindex Arduino Functions @c Arduino Functions @arduino/arduino @c ----------------------------------------- @subsection @@arduino/arduino @cindex arduino @deftypefn {} {@var{retval} =} arduino () @deftypefnx {} {@var{retval} =} arduino (@var{port}) @deftypefnx {} {@var{retval} =} arduino (@var{port}, @var{board}) @deftypefnx {} {@var{retval} =} arduino (@var{port}, @var{board}[, [@var{propname}, @var{propvalue}]*) @deftypefnx {} {@var{retval} =} arduino (@var{iaddress}) @deftypefnx {} {@var{retval} =} arduino (@var{ipaddress}, @var{board}) Create a arduino object with a connection to an arduino board. @subsubheading Inputs @var{port} - full path of serial port to connect to. For Linux, usually /dev/ttySXXX, for windows COMXX. @var{board} - name of board to connect (default is 'uno'). @var{propname}, @var{propvalue} - property name and value pair for additional properties to pass to the creation of the arduino object. Currently properties are ignored, with the exception of: @table @asis @item debug true / false flag for whether setting debug (default false) @item forcebuildon true / false flag for whether to force show of the arduino IDE to rebuild the installed code on the arduino (default false) @item baudrate (read only) the communications baudrate to the board. (default 9600) @item libraries The libraries to be enabled on the arduino board. (default uses whatever is already installed) @end table if the arduino function is called without parameters, it will scan for the first available arduino it can find and connect to it. @subsubheading Outputs @var{retval} - a successfully connected arduino object. @subsubheading Properties The arduino object has the following public properties: @table @asis @item name name assigned to the arduino object @item debug true / false flag for whether debug is turned on @item forcebuildon true / false flag for whether to force show of the arduino IDE to reprogram the arduino @item port (read only) the communications port the board is connected to. @item baudrate (read only) the communications baudrate to the board. @item board (read only) The name of the board type that the arduino connected to @item libraries (read only) The libraries currently programmed onto the board @item availablepins The pins available for use on the board @item analogreference The analog voltage reference @end table @xseealso{scanForArduinos, arduinosetup} @end deftypefn @c Arduino Functions @arduino/checkI2CAddress @c ----------------------------------------- @subsection @@arduino/checkI2CAddress @cindex checkI2CAddress @deftypefn {} {@var{retval} =} checkI2CAddress (@var{ar}, @var{address}) @deftypefnx {} {@var{retval} =} checkI2CAddress (@var{ar}, @var{address}, @var{bus}) Check that an address of given address responds on the I2C bus @subsubheading Inputs @var{ar} - arduino object connected to a arduino board. @var{address} - I2C address number to check @var{bus} - bus number to check for I2C device, when multiple buses are available. If the bus is not specified, it will default to 0. @subsubheading Outputs @var{retval} - boolean value of true if address responds on the I2C bus @subsubheading Example @example @code { # create arduino connection. ar = arduino(); # scan for devices on the I2C bus checkI2CAddress (ar) # output if a device using that address is attached ans = 1 } @end example @xseealso{arduino, scanI2Cbus} @end deftypefn @c Arduino Functions @arduino/configurePin @c ----------------------------------------- @subsection @@arduino/configurePin @cindex configurePin @deftypefn {} {@var{currmode} =} configurePin (@var{ar}, @var{pin}) @deftypefnx {} {} configurePin (@var{ar}, @var{pin}, @var{mode}) Set/Get pin mode for a specified pin on arduino connection. configurePin (@var{ar}, @var{pin}) will get the current mode of the specified pin. configurePin (@var{ar}, @var{pin}, @var{mode}) will attempt set the pin to the specified mode if the mode is unset. @subsubheading Inputs @var{ar} - the arduino object of the connection to an arduino board. @var{pin} - string name of the pin to set/get the mode of. @var{mode} - string mode to set the pin to. @subsubheading Outputs @var{mode} - string current mode of the pin. Valid modes can be: @itemize @bullet @item AnalogInput - Acquire analog signals from pin @item DigitalInput - Acquire digital signals from pin @item DigitalOutput - Generate digital signals from pin @item I2C - Specify a pin to use with I2C protocol @item Pullup - Specify pin to use a pullup switch @item PWM - Specify pin to use a pulse width modulator @item Servo - Specify pin to use a servo @item SPI - Specify a pin to use with SPI protocol @item Interrupt - Specify a pin to use for with interrupts @item Reserved - Specify a pin to be reserved @item Unset - Clears pin designation. The pin is no longer reserved and can be automatically set at the next operation. @end itemize @xseealso{arduino} @end deftypefn @c Arduino Functions @arduino/configurePinResource @c ----------------------------------------- @subsection @@arduino/configurePinResource @cindex configurePinResource @deftypefn {} {@var{currmode} =} configurePinResource (@var{ar}, @var{pin}) @deftypefnx {} {} configurePinResource (@var{ar}, @var{pin}, @var{owner}, @var{mode}) @deftypefnx {} {} configurePinResource (@var{ar}, @var{pin}, @var{owner}, @var{mode}, @var{force}) Set/Get pin mode for a specified pin on arduino connection. configurePinResource (@var{ar}, @var{pin}) will get the current mode of the specified pin. configurePinResource (@var{ar}, @var{pin}, @var{owner}, @var{mode}) will attempt set the pin to the specified mode and owner. If the pin is already owned by another owner, the configure will fail unless the force option is used. If the mode is already set, configure will fail unless force is used. @subsubheading Inputs @var{ar} - the arduino object of the connection to an arduino board. @var{pin} - string name of the pin to set/get the mode of. @var{mode} - string mode to set the pin to. @var{owner} - string name to use as the pin owner. @var{force} - boolean to force mode change. If not set, it will be false. @subsubheading Outputs @var{currmode} - current string mode of the pin. Valid modes can be: @itemize @bullet @item AnalogInput - Acquire analog signals from pin @item DigitalInput - Acquire digital signals from pin @item DigitalOutput - Generate digital signals from pin @item I2C - Specify a pin to use with I2C protocol @item Pullup - Specify pin to use a pullup switch @item PWM - Specify pin to use a pulse width modulator @item Servo - Specify pin to use a servo @item SPI - Specify a pin to use with SPI protocol @item Interrupt - Specify a pin to use with interrupts @item Reserved - Pin marked reserved, but not for of any particular mode @item Unset - Clears pin designation. The pin is no longer reserved and can be automatically set at the next operation. @end itemize @xseealso{arduino, configurePin} @end deftypefn @c Arduino Functions @arduino/decrementResourceCount @c ----------------------------------------- @subsection @@arduino/decrementResourceCount @cindex decrementResourceCount @deftypefn {} {@var{count} =} decrementResourceCount (@var{ar}, @var{resource}) Decrement the count of a named resource by 1 and return the new count. @subsubheading Inputs @var{ar} - connected arduino object @var{resource} - name of resource to decrement count. @subsubheading Outputs @var{count} = count of uses registered to resource. @xseealso{getResourceCount. incrementResourceCount} @end deftypefn @c Arduino Functions @arduino/delete @c ----------------------------------------- @subsection @@arduino/delete @cindex delete @deftypefn {} {} delete (@var{dev}) Free resources of an arduino object. @subsubheading Inputs @var{dev} - object to free @xseealso{arduino} @end deftypefn @c Arduino Functions @arduino/disp @c ----------------------------------------- @subsection @@arduino/disp @cindex disp @deftypefn {} {} disp (@var{ar}) Display the arduino object in a verbose way, showing the board and available pins. @subsubheading Inputs @var{ar} - the arduino object. If the arduino object has debug mode set, additional information will be displayed. @xseealso{arduino} @end deftypefn @c Arduino Functions @arduino/getEndian @c ----------------------------------------- @subsection @@arduino/getEndian @cindex getEndian @deftypefn {} {@var{mcu} =} getEndian (@var{ar}) Get the endian used by the connected arduino. @subsubheading Inputs @var{ar} - arduino object connected to a arduino board. @subsubheading Outputs @var{endian} - string representing the endian used by the arduino board. 'L' means little endian, 'B' means big endian @xseealso{arduino, getMCU} @end deftypefn @c Arduino Functions @arduino/getI2CTerminals @c ----------------------------------------- @subsection @@arduino/getI2CTerminals @cindex getI2CTerminals @deftypefn {} {@var{pinlist} =} getI2CTerminals (@var{ar}) @deftypefnx {} {@var{pinlist} =} getI2CTerminals (@var{ar}, @var{bus}) Get a cell list of pin Ids available are used for I2C mode. @subsubheading Inputs @var{ar} - the arduino object. @var{bus} - optional bus number 0 or 1 for boards that support more than 1 bus. @subsubheading Outputs @var{pinlist} - cell list of pin numbers available for I2C use. @xseealso{arduino} @end deftypefn @c Arduino Functions @arduino/getInterruptTerminals @c ----------------------------------------- @subsection @@arduino/getInterruptTerminals @cindex getInterruptTerminals @deftypefn {} {@var{pinlist} =} getInterruptTerminals (@var{ar}) Get a cell list of pin Ids available have interrupt functionality @subsubheading Inputs @var{ar} - the arduino object. @subsubheading Outputs @var{pinlist} - cell list of pin numbers available for interrupt use. @xseealso{arduino} @end deftypefn @c Arduino Functions @arduino/getLEDTerminals @c ----------------------------------------- @subsection @@arduino/getLEDTerminals @cindex getLEDTerminals @deftypefn {} {@var{pinlist} =} getLEDTerminals (@var{ar}) Get a cell list of pin Ids available are connected natively to LEDs. @subsubheading Inputs @var{ar} - the arduino object. @subsubheading Outputs @var{pinlist} - cell list of pin numbers available for LED use. @xseealso{arduino} @end deftypefn @c Arduino Functions @arduino/getMCU @c ----------------------------------------- @subsection @@arduino/getMCU @cindex getMCU @deftypefn {} {@var{mcu} =} getMCU (@var{ar}) Get the MCU used by the connected arduino. @subsubheading Inputs @var{ar} - arduino object connected to a arduino board. @subsubheading Outputs @var{mcu} - string representing the mcu used by the arduino board. @xseealso{arduino} @end deftypefn @c Arduino Functions @arduino/getPWMTerminals @c ----------------------------------------- @subsection @@arduino/getPWMTerminals @cindex getPWMTerminals @deftypefn {} {@var{pinlist} =} getPWMTerminals (@var{ar}) Get a cell list of pin Ids available for PWM use. @subsubheading Inputs @var{ar} - the arduino object. @subsubheading Outputs @var{pinlist} - cell list of pin numbers available for PWM use. @xseealso{arduino} @end deftypefn @c Arduino Functions @arduino/getPinAlias @c ----------------------------------------- @subsection @@arduino/getPinAlias @cindex getPinAlias @deftypefn {} {@var{ouy} =} getPinAlias (@var{ar}, @var{pin}) Get the pin actual pin name from a pin alias. For example, the arduino Leonardo, pin "D4" is also "A6". @subsubheading Inputs @var{ar} - the connected arduino object. @var{pin} - a pin name. @subsubheading Outputs @var{out} - alias pin name, or same as @var{pin} if the pin doesnt have any alias names. @xseealso{arduino, configurePinResource, getResourceOwner} @end deftypefn @c Arduino Functions @arduino/getPinInfo @c ----------------------------------------- @subsection @@arduino/getPinInfo @cindex getPinInfo @deftypefn {} {@var{pininfo} =} getPinInfo (@var{ar}, @var{pin}) @deftypefnx {} {@var{pininfoarray} =} getPinInfo (@var{ar}, @var{pinarray}) Get the pin information from the input pins values. getPinInfo (@var{ar}, @var{pin}) will get information for a single pin. getPinInfo (@var{ar}, @var{pinarray}) will get a cell array of pin information @subsubheading Inputs @var{ar} - the connected arduino object. @var{pin} - a pin number or pin name. @var{pinarray} - the array of pin numbers or names The pininfo struct contains the following fields: @table @asis @item terminal Terminal number of the pin @item name String name of the pin @item owner Current item owner of the pin @item mode Current configured mode for the pin @end table @subsubheading Outputs @var{pininfo} - struct on pin information. @var{pininfolist} - cell array of pin info @xseealso{arduino, configurePinResource, getResourceOwner} @end deftypefn @c Arduino Functions @arduino/getPinsFromTerminals @c ----------------------------------------- @subsection @@arduino/getPinsFromTerminals @cindex getPinsFromTerminals @deftypefn {} {@var{pinnames} =} getPinsFromTerminals (@var{ar}, @var{terminals}) Get the pin names from the input terminal values. @subsubheading Inputs @var{ar} - the connected arduino object. @var{terminals} - the numeric pin number, or array of pin numbers to get pin names. @subsubheading Outputs @var{pinnames} - the string names of each input pin. If terminals was a single value, the return will be a single string, otherwise it will return a cell array of each pin name. @xseealso{arduino, getTerminalsFromPins} @end deftypefn @c Arduino Functions @arduino/getResourceCount @c ----------------------------------------- @subsection @@arduino/getResourceCount @cindex getResourceCount @deftypefn {} {@var{count} =} getResourceCount (@var{ar}, @var{resource}) Get the count of uses of a given resource. @subsubheading Inputs @var{ar} - connected arduino object @var{resource} - name of resource to get count for. @subsubheading Outputs @var{count} = count of uses registered to resource. @xseealso{incrementResourceCount. decrementResourceCount} @end deftypefn @c Arduino Functions @arduino/getResourceOwner @c ----------------------------------------- @subsection @@arduino/getResourceOwner @cindex getResourceOwner @deftypefn {} {@var{owner} =} getResourceOwner (@var{ar}, @var{terminal}) Get the owner of pin allocated previously by configurePinResource. @subsubheading Inputs @var{ar} - connected arduino object @var{terminal} - terminal number to get owner of. @subsubheading Outputs @var{owner} = owner of the terminal pin, or "" if not owned. @xseealso{configurePinResource} @end deftypefn @c Arduino Functions @arduino/getSPITerminals @c ----------------------------------------- @subsection @@arduino/getSPITerminals @cindex getSPITerminals @deftypefn {} {@var{pinlist} =} getSPITerminals (@var{ar}) Get a cell list of pin Ids available for SPI mode. @subsubheading Inputs @var{ar} - the arduino object. @subsubheading Outputs @var{pinlist} - cell list of pin numbers available for SPI use. @xseealso{arduino} @end deftypefn @c Arduino Functions @arduino/getServoTerminals @c ----------------------------------------- @subsection @@arduino/getServoTerminals @cindex getServoTerminals @deftypefn {} {@var{pinlist} =} getServoTerminals (@var{ar}) Get a cell list of pin Ids available for servo use. @subsubheading Inputs @var{ar} - the arduino object. @subsubheading Outputs @var{pinlist} - cell list of pin numbers available for servo use. @xseealso{arduino, getPWMTerminals} @end deftypefn @c Arduino Functions @arduino/getSharedResourceProperty @c ----------------------------------------- @subsection @@arduino/getSharedResourceProperty @cindex getSharedResourceProperty @deftypefn {} {@var{count} =} getSharedResourceProperty (@var{ar}, @var{resource}, @var{property}) Get the value of a property from a given resource. @subsubheading Inputs @var{ar} - connected arduino object @var{resource} - name of resource to get property for. @var{property} - name of property from the resource. @subsubheading Outputs @var{propvalue} - value of the property @xseealso{getResourceCount, setSharedResourceProperty} @end deftypefn @c Arduino Functions @arduino/getTerminalMode @c ----------------------------------------- @subsection @@arduino/getTerminalMode @cindex getTerminalMode @deftypefn {} {@var{mode} =} getTerminalMode (@var{ar}, @var{terminal}) Get the mode of a pin allocated previously by configurePinResource. @subsubheading Inputs @var{ar} - connected arduino object @var{terminal} - terminal number to get owner of. @subsubheading Outputs @var{mode} - mode of the terminal pin, or "not_set" if not owned. @xseealso{configurePinResource, getResourceOwner} @end deftypefn @c Arduino Functions @arduino/getTerminalsFromPins @c ----------------------------------------- @subsection @@arduino/getTerminalsFromPins @cindex getTerminalsFromPins @deftypefn {} {@var{pinnums} =} getTerminalsFromPins (@var{ar}, @var{pins}) Get the terminal number for each pin. @subsubheading Inputs @var{ar} - connected arduino object @var{pins} - single pin name or cell or vector array of pin names. @subsubheading Outputs @var{pinnums} - pin number of each named pin. If the input was a single string, returns a number. if the input pins was a vector or cell array, return a cell array of pin numbers corresponding to each input pin name. @xseealso{arduino, getPinsFromTerminals} @end deftypefn @c Arduino Functions @arduino/incrementResourceCount @c ----------------------------------------- @subsection @@arduino/incrementResourceCount @cindex incrementResourceCount @deftypefn {} {@var{count} =} incrementResourceCount (@var{ar}, @var{resource}) Increment the count value of a named resource by 1 and return the new count @subsubheading Inputs @var{ar} - connected arduino object @var{resource} - name of resource to increment count. @subsubheading Outputs @var{count} = count of uses registered to resource. @xseealso{getResourceCount. decrementResourceCount} @end deftypefn @c Arduino Functions @arduino/isTerminalAnalog @c ----------------------------------------- @subsection @@arduino/isTerminalAnalog @cindex isTerminalAnalog @deftypefn {} {@var{ret} = } isTerminalAnalog (@var{obj}, @var{terminal}) Return true if pin is capable of analog input @subsubheading Inputs @var{ar} - the connected arduino object @var{terminal} is a terminal number to check @subsubheading Outputs @var{ret} return 1 if terminal is a analog pin, 0 otherwise @end deftypefn @c Arduino Functions @arduino/isTerminalDigital @c ----------------------------------------- @subsection @@arduino/isTerminalDigital @cindex isTerminalDigital @deftypefn {} {@var{ret} = } isTerminalDigital(@var{obj}, @var{terminal}) Return true if pin is capable of digital functions @subsubheading Inputs @var{ar} - the connected arduino object @var{terminal} is a terminal number to check @subsubheading Outputs @var{ret} return 1 if terminal is a digital pin, 0 otherwise @end deftypefn @c Arduino Functions @arduino/playTone @c ----------------------------------------- @subsection @@arduino/playTone @cindex playTone @deftypefn {} {} playTone (@var{ar}, @var{pin}, @var{freq}, @var{duration}) Play a tone of a given frequency on a specified pin. @subsubheading Inputs @var{ar} - connected arduino object @var{pin} - digital pin to play tone on @var{freq} - frequency in hertz to play between 0 and 32767Hz. @var{duration} duration in seconds to play tone between 0 and 30 seconds If duration is 0 or not specified, tone will continue to play until next tone is commanded. If frequency is 0, tone will stop playing @strong{NOTE:} use of playTone can interfere with PWM output. @end deftypefn @c Arduino Functions @arduino/readAnalogPin @c ----------------------------------------- @subsection @@arduino/readAnalogPin @cindex readAnalogPin @deftypefn {} {@var{value} =} readAnalogPin (@var{ar}, @var{pin}) Read analog voltage of @var{pin}. @subsubheading Inputs @var{ar} - connected arduino object. @var{pin} - string name of the pin to read. @subsubheading Outputs @var{value} - analog value of the pin @subsubheading Example @example @code{ ar = arduino (); readAnalogPin(ar, "A4"); ans = 87 } @end example @xseealso{arduino, readVoltage} @end deftypefn @c Arduino Functions @arduino/readDigitalPin @c ----------------------------------------- @subsection @@arduino/readDigitalPin @cindex readDigitalPin @deftypefn {} {@var{value} =} readDigitalPin (@var{obj}, @var{pin}) Read digital value from a digital I/O pin. @subsubheading Inputs @var{ar} - connected arduino object. @var{pin} - string name of the pin to read. @subsubheading Outputs @var{value} - the logical value (0, 1, true false) of the current pin state. @subsubheading Example @example @code{ a = arduino (); pinvalue = readDigitalPin (a, 'D5'); } @end example @xseealso{arduino, writeDigitalPin} @end deftypefn @c Arduino Functions @arduino/readVoltage @c ----------------------------------------- @subsection @@arduino/readVoltage @cindex readVoltage @deftypefn {} {@var{voltage} =} readVoltage (@var{ar}, @var{pin}) Read analog voltage of a pin. @subsubheading Inputs @var{ar} - connected arduino. @var{pin} - pin name or number to query for voltage @subsubheading Outputs @var{voltage} - scaled pin value as a voltage @subsubheading Example @example @code{ ar = arduino (); readVoltage(ar, "A4"); ans = 1.401 } @end example @xseealso{arduino, readAnalogPin} @end deftypefn @c Arduino Functions @arduino/reset @c ----------------------------------------- @subsection @@arduino/reset @cindex reset @deftypefn {} {} reset (@var{ar}) Send reset command to arduino hardware to force a hardware reset. @subsubheading Inputs @var{ar} - connected arduino object. @xseealso{arduino} @end deftypefn @c Arduino Functions @arduino/sendCommand @c ----------------------------------------- @subsection @@arduino/sendCommand @cindex sendCommand @deftypefn {} {@var{outdata, outsize} =} sendCommand (@var{ar}, @var{libname}, @var{commandid}) @deftypefnx {} {@var{outdata, outsize} =} sendCommand (@var{ar}, @var{libname}, @var{commandid}, @var{data}) @deftypefnx {} {@var{outdata, outsize} =} sendCommand (@var{ar}, @var{libname}, @var{commandid}, @var{data}, @var{timeout}) Send a command with option data to the connected arduino, waiting up to a specified number of seconds for a response. @subsubheading Inputs @var{ar} - connected arduino object. @var{libname} - library sending the command. The name should match a programmed library of the arduino, or an error will be displayed. @var{commandid} - integer value for the command being sent to the arduino. @var{data} - optional data sent with the command. @var{timeout} - optional timeout to wait for data @subsubheading Outputs @var{outdata} - data returned back from the arduino in response to command @var{outsize} - size of data received If the arduino fails to respond with a valid reply, sendCommand will error. @xseealso{arduino} @end deftypefn @c Arduino Functions @arduino/setSharedResourceProperty @c ----------------------------------------- @subsection @@arduino/setSharedResourceProperty @cindex setSharedResourceProperty @deftypefn {} {} setSharedResourceProperty (@var{ar}, @var{resource}, @var{propname}, @var{propvalue}) @deftypefnx {} {} setSharedResourceProperty (@var{ar}, @var{resource}, @var{propname}, @var{propvalue}, ___) Set property values for a given resource. @subsubheading Inputs @var{ar} - connected arduino object @var{resource} - name of resource to get property for. @var{propname} - name of property from the resource. @var{propvalue} - value of property from the resource. Multiple @var{propname}, @var{propvalue} pairs can be given. @subsubheading Outputs None @subsubheading Example @example @code{ ar = arduino(); setSharedResourceProperty(ar, "myresource", "myproperty", [1 2 3]) } @end example @xseealso{getSharedResourceProperty} @end deftypefn @c Arduino Functions @arduino/uptime @c ----------------------------------------- @subsection @@arduino/uptime @cindex uptime @deftypefn {} {@var{sec} =} uptime (@var{ar}) Get the number of seconds the arduino board has been running concurrently. @subsubheading Inputs @var{ar} - the arduino object of the connection to an arduino board. @subsubheading Outputs @var{sec} - the number seconds the board has been running. Note that the count will wrap around after approximately 50 days. @xseealso{arduino} @end deftypefn @c Arduino Functions @arduino/validatePin @c ----------------------------------------- @subsection @@arduino/validatePin @cindex validatePin @deftypefn {} {} validatePin (@var{ar}, @var{pin}, @var{type}) Validate that the mode is allowed for specified pin If the mode is not valid, and error will be thrown. @subsubheading Inputs @var{ar} - connected arduino object @var{pin} - name of pin to query mode validity of @var{mode} - mode to query Known modes are: @itemize @bullet @item 'I2C' @item 'SPI' @item 'PWM' @item 'Servo' @item 'analog' @item 'digital' @end itemize @xseealso{arduino, configurePin} @end deftypefn @c Arduino Functions @arduino/version @c ----------------------------------------- @subsection @@arduino/version @cindex version @deftypefn {} {@var{ver} =} version (@var{ar}) Get version of library code installed on arduino board @subsubheading Inputs @var{ar} - the arduino object of the connection to an arduino board. @subsubheading Outputs @var{ver} - version string in format of X.Y.Z. @xseealso{arduino} @end deftypefn @c Arduino Functions @arduino/writeDigitalPin @c ----------------------------------------- @subsection @@arduino/writeDigitalPin @cindex writeDigitalPin @deftypefn {} {} writeDigitalPin (@var{ar}, @var{pin}, @var{value}) Write digital value to a digital I/O pin. @subsubheading Inputs @var{ar} - connected arduino object. @var{pin} - string name of the pin to write to. @var{value} - the logical value (0, 1, true false) to write to the pin. If pin was unconfigured before using, pin is set into digital mode. @subsubheading Example @example @code{ a = arduino(); writeDigitalPin(a,'D5',1); } @end example @xseealso{arduino, readDigitalPin} @end deftypefn @c Arduino Functions @arduino/writePWMDutyCycle @c ----------------------------------------- @subsection @@arduino/writePWMDutyCycle @cindex writePWMDutyCycle @deftypefn {} {} writePWMDutyCyle (@var{ar}, @var{pin}, @var{value}) Set pin to output a square wave with a specified duty cycle. @subsubheading Inputs @var{ar} - connected arduino object @var{pin} - pin to write to. @var{value} - duty cycle value where 0 = off, 0.5 = 50% on, 1 = always on. @subsubheading Example @example @code{ a = arduino(); writePWMDutyCycle(a,'D5',0.5); } @end example @xseealso{arduino, writePWMVoltage} @end deftypefn @c Arduino Functions @arduino/writePWMVoltage @c ----------------------------------------- @subsection @@arduino/writePWMVoltage @cindex writePWMVoltage @deftypefn {} {} writePWMVoltage (@var{ar}, @var{pin}, @var{voltage}) Emulate an approximate voltage out of a pin using PWM. @subsubheading Inputs @var{ar} - connected arduino object @var{pin} - pin to write to. @var{voltage} - voltage to emulate with PWM, between 0 - 5.0 @subsubheading Example @example @code{ a = arduino(); writePWMVoltage(a,'D5',1.0); } @end example @xseealso{arduino, writePWMDutyCycle} @end deftypefn @c --------------------------------------------------- @node Arduino I2C Functions @section Arduino I2C Functions @cindex Arduino I2C Functions @c Arduino I2C Functions @device/delete @c ----------------------------------------- @subsection @@device/delete @cindex delete @deftypefn {} {} delete (@var{dev}) Free resources of a device object. @subsubheading Inputs @var{dev} - object to free @xseealso{device} @end deftypefn @c Arduino I2C Functions @device/disp @c ----------------------------------------- @subsection @@device/disp @cindex disp @deftypefn {} {} disp (@var{dev}) Display device object. @subsubheading Inputs @var{dev} - device object to display @xseealso{device} @end deftypefn @c Arduino I2C Functions @device/read @c ----------------------------------------- @subsection @@device/read @cindex read @deftypefn {} {@var{data} =} read (@var{dev}, @var{numbytes}) @deftypefnx {} {@var{data} =} read (@var{dev}, @var{numbytes}, @var{precision}) Read a specified number of bytes from a i2c or serial device object using optional precision for bytesize. @subsubheading Inputs @var{dev} - connected i2c or serial device opened using device @var{numbytes} - number of bytes to read. @var{precision} - Optional precision for the output data read data. Currently known precision values are uint8 (default), int8, uint16, int16 @subsubheading Outputs @var{data} - data read from the device @xseealso{arduino, device} @end deftypefn @c Arduino I2C Functions @device/readRegister @c ----------------------------------------- @subsection @@device/readRegister @cindex readRegister @deftypefn {} {@var{data} =} readRegister (@var{dev}, @var{reg}, @var{numbytes}) @deftypefnx {} {@var{data} =} readRegister (@var{dev}, @var{reg}, @var{numbytes}, @var{precision}) Read a specified number of bytes from a register of an i2cdev object using optional precision for bytesize. @subsubheading Inputs @var{dev} - connected i2c device opened using device @var{reg} - registry value number @var{numbytes} - number of bytes to read. @var{precision} - Optional precision for the output data read data. Currently known precision values are uint8 (default), int8, uint16, int16 @subsubheading Output @var{data} - data read from device. @xseealso{arduino, device} @end deftypefn @c Arduino I2C Functions @device/subsref @c ----------------------------------------- @subsection @@device/subsref @cindex subsref @deftypefn {} {@var{val} = } subsref (@var{dev}, @var{sub}) subref for device @xseealso{device} @end deftypefn @c Arduino I2C Functions @device/write @c ----------------------------------------- @subsection @@device/write @cindex write @deftypefn {} {} write (@var{dev}, @var{datain}) @deftypefnx {} {} write (@var{dev}, @var{datain}, @var{precision}) Write data to a I2C or serial device object using optional precision for the data byte used for the data. @subsubheading Inputs @var{dev} - connected i2c or serial device opened using device @var{datain} - data to write to device. Datasize should not exceed the constraints of the data type specified for the precision. @var{precision} - Optional precision for the input write data. Currently known precision values are uint8 (default), int8, uint16, int16 @xseealso{arduino, device, read} @end deftypefn @c Arduino I2C Functions @device/writeRegister @c ----------------------------------------- @subsection @@device/writeRegister @cindex writeRegister @deftypefn {} {} writeRegister (@var{dev}, @var{reg}, @var{datain}) @deftypefnx {} {} writeRegister (@var{dev}, @var{dev}, @var{datain}, @var{precision}) Write data to i2c device object at a given registry position using optional precision for the data byte used for the data. @subsubheading Inputs @var{dev} - connected i2c device opened using device @var{reg} - registry position to write to. @var{datain} - data to write to device. Datasize should not exceed the constraints of the data type specified for the precision. @var{precision} - Optional precision for the input write data. Currently known precision values are uint8 (default), int8, uint16, int16 @xseealso{arduino, device, read} @end deftypefn @c Arduino I2C Functions @i2cdev/delete @c ----------------------------------------- @subsection @@i2cdev/delete @cindex delete @deftypefn {} {} delete (@var{dev}) Free resources of a i2cdev object. @subsubheading Inputs @var{dev} - object to free @xseealso{i2cdev} @end deftypefn @c Arduino I2C Functions @i2cdev/disp @c ----------------------------------------- @subsection @@i2cdev/disp @cindex disp @deftypefn {} {} disp (@var{dev}) Display i2cdev object. @subsubheading Inputs @var{dev} - i2cdev object @xseealso{i2cdev} @end deftypefn @c Arduino I2C Functions @i2cdev/i2cdev @c ----------------------------------------- @subsection @@i2cdev/i2cdev @cindex i2cdev @deftypefn {} {@var{dev} =} i2cdev (@var{ar}, @var{address}) @deftypefnx {} {@var{dev} =} i2cdev (@var{ar}, @var{address}, @var{propname}, @var{propvalue}) @code{i2cdev} is depreciated and will be removed in a future version. Use @code{device} instead. Create an i2cdev object to communicate to the i2c port on a connected arduino. @subsubheading Inputs @var{ar} - connected arduino object @var{address} - address to use for device on I2C bus. @var{propname}, @var{propvalue} - property name/value pair for values to pass to devices. Currently known properties: @table @asis @item bus bus number (when arduino board supports multiple I2C buses) with value of 0 or 1. @end table @subsubheading Outputs @var{dev} - new created i2cdev object. @subsubheading Properties The i2cdev object has the following public properties: @table @asis @item parent The parent (arduino) for this device @item pins pins used by this object @item bus bus used for created object @item address I2C address set for object @end table @xseealso{arduino} @end deftypefn @c Arduino I2C Functions @i2cdev/read @c ----------------------------------------- @subsection @@i2cdev/read @cindex read @deftypefn {} {@var{data} =} read (@var{dev}, @var{numbytes}) @deftypefnx {} {@var{data} =} read (@var{dev}, @var{numbytes}, @var{precision}) Read a specified number of bytes from a i2cdev object using optional precision for bytesize. @subsubheading Inputs @var{dev} - connected i2c device opened using i2cdev @var{numbytes} - number of bytes to read. @var{precision} - Optional precision for the output data read data. Currently known precision values are uint8 (default), int8, uint16, int16 @subsubheading Outputs @var{data} - data read from i2cdevice @xseealso{arduino, i2cdev} @end deftypefn @c Arduino I2C Functions @i2cdev/readRegister @c ----------------------------------------- @subsection @@i2cdev/readRegister @cindex readRegister @deftypefn {} {@var{data} =} readRegister (@var{dev}, @var{reg}, @var{numbytes}) @deftypefnx {} {@var{data} =} readRegister (@var{dev}, @var{reg}, @var{numbytes}, @var{precision}) Read a specified number of bytes from a register of an i2cdev object using optional precision for bytesize. @subsubheading Inputs @var{dev} - connected i2c device opened using i2cdev @var{reg} - registry value number @var{numbytes} - number of bytes to read. @var{precision} - Optional precision for the output data read data. Currently known precision values are uint8 (default), int8, uint16, int16 @subsubheading Output @var{data} - data read from device. @xseealso{arduino, i2cdev} @end deftypefn @c Arduino I2C Functions @i2cdev/subsref @c ----------------------------------------- @subsection @@i2cdev/subsref @cindex subsref @deftypefn {} {@var{val} = } subsref (@var{dev}, @var{sub}) subref for i2cdev @xseealso{i2cdev} @end deftypefn @c Arduino I2C Functions @i2cdev/write @c ----------------------------------------- @subsection @@i2cdev/write @cindex write @deftypefn {} {} write (@var{dev}, @var{datain}) @deftypefnx {} {} write (@var{dev}, @var{datain}, @var{precision}) Write data to a i2cdev object using optional precision for the data byte used for the data. @subsubheading Inputs @var{dev} - connected i2c device opened using i2cdev @var{datain} - data to write to device. Datasize should not exceed the constraints of the data type specified for the precision. @var{precision} - Optional precision for the input write data. Currently known precision values are uint8 (default), int8, uint16, int16 @xseealso{arduino, i2cdev, read} @end deftypefn @c Arduino I2C Functions @i2cdev/writeRegister @c ----------------------------------------- @subsection @@i2cdev/writeRegister @cindex writeRegister @deftypefn {} {} writeRegister (@var{dev}, @var{reg}, @var{datain}) @deftypefnx {} {} writeRegister (@var{dev}, @var{dev}, @var{datain}, @var{precision}) Write data to i2cdev object at a given registry position using optional precision for the data byte used for the data. @subsubheading Inputs @var{dev} - connected i2c device opened using i2cdev @var{reg} - registry position to write to. @var{datain} - data to write to device. Datasize should not exceed the constraints of the data type specified for the precision. @var{precision} - Optional precision for the input write data. Currently known precision values are uint8 (default), int8, uint16, int16 @xseealso{arduino, i2cdev, read} @end deftypefn @c Arduino I2C Functions scanI2Cbus @c ----------------------------------------- @subsection scanI2Cbus @cindex scanI2Cbus @deftypefn {} {@var{retval} =} scanI2Cbus (@var{ar}) @deftypefnx {} {@var{retval} =} scanI2Cbus (@var{ar}, @var{bus}) Scan arduino for devices on the I2C bus. @subsubheading Inputs @var{ar} - arduino object connected to a arduino board. @var{bus} - bus number to scan I2C devices, when multiple buses are available. If the bus is not specified, it will default to 0. @subsubheading Outputs @var{retval} - cell array of addresses as strings in format of "0xXX". @subsubheading Example @example @code { # create arduino connection. ar = arduino(); # scan for devices on the I2C bus scanI2Cbus (ar) # output is each detected i2c address as a string ans = @{ [1,1] = 0x50 @} } @end example @xseealso{arduino, i2cdev, checkI2CAddress} @end deftypefn @c --------------------------------------------------- @node Arduino Rotary Encoder Functions @section Arduino Rotary Encoder Functions @cindex Arduino Rotary Encoder Functions @c Arduino Rotary Encoder Functions @rotaryEncoder/delete @c ----------------------------------------- @subsection @@rotaryEncoder/delete @cindex delete @deftypefn {} {} delete (@var{dev}) Free resources of a encoder object. @subsubheading Inputs @var{dev} - object to free @xseealso{rotartEncoder} @end deftypefn @c Arduino Rotary Encoder Functions @rotaryEncoder/disp @c ----------------------------------------- @subsection @@rotaryEncoder/disp @cindex disp @deftypefn {} {@var{retval} =} disp (@var{obj}) Display the rotary encoder object in a verbose way, @subsubheading Inputs @var{obj} - the arduino rotary encoder object created with rotaryEncoder @xseealso{rotaryEncoder} @end deftypefn @c Arduino Rotary Encoder Functions @rotaryEncoder/readCount @c ----------------------------------------- @subsection @@rotaryEncoder/readCount @cindex readCount @deftypefn {} {[@var{count}, @var{time}] =} readCount (@var{obj}) @deftypefnx {} {[@var{count}, @var{time}] =} readCount (@var{obj}, @var{name}, @var{value}) read count value from the rotary encoder. subsubheading Inputs @var{obj} - rotary encoder object created with rotaryEncoder call. @var{name}, @var{value} - optional name,value pairs Valid option name pairs currently are: @table @asis @item reset Reset the count after reading (if true) @end table @subsubheading Outputs @var{count} - returned count read from the encoder. @var{time} - seconds since arduino started @xseealso{rotaryEncoder, resetCount} @end deftypefn @c Arduino Rotary Encoder Functions @rotaryEncoder/readSpeed @c ----------------------------------------- @subsection @@rotaryEncoder/readSpeed @cindex readSpeed @deftypefn {} {@var{speed} =} readSpeed (@var{obj}) read rotational speed from the rotary encoder. @subsubheading Inputs @var{obj} - rotary encoder object created with rotaryEncoder call. @subsubheading Outputs @var{speed} - returned speed in revolutions per minute read from the encoder. @xseealso{rotaryEncoder, resetCount} @end deftypefn @c Arduino Rotary Encoder Functions @rotaryEncoder/resetCount @c ----------------------------------------- @subsection @@rotaryEncoder/resetCount @cindex resetCount @deftypefn {} reset (@var{obj}) @deftypefnx {} reset (@var{obj}, @var{cnt}) reset the rotary encoder count values @subsubheading Inputs @var{obj} - the rotaryEncoder object @var{cnt} - optional count value to reset to @xseealso{rotaryEncoder, readCount} @end deftypefn @c Arduino Rotary Encoder Functions @rotaryEncoder/rotaryEncoder @c ----------------------------------------- @subsection @@rotaryEncoder/rotaryEncoder @cindex rotaryEncoder @deftypefn {} {@var{obj} =} rotaryEncoder (@var{ar}, @var{chanApin}, @var{chanBpin}) @deftypefnx {} {@var{obj} =} rotaryEncoder (@var{ar}, @var{chanApin}, @var{chanBpin}, @var{ppr}) Create a rotaryEncoder object controlled by the input pins. @subsubheading Inputs @var{ar} - connected arduino object. @var{chanApin} - pin used for channel A @var{chanBpin} - pin used for channel B @var{ppr} - count of encoder pulsed required for a full revolution of the encoder. @subsubheading Outputs @var{obj} - created rotary encoder object @subsubheading Example @example a = arduino (); enc = rotaryEncoder(a, "d2", "d3", 180); @end example @subsubheading Properties The rotaryEncoder object has the following public properties: @table @asis @item parent The parent (arduino) for this device @item pins pins used by this object @item ppr Number of pulses used per rotation @end table @xseealso{arduino} @end deftypefn @c Arduino Rotary Encoder Functions @rotaryEncoder/subsref @c ----------------------------------------- @subsection @@rotaryEncoder/subsref @cindex subsref @deftypefn {} {@var{val} = } subsref (@var{dev}, @var{sub}) subref for rotaryEncoder @xseealso{rotaryEncoder} @end deftypefn @c --------------------------------------------------- @node Arduino Servo Functions @section Arduino Servo Functions @cindex Arduino Servo Functions @c Arduino Servo Functions @servo/delete @c ----------------------------------------- @subsection @@servo/delete @cindex delete @deftypefn {} {} delete (@var{dev}) Free resources of a servo object. @subsubheading Inputs @var{dev} - object to free @xseealso{servo} @end deftypefn @c Arduino Servo Functions @servo/disp @c ----------------------------------------- @subsection @@servo/disp @cindex disp @deftypefn {} {} disp (@var{dev}) Display servo object. @subsubheading Inputs @var{dev} - servo device to display @xseealso{servo} @end deftypefn @c Arduino Servo Functions @servo/readPosition @c ----------------------------------------- @subsection @@servo/readPosition @cindex readPosition @deftypefn {} {@var{position} = } readPosition (@var{servo}) Read the position of a servo @subsubheading Inputs @var{servo} - servo object created from arduino.servo. @subsubheading Outputs @var{position} - value between 0 .. 1 for the current servo position, where 0 is the servo min position, 1 is the servo maximum position. @xseealso{servo, writePosition} @end deftypefn @c Arduino Servo Functions @servo/servo @c ----------------------------------------- @subsection @@servo/servo @cindex servo @deftypefn {} {@var{obj} = } servo (@var{arduinoobj}, @var{pin}) @deftypefnx {} {@var{obj} = } servo (@var{arduinoobj}, @var{pin}, @var{propertyname}, @var{propertyvalue}) Create a servo object using a specified pin on a arduino board. @subsubheading Inputs @var{obj} - servo object @var{arduinoobj} - connected arduino object @var{propertyname}, @var{propertyvalue} - name value pairs for properties to pass to the created servo object. Current properties are: @table @asis @item minpulseduration min PWM pulse value in seconds. @item maxpulseduration max PWM pulse value in seconds. @end table @subsubheading Outputs @var{obj} - created servo object. @subsubheading Example @example # create arduino connection ar = arduino(); # create hobby servo (1 - 2 ms pulse range) servo = servo(ar, "d9", "minpulseduration", 1.0e-3, "maxpulseduration", 2e-3); # center the servo writePosition(servo, 0.5); @end example @subsubheading Properties The servo object has the following public properties: @table @asis @item parent The parent (arduino) for this device @item pins pins used by this object @item minpulseduration minpulseduration set for object @item maxpulseduration maxpulseduration set for object @end table @xseealso{arduino, readPosition, writePosition} @end deftypefn @c Arduino Servo Functions @servo/subsref @c ----------------------------------------- @subsection @@servo/subsref @cindex subsref @deftypefn {} {@var{val} = } subsref (@var{dev}, @var{sub}) subref for servo @xseealso{servo} @end deftypefn @c Arduino Servo Functions @servo/writePosition @c ----------------------------------------- @subsection @@servo/writePosition @cindex writePosition @deftypefn {} {} writePosition (@var{servo}, @var{position}) Write the position to a servo. @subsubheading Inputs @var{servo} - servo object created from arduino.servo. @var{position} - value between 0 .. 1 for the current servo position, where 0 is the servo min position, 1 is the servo maximum position. @xseealso{servo, readPosition} @end deftypefn @c --------------------------------------------------- @node Arduino Shiftregister Functions @section Arduino Shiftregister Functions @cindex Arduino Shiftregister Functions @c Arduino Shiftregister Functions @shiftRegister/delete @c ----------------------------------------- @subsection @@shiftRegister/delete @cindex delete @deftypefn {} {} delete (@var{dev}) Free resources of a shiftRegister object. @subsubheading Inputs @var{dev} - object to free @xseealso{shiftRegister} @end deftypefn @c Arduino Shiftregister Functions @shiftRegister/disp @c ----------------------------------------- @subsection @@shiftRegister/disp @cindex disp @deftypefn {} {} disp (@var{register}) Display the register object in a verbose way, @subsubheading Inputs @var{register} - the arduino register object created with shiftRegister. @xseealso{shiftRegister} @end deftypefn @c Arduino Shiftregister Functions @shiftRegister/read @c ----------------------------------------- @subsection @@shiftRegister/read @cindex read @deftypefn {} {@var{retval} =} read (@var{register}) @deftypefnx {} {@var{retval} =} read (@var{register}, @var{precision}) read a value from the shift register. @subsubheading Inputs @var{register} - shift register created from shiftRegister call. @var{precision} - optional precision of the data, where precision can be a number in a multiple of 8 (ie: 8,16,32) or can be a named integer type: 8 of 'uint8', 'uint16', 'uint32'. The default precision is 8. @subsubheading Outputs @var{retval} - returned data read from the register. @xseealso{shiftRegister, write} @end deftypefn @c Arduino Shiftregister Functions @shiftRegister/reset @c ----------------------------------------- @subsection @@shiftRegister/reset @cindex reset @deftypefn {} reset (@var{register}) clear the shift register value. @subsubheading Inputs @var{register} - shift register created from shiftRegister call. @xseealso{shiftRegister, read, write} @end deftypefn @c Arduino Shiftregister Functions @shiftRegister/shiftRegister @c ----------------------------------------- @subsection @@shiftRegister/shiftRegister @cindex shiftRegister @deftypefn {} {@var{register} =} shiftRegister (@var{ar}, @var{shifttype}, @var{dataPin}, @var{clockPin} ...) @deftypefnx {} {@var{register} =} shiftRegister (@var{ar},'74hc164', @var{dataPin}, @var{clockPin}, @var{resetPin}) @deftypefnx {} {@var{register} =} shiftRegister (@var{ar},'74hc165', @var{dataPin}, @var{clockPin}, @var{loadPin}, @var{clockEnablePin}) @deftypefnx {} {@var{register} =} shiftRegister(@var{ar},'74hc595', @var{dataPin}, @var{clockPin}, @var{latchPin} , @var{resetPin}) Create shift register of a given type, controlled by the input pins. @subsubheading Inputs Common function parameter definition: @var{ar} - connected arduino object. @var{shifttype} - string name of the shift register type. @var{dataPin} - pin used for data in/out of the device. @var{clockPin} - pin used for clocking data on the shiftRegister. Other variables are dependent on the shift register type: @table @asis @item '74hc164' Additional inputs: @var{resetPin} - optional pin for resetting the shift register. @item '74hc165' Additional inputs: @var{loadPin} - load pin to the shift register. @var{clockEnablePin} - clock enable pin. @item '74hc595' Additional inputs: @var{latchPin} - latching data to the shift register. @var{resetPin} - optional pin for resetting the shift register. @end table @subsubheading Outputs @var{register} - register object @subsubheading Properties The shiftRegister object has the following public properties: @table @asis @item parent The parent (arduino) for this device @item pins pins used by this object @item model model set for object @end table @xseealso{arduino} @end deftypefn @c Arduino Shiftregister Functions @shiftRegister/subsref @c ----------------------------------------- @subsection @@shiftRegister/subsref @cindex subsref @deftypefn {} {@var{val} = } subsref (@var{dev}, @var{sub}) subref for shiftRegister @xseealso{shiftRegister} @end deftypefn @c Arduino Shiftregister Functions @shiftRegister/write @c ----------------------------------------- @subsection @@shiftRegister/write @cindex write @deftypefn {} write (@var{register}, @var{dataIn}) @deftypefnx {} write (@var{register}, @var{dataIn}, @var{precision}) Write a value to the shift register. @subsubheading Inputs @var{register} - shift register created from shiftRegister call. @var{dataIn} - data to clock into the shiftRegister. @var{precision} - optional precision of the data, where precision can be a number in a multiple of 8 (ie: 8,16,32) or can be a named integer type of 'uint8', 'uint16', 'uint32'. The default precision is 8. @xseealso{shiftRegister, read} @end deftypefn @c --------------------------------------------------- @node Arduino SPI Functions @section Arduino SPI Functions @cindex Arduino SPI Functions @c Arduino SPI Functions @device/delete @c ----------------------------------------- @subsection @@device/delete @cindex delete @deftypefn {} {} delete (@var{dev}) Free resources of a device object. @subsubheading Inputs @var{dev} - object to free @xseealso{device} @end deftypefn @c Arduino SPI Functions @device/disp @c ----------------------------------------- @subsection @@device/disp @cindex disp @deftypefn {} {} disp (@var{dev}) Display device object. @subsubheading Inputs @var{dev} - device object to display @xseealso{device} @end deftypefn @c Arduino SPI Functions @device/subsref @c ----------------------------------------- @subsection @@device/subsref @cindex subsref @deftypefn {} {@var{val} = } subsref (@var{dev}, @var{sub}) subref for device @xseealso{device} @end deftypefn @c Arduino SPI Functions @device/writeRead @c ----------------------------------------- @subsection @@device/writeRead @cindex writeRead @deftypefn {} {@var{dataOut} =} readWrite (@var{spi}, @var{dataIn}) Write uint8 data to spi device and return back clocked out response data of same size. @subsubheading Inputs @var{spi} - connected spi device on arduino @var{dataIn} - uint8 sized data to send to spi device framed between SS frame. @subsubheading Outputs @var{dataOut} - uint8 data clocked out during send to dataIn. @xseealso{arduino, device} @end deftypefn @c Arduino SPI Functions @spidev/delete @c ----------------------------------------- @subsection @@spidev/delete @cindex delete @deftypefn {} {} delete (@var{dev}) Free resources of a spidev object. @subsubheading Inputs @var{dev} - spidev object to free @xseealso{spidev} @end deftypefn @c Arduino SPI Functions @spidev/disp @c ----------------------------------------- @subsection @@spidev/disp @cindex disp @deftypefn {} {} disp (@var{dev}) Display spidev object. @subsubheading Inputs @var{dev} - spidev object to display @xseealso{spidev} @end deftypefn @c Arduino SPI Functions @spidev/spidev @c ----------------------------------------- @subsection @@spidev/spidev @cindex spidev @deftypefn {} {@var{dev} =} spidev (@var{ar}, @var{cspin}) @deftypefnx {} {@var{dev} =} spidev (@var{ar}, @var{cspin}, @var{propname}, @var{propvalue}) @code{spidev} is depreciated and will be removed in a future version. Use @code{device} instead. Create an spidev object to communicate to the SPI port on a connected arduino. @subsubheading Inputs @var{ar} - connected arduino object @var{cspin} - chip select pin for attached spi device. @var{propname}, @var{propvalue} - property name/value pair for values to pass to devices. Currently known properties: @table @asis @item bitrate bit rate speed in Mbs @item bitorder 'msbfirst' or 'lsbfirst' @item mode SPI mode 0 - 3. @end table @subsubheading Outputs @var{dev} - created spidev object @subsubheading Properties The spidev object has the following public properties: @table @asis @item parent The parent (arduino) for this device @item pins pins used by this object @item mode mode used for created object @item bitrate Bitrate set for object @item bitorder Bitorder set for object @item chipselectpin Pin used for chipselect @end table @xseealso{arduino, readWrite} @end deftypefn @c Arduino SPI Functions @spidev/subsref @c ----------------------------------------- @subsection @@spidev/subsref @cindex subsref @deftypefn {} {@var{val} = } subsref (@var{dev}, @var{sub}) subref for spidev @xseealso{spidev} @end deftypefn @c Arduino SPI Functions @spidev/writeRead @c ----------------------------------------- @subsection @@spidev/writeRead @cindex writeRead @deftypefn {} {@var{dataOut} =} readWrite (@var{spi}, @var{dataIn}) Write uint8 data to spi device and return back clocked out response data of same size. @subsubheading Inputs @var{spi} - connected spi device on arduino @var{dataIn} - uint8 sized data to send to spi device framed between SS frame. @subsubheading Outputs @var{dataOut} - uint8 data clocked out during send to dataIn. @xseealso{arduino, spidev} @end deftypefn @c --------------------------------------------------- @node Arduino Serial Functions @section Arduino Serial Functions @cindex Arduino Serial Functions @c Arduino Serial Functions @device/delete @c ----------------------------------------- @subsection @@device/delete @cindex delete @deftypefn {} {} delete (@var{dev}) Free resources of a device object. @subsubheading Inputs @var{dev} - object to free @xseealso{device} @end deftypefn @c Arduino Serial Functions @device/device @c ----------------------------------------- @subsection @@device/device @cindex device @deftypefn {} {@var{dev} =} device (@var{ar}, 'I2CAddress', @var{address}) @deftypefnx {} {@var{dev} =} device (@var{ar}, 'SPIChipSelectPin', @var{pin}) @deftypefnx {} {@var{dev} =} device (@var{ar}, 'Serial', @var{serialid}) @deftypefnx {} {@var{dev} =} device (..., @var{propname}, @var{propvalue}) Create an i2c, spi or serial object to communicate on a connected arduino. @subsubheading Inputs @var{ar} - connected arduino object @var{propname}, @var{propvalue} - property name/value pair for values to pass to devices. A property of 'i2caddress', 'spichipselectpin' or 'serial' must be specified to denote the device type to create. @var{i2caddress} - address to use for device on I2C bus. @var{pin} - pin to use for device SPI chip select. @var{serialid} - Serial port id to use Additional properties can also be specified for the device object Currently known input I2C properties values: @table @asis @item bus bus number (when arduino board supports multiple I2C buses) with value of 0 or 1. @item noprobe Do not probe the existence of device on creation if set to 1 (default 0) @item bitrate bit rate speed in Mbs - default 100000 @end table Currently known input SPI properties values: @table @asis @item bitrate bit rate speed in Mbs @item bitorder 'msbfirst' or 'lsbfirst' @item spimode SPI mode 0 - 3. @end table Currently known input Serial properties values: @table @asis @item baudrate baudrate value (default 9600) @item databits number of databits (5,6,7,8) (default 8) @item stopbits number of stopbits (1,2) (default 1) @item parity parity of device ('odd','even','none') (default 'none') @end table @subsubheading Outputs @var{dev} - new created device object. @subsubheading Properties The object has the following public properties: @table @asis @item parent The parent (arduino) for this device @item interface The interface type for this device ("SPI" or "I2C" or "Serial") @end table In addition, depending on type, the object will have these properties: @subsubheading I2C Properties The object has the following public properties: @table @asis @item bus bus used for created object @item i2caddress I2C address set for object @item sclpin the SCL pin of the device @item sdapin the SDA pin of the device @item bitrate bit rate for the i2c clock @end table @subsubheading SPI Properties The object has the following public properties: @table @asis @item spimode mode used for created object @item bitrate Bitrate set for object @item bitorder Bitorder set for object @item spichipselectpin Pin used for chipselect @item mosipin Pin used for mosi @item misopin Pin used for miso @item sckpin Pin used for sckpin @end table @subsubheading Serial Properties The object has the following public properties: @table @asis @item id serial port id @item baudrate baudrate @item databits number of databits (5,6,7,8) @item stopbits number of stopbits (1,2) @item parity parity of device ('odd','even','none') @end table @xseealso{arduino, i2cdev, spidev} @end deftypefn @c Arduino Serial Functions @device/disp @c ----------------------------------------- @subsection @@device/disp @cindex disp @deftypefn {} {} disp (@var{dev}) Display device object. @subsubheading Inputs @var{dev} - device object to display @xseealso{device} @end deftypefn @c Arduino Serial Functions @device/flush @c ----------------------------------------- @subsection @@device/flush @cindex flush @deftypefn {} {@var{data} =} flush (@var{dev}) @deftypefnx {} {@var{data} =} flush (@var{dev}, "input") @deftypefnx {} {@var{data} =} flush (@var{dev}, "output") Flush the serial port buffers @subsubheading Inputs @var{dev} - connected serial device opened using device If an additional parameter is provided of "input" or "output", then only the input or output buffer will be flushed @subsubheading Outputs None @xseealso{arduino, device, read} @end deftypefn @c Arduino Serial Functions @device/read @c ----------------------------------------- @subsection @@device/read @cindex read @deftypefn {} {@var{data} =} read (@var{dev}, @var{numbytes}) @deftypefnx {} {@var{data} =} read (@var{dev}, @var{numbytes}, @var{precision}) Read a specified number of bytes from a i2c or serial device object using optional precision for bytesize. @subsubheading Inputs @var{dev} - connected i2c or serial device opened using device @var{numbytes} - number of bytes to read. @var{precision} - Optional precision for the output data read data. Currently known precision values are uint8 (default), int8, uint16, int16 @subsubheading Outputs @var{data} - data read from the device @xseealso{arduino, device} @end deftypefn @c Arduino Serial Functions @device/subsref @c ----------------------------------------- @subsection @@device/subsref @cindex subsref @deftypefn {} {@var{val} = } subsref (@var{dev}, @var{sub}) subref for device @xseealso{device} @end deftypefn @c Arduino Serial Functions @device/write @c ----------------------------------------- @subsection @@device/write @cindex write @deftypefn {} {} write (@var{dev}, @var{datain}) @deftypefnx {} {} write (@var{dev}, @var{datain}, @var{precision}) Write data to a I2C or serial device object using optional precision for the data byte used for the data. @subsubheading Inputs @var{dev} - connected i2c or serial device opened using device @var{datain} - data to write to device. Datasize should not exceed the constraints of the data type specified for the precision. @var{precision} - Optional precision for the input write data. Currently known precision values are uint8 (default), int8, uint16, int16 @xseealso{arduino, device, read} @end deftypefn @c --------------------------------------------------- @node Arduino Device Functions @section Arduino Device Functions @cindex Arduino Device Functions @c Arduino Device Functions @device/delete @c ----------------------------------------- @subsection @@device/delete @cindex delete @deftypefn {} {} delete (@var{dev}) Free resources of a device object. @subsubheading Inputs @var{dev} - object to free @xseealso{device} @end deftypefn @c Arduino Device Functions @device/device @c ----------------------------------------- @subsection @@device/device @cindex device @deftypefn {} {@var{dev} =} device (@var{ar}, 'I2CAddress', @var{address}) @deftypefnx {} {@var{dev} =} device (@var{ar}, 'SPIChipSelectPin', @var{pin}) @deftypefnx {} {@var{dev} =} device (@var{ar}, 'Serial', @var{serialid}) @deftypefnx {} {@var{dev} =} device (..., @var{propname}, @var{propvalue}) Create an i2c, spi or serial object to communicate on a connected arduino. @subsubheading Inputs @var{ar} - connected arduino object @var{propname}, @var{propvalue} - property name/value pair for values to pass to devices. A property of 'i2caddress', 'spichipselectpin' or 'serial' must be specified to denote the device type to create. @var{i2caddress} - address to use for device on I2C bus. @var{pin} - pin to use for device SPI chip select. @var{serialid} - Serial port id to use Additional properties can also be specified for the device object Currently known input I2C properties values: @table @asis @item bus bus number (when arduino board supports multiple I2C buses) with value of 0 or 1. @item noprobe Do not probe the existence of device on creation if set to 1 (default 0) @item bitrate bit rate speed in Mbs - default 100000 @end table Currently known input SPI properties values: @table @asis @item bitrate bit rate speed in Mbs @item bitorder 'msbfirst' or 'lsbfirst' @item spimode SPI mode 0 - 3. @end table Currently known input Serial properties values: @table @asis @item baudrate baudrate value (default 9600) @item databits number of databits (5,6,7,8) (default 8) @item stopbits number of stopbits (1,2) (default 1) @item parity parity of device ('odd','even','none') (default 'none') @end table @subsubheading Outputs @var{dev} - new created device object. @subsubheading Properties The object has the following public properties: @table @asis @item parent The parent (arduino) for this device @item interface The interface type for this device ("SPI" or "I2C" or "Serial") @end table In addition, depending on type, the object will have these properties: @subsubheading I2C Properties The object has the following public properties: @table @asis @item bus bus used for created object @item i2caddress I2C address set for object @item sclpin the SCL pin of the device @item sdapin the SDA pin of the device @item bitrate bit rate for the i2c clock @end table @subsubheading SPI Properties The object has the following public properties: @table @asis @item spimode mode used for created object @item bitrate Bitrate set for object @item bitorder Bitorder set for object @item spichipselectpin Pin used for chipselect @item mosipin Pin used for mosi @item misopin Pin used for miso @item sckpin Pin used for sckpin @end table @subsubheading Serial Properties The object has the following public properties: @table @asis @item id serial port id @item baudrate baudrate @item databits number of databits (5,6,7,8) @item stopbits number of stopbits (1,2) @item parity parity of device ('odd','even','none') @end table @xseealso{arduino, i2cdev, spidev} @end deftypefn @c Arduino Device Functions @device/disp @c ----------------------------------------- @subsection @@device/disp @cindex disp @deftypefn {} {} disp (@var{dev}) Display device object. @subsubheading Inputs @var{dev} - device object to display @xseealso{device} @end deftypefn @c Arduino Device Functions @device/flush @c ----------------------------------------- @subsection @@device/flush @cindex flush @deftypefn {} {@var{data} =} flush (@var{dev}) @deftypefnx {} {@var{data} =} flush (@var{dev}, "input") @deftypefnx {} {@var{data} =} flush (@var{dev}, "output") Flush the serial port buffers @subsubheading Inputs @var{dev} - connected serial device opened using device If an additional parameter is provided of "input" or "output", then only the input or output buffer will be flushed @subsubheading Outputs None @xseealso{arduino, device, read} @end deftypefn @c Arduino Device Functions @device/read @c ----------------------------------------- @subsection @@device/read @cindex read @deftypefn {} {@var{data} =} read (@var{dev}, @var{numbytes}) @deftypefnx {} {@var{data} =} read (@var{dev}, @var{numbytes}, @var{precision}) Read a specified number of bytes from a i2c or serial device object using optional precision for bytesize. @subsubheading Inputs @var{dev} - connected i2c or serial device opened using device @var{numbytes} - number of bytes to read. @var{precision} - Optional precision for the output data read data. Currently known precision values are uint8 (default), int8, uint16, int16 @subsubheading Outputs @var{data} - data read from the device @xseealso{arduino, device} @end deftypefn @c Arduino Device Functions @device/readRegister @c ----------------------------------------- @subsection @@device/readRegister @cindex readRegister @deftypefn {} {@var{data} =} readRegister (@var{dev}, @var{reg}, @var{numbytes}) @deftypefnx {} {@var{data} =} readRegister (@var{dev}, @var{reg}, @var{numbytes}, @var{precision}) Read a specified number of bytes from a register of an i2cdev object using optional precision for bytesize. @subsubheading Inputs @var{dev} - connected i2c device opened using device @var{reg} - registry value number @var{numbytes} - number of bytes to read. @var{precision} - Optional precision for the output data read data. Currently known precision values are uint8 (default), int8, uint16, int16 @subsubheading Output @var{data} - data read from device. @xseealso{arduino, device} @end deftypefn @c Arduino Device Functions @device/subsref @c ----------------------------------------- @subsection @@device/subsref @cindex subsref @deftypefn {} {@var{val} = } subsref (@var{dev}, @var{sub}) subref for device @xseealso{device} @end deftypefn @c Arduino Device Functions @device/write @c ----------------------------------------- @subsection @@device/write @cindex write @deftypefn {} {} write (@var{dev}, @var{datain}) @deftypefnx {} {} write (@var{dev}, @var{datain}, @var{precision}) Write data to a I2C or serial device object using optional precision for the data byte used for the data. @subsubheading Inputs @var{dev} - connected i2c or serial device opened using device @var{datain} - data to write to device. Datasize should not exceed the constraints of the data type specified for the precision. @var{precision} - Optional precision for the input write data. Currently known precision values are uint8 (default), int8, uint16, int16 @xseealso{arduino, device, read} @end deftypefn @c Arduino Device Functions @device/writeRead @c ----------------------------------------- @subsection @@device/writeRead @cindex writeRead @deftypefn {} {@var{dataOut} =} readWrite (@var{spi}, @var{dataIn}) Write uint8 data to spi device and return back clocked out response data of same size. @subsubheading Inputs @var{spi} - connected spi device on arduino @var{dataIn} - uint8 sized data to send to spi device framed between SS frame. @subsubheading Outputs @var{dataOut} - uint8 data clocked out during send to dataIn. @xseealso{arduino, device} @end deftypefn @c Arduino Device Functions @device/writeRegister @c ----------------------------------------- @subsection @@device/writeRegister @cindex writeRegister @deftypefn {} {} writeRegister (@var{dev}, @var{reg}, @var{datain}) @deftypefnx {} {} writeRegister (@var{dev}, @var{dev}, @var{datain}, @var{precision}) Write data to i2c device object at a given registry position using optional precision for the data byte used for the data. @subsubheading Inputs @var{dev} - connected i2c device opened using device @var{reg} - registry position to write to. @var{datain} - data to write to device. Datasize should not exceed the constraints of the data type specified for the precision. @var{precision} - Optional precision for the input write data. Currently known precision values are uint8 (default), int8, uint16, int16 @xseealso{arduino, device, read} @end deftypefn @c --------------------------------------------------- @node Arduino Ultrasonic Functions @section Arduino Ultrasonic Functions @cindex Arduino Ultrasonic Functions @c Arduino Ultrasonic Functions @ultrasonic/delete @c ----------------------------------------- @subsection @@ultrasonic/delete @cindex delete @deftypefn {} {} delete (@var{dev}) Free resources of a ultrasonic object. @subsubheading Inputs @var{dev} - ultrasonic object to free @xseealso{ultrasonic} @end deftypefn @c Arduino Ultrasonic Functions @ultrasonic/disp @c ----------------------------------------- @subsection @@ultrasonic/disp @cindex disp @deftypefn {} {} disp (@var{dev}) Display ultrasonic object. @subsubheading Inputs @var{dev} - ultrasonic object to display @xseealso{ultrasonic} @end deftypefn @c Arduino Ultrasonic Functions @ultrasonic/readDistance @c ----------------------------------------- @subsection @@ultrasonic/readDistance @cindex readDistance @deftypefn {} {@var{distance} =} readDistance (@var{dev}) Read the distance from a ultrasonic device @subsubheading Inputs @var{dev} - connected ultrasonic device opened using ultrasonic @subsubheading Outputs @var{distance} - distance value in meters from the ultrasonic device, or Inf if out of sensor range @xseealso{arduino, ultrasonic} @end deftypefn @c Arduino Ultrasonic Functions @ultrasonic/readEchoTime @c ----------------------------------------- @subsection @@ultrasonic/readEchoTime @cindex readEchoTime @deftypefn {} {@var{time} =} readEchoTime (@var{dev}) Measure the time for waves to reflect back to the ultrasonic device @subsubheading Inputs @var{dev} - connected ultrasonic device opened using ultrasonic() @subsubheading Outputs @var{time} - time in seconds, or Inf if out of sensor range @xseealso{arduino, ultrasonic} @end deftypefn @c Arduino Ultrasonic Functions @ultrasonic/subsref @c ----------------------------------------- @subsection @@ultrasonic/subsref @cindex subsref @deftypefn {} {@var{val} = } subsref (@var{dev}, @var{sub}) subref for ultrasonic @xseealso{ultrasonic} @end deftypefn @c Arduino Ultrasonic Functions @ultrasonic/ultrasonic @c ----------------------------------------- @subsection @@ultrasonic/ultrasonic @cindex ultrasonic @deftypefn {} {@var{dev} =} ultrasonic (@var{ar}, @var{triggerpin}) @deftypefnx {} {@var{dev} =} ultrasonic (@var{ar}, @var{triggerpin}, @var{echopin}) @deftypefnx {} {@var{dev} =} ultrasonic (@var{ar}, @var{triggerpin}, @var{echopin}, @var{propname}, @var{propvalue}) Create an ultrasonic object to communicate to a connected ultrasonic device @subsubheading Inputs @var{ar} - connected arduino object @var{triggerpin} - trigger pin for attached device. @var{echopin} - trigger pin for attached device. @var{propname}, @var{propvalue} - property name/value pair for values to pass to devices. Currently known properties: @table @asis @item outputformat string designating number format for output ('double') @end table @subsubheading Outputs @var{dev} - created ultrasonic object @subsubheading Properties The ultrasonic object has the following public properties: @table @asis @item parent The parent (arduino) for this device @item pins pins used by this object @item triggerpin trigger used for created object @item echopin Echo pin set for object @item outputformat Output format for the created object @end table @xseealso{arduino, readDistance, readEchoTime} @end deftypefn @c --------------------------------------------------- @node Arduino Addons @section Arduino Addons @cindex Arduino Addons @c Arduino Addons addon @c ----------------------------------------- @subsection addon @cindex addon @deftypefn {} {@var{retval} =} addon (@var{ar}, @var{addonname}) @deftypefnx {} {@var{retval} =} addon (@var{ar}, @var{addonname}, varargs) Create an addon object using the addon named class. @subsubheading Inputs @var{ar} - connected arduino object @var{addonname} - the name of the addon to create. The addon name can be a user addon or an inbuilt addon, however must appear in the listArduinoLibraries output and have been programmed onto the arduino. @var{varargs} - optional values that will be provided verbatim to the the addon class constructor. @subsubheading Outputs @var{retval} - cell array of string library names. @xseealso{arduino, arduinosetup, listArduinoLibraries} @end deftypefn @c Arduino Addons arduinoioaddons.EEPRomAddon.EEPRom @c ----------------------------------------- @subsection arduinoioaddons.EEPRomAddon.EEPRom @cindex EEPRom @deftypefn {} {} arduinoioaddons.EEPRomAddon.EEPRom EEPROM addon for arduino Allows read and write of uint8 data to the onboard arduino EEPROM. @subsubheading Example Assuming eeprom addon has been programmed into the Arduino: @example a = arduino (); e = addon (a, "eepromaddon/eeprom"); write (e, 0, uint8("hello world")); str = uint8( read(e, 0, 11) ) @end example @xseealso{addon} @end deftypefn @subsubheading Properties @var{length} - Size of the EEPROM. @subheading Methods @deftypefn {} {@var{eeprom} =} EEPRom () Constructor to create EEPROM device. @subsubheading Outputs @var{eeprom} - created EEPROM device. @end deftypefn @deftypefn {} {} erase () Erase all values in EEPROM (Effectively setting the 0xFF) @end deftypefn @deftypefn {} {} write (@var{address}, @var{uintdata}) Write data to EEPROM at the provided address. @subsubheading Inputs @var{address} - start address to write data to, should be an integer between 0 and the size of the EEPROM. @var{uintdata} a value or array of uint8 data to write to EEPROM. @end deftypefn @deftypefn {} {@var{data} =} read (@var{address}) @deftypefnx {} {@var{data} =} read (@var{address}, @var{count}) Read data from starting address of EEPROM. @subsubheading Inputs @var{address} - start address to read data from, should be an integer between 0 and the size of the EEPROM. @var{count} - Number of uint8 values to read from the EEPROM (default is 1) @subsubheading Outputs @var{data} a value or array of uint8 data read from the EEPROM. @end deftypefn @c Arduino Addons arduinoioaddons.ExampleAddon.Echo @c ----------------------------------------- @subsection arduinoioaddons.ExampleAddon.Echo @cindex Echo @deftypefn {} {} arduinoioaddons.ExampleAddon.Echo Basic Example matlab/octave code to illustrate creating a user addon. @xseealso{addon} @end deftypefn @subsubheading Properties @var{Parent} - the parent arduino object. @var{Pins} - the pins allocated the addon. @subheading Methods @deftypefn {} {@var{obj} =} Echo(arObj) Constructor to create Echo addon @subsubheading Inputs @var{arObj} - the arduino parent object @subsubheading Outputs @var{obj} - created Echo object @end deftypefn @deftypefn {} {@var{response} = } shout(@var{text}) Send text to arduino and receive back the echoed reply @subsubheading Inputs @var{text} - text to send to arduino @subsubheading Outputs @var{response} - response from the arduino, which should be the same as the input text. @end deftypefn @c Arduino Addons arduinoioaddons.ExampleLCD.LCD @c ----------------------------------------- @subsection arduinoioaddons.ExampleLCD.LCD @cindex LCD @deftypefn {} {} arduinoioaddons.LCDAddon.LCD Basic Example octave addon for LCD Allows basic manipulation of an LCD as a illustration of using the addon functionality. @subsubheading Example Assuming the arduino has been programmed with the lcd addon: @example a = arduino(); lcd = addon(a, "examplelcd/lcd", "d8", "d9", "d4", "d5", "d6", "d7") clearLCD(lcd); printLCD(lcd, "Hello"); # go to next line gotoLCD(lcd, 0, 1); printLCD(lcd, "World"); @end example @xseealso{addon} @end deftypefn @subsubheading Properties @var{Pins} - the pins allocated the LCD display. @subheading Methods @deftypefn {} {@var{lcd} =} LCD(arObj, rs, enable, d0, d1, d2, d3) Constructor to create LCD device @subsubheading Inputs @var{arObj} - the arduino parent object @var{rs} - the pin to use for the rs line. @var{enable} - the pin to use for the enable line. @var{d0} - the pin to use for the d0 line. @var{d1} - the pin to use for the d1 line. @var{d2} - the pin to use for the d2 line. @var{d3} - the pin to use for the d3 line. @subsubheading Outputs @var{lcd} - created LCD object @end deftypefn @deftypefn {} {} freeLCD() Free the LCD Should be called before discarding the LCD @subsubheading Inputs None. @subsubheading Outputs None. @end deftypefn @deftypefn {} {} clearLCD() Clear the LCD display and set the cursor position to the home position. @subsubheading Inputs None. @subsubheading Outputs None. @end deftypefn @deftypefn {} {} printLCD(@var{text}) Display text on LCD starting at the current cursor position. @subsubheading Inputs @var{text} - text to display on LCD @subsubheading Outputs None. @end deftypefn @deftypefn {} {} gotoLCD(@var{col}, @var{row}) Set the cursor position to row, col @subsubheading Inputs @var{col} - 0 indexed LCD column to position to. @var{row} - 0 indexed LCD row to position to. @subsubheading Outputs None. @end deftypefn @c Arduino Addons arduinoioaddons.RTCAddon.DS1307 @c ----------------------------------------- @subsection arduinoioaddons.RTCAddon.DS1307 @cindex DS1307 @deftypefn {} {} arduinoioaddons.RTCAddon.DS1307 DS1307 addon @xseealso{addon} @end deftypefn @subsubheading Properties @var{Parent} - the parent arduino object. @var{Pins} - the pins allocated the addon. @subheading Methods @deftypefn {} {@var{obj} =} DS1307(@var{arObj}) @deftypefnx {} {@var{obj} =} DS1307(@var{arObj}, @var{propertyname, propertyvalue} ....) Constructor to create DS1307 addon @subsubheading Inputs @var{arObj} - the arduino parent object @var{propertyname, propertyvalue} - optional property name, value pairs. Current known properties are: @table @asis @item address I2C address of the DS1307 (default 0x68) @end table @subsubheading Outputs @var{obj} - created DS1307 object @subsubheading Example @example @code { a = arduino() rtc = addon(a, "rtcaddon/ds1307") } @end example @end deftypefn @deftypefn {} {@var{date} =} clock(@var{dsObj}) @deftypefnx {} {} clock(@var{dsObj}, @var{date}) Get/set the DS1307 clock @subsubheading Inputs @var{dsObj} - the ds1307 object @var{date} - a date vector in same format as datevec and clock @subsubheading Outputs @var{date} - a date vector in same format as datevec and clock @subsubheading Example @example @code { a = arduino() rtc = addon(a, "rtcaddon/ds1307") # get and display rtc time as a date string datestr(rtc.clock) } @end example @xseealso{datevec} @end deftypefn @deftypefn {} {@var{ctrl} =} control(@var{dsObj}) @deftypefnx {} {} control(@var{dsObj}, @var{ctrl}) Get/set the DS1307 clock @subsubheading Inputs @var{dsObj} - the ds1307 object @var{ctrl} - a structure containing the control bit fields. @subsubheading Outputs @var{ctrl} - a structure containing the control bit fields. Control structure fields are: Current properties are: @table @asis @item out Out bit in the control register @item sqwe Square wave enable bit in control register @item rs The combined RS0, RS1 value @end table @end deftypefn @deftypefn {} {@var{YN} =} isstarted(@var{dsObj}) Get whether the RTC clock is currently counting time @subsubheading Inputs @var{dsObj} - the ds1307 object @subsubheading Outputs @var{YN} - returns true if the RTC is counting @xseealso{start, stop} @end deftypefn @deftypefn {} {} start(@var{dsObj}) Start the RTC counting @subsubheading Inputs @var{dsObj} - the ds1307 object @subsubheading Outputs None @xseealso{datevec} @end deftypefn @deftypefn {} {} stop(@var{dsObj}) Stop the RTC counting @subsubheading Inputs @var{dsObj} - the ds1307 object @subsubheading Outputs None @xseealso{datevec} @end deftypefn @c Arduino Addons arduinoioaddons.SimpleStepper.SimpleStepper @c ----------------------------------------- @subsection arduinoioaddons.SimpleStepper.SimpleStepper @cindex SimpleStepper @deftypefn {} {} arduinoioaddons.SimpleStepper Stepper class for stepper control using ULN2003 and compatible drivers @end deftypefn @subsubheading Properties @table @asis @item @var{Id} Id of the stepper (Read only) @item @var{Speed} Number of steps to do per second. @item Status Status of stepper (Read only). 0 = not moving, 1 = moving, 2 = rotating @item Parent the Arduino parent (read only) @item Pins the pins used for the stepper (read only) @end table @subheading Methods @deftypefn {} {@var{obj} =} SimpleStepper(@var{aObj}, @var{pin1}, @var{pin2}, @var{pin3}, @var{pin4}) @deftypefnx {} {@var{obj} =} SimpleStepper(@var{aObj}, @var{pin1}, @var{pin2}, @var{pin3}, @var{pin4}, @var{pin5}) Constructor to create a stepper object @subsubheading Inputs @var{aObj} - The arduino @var{pin1} - The first pin of the controller @var{pin2} - The second pin of the controller @var{pin3} - The third pin of the controller @var{pin4} - The fourth pin of the controller @var{pin5} - The fifth pin of the controller @subsubheading Outputs @var{s} - a simplestepper object @subsubheading Example @example @code { a = arduino() # create stepper object s = addon(a, "simplestepper/simplestepper", "d2", "d3", "d4", "d5") # start rotating left s.rotate(-1); } @end example @xseealso{addon} @end deftypefn @deftypefn {} {} move(@var{sObj}, @var{steps}) Move the motor the specified number of steps using the configured Speed. @subsubheading Inputs @var{sObj} - the stepper object @var{steps} - the number of steps to move. steps less than 0 will be moving left. @subsubheading Outputs None @xseealso{rotate} @end deftypefn @deftypefn {} {} rotate(@var{sObj}, @var{dir}) Start steppermotor moving in the specified direction using the configured Speed. @subsubheading Inputs @var{sObj} - the stepper object @var{dir} - Direction to move. -1 = left, 0 = stop, 1 = right. @subsubheading Outputs None @xseealso{move} @end deftypefn @deftypefn {} {} release(@var{sObj}) Release this stepper motor @subsubheading Inputs @var{sObj} - the stepper object @subsubheading Outputs None @end deftypefn @c Arduino Addons arduinoioaddons.adafruit.dcmotorv2 @c ----------------------------------------- @subsection arduinoioaddons.adafruit.dcmotorv2 @cindex dcmotorv2 @deftypefn {} {} arduinoioaddons.adafruit.dcmotorv2 DC Motor class for dc motor control on the adafruit motor shield @xseealso{arduinoioaddons.adafruit.motorshieldv2} @end deftypefn @subsubheading Properties @var{Speed} - The speed value set for the motor @var{Parent} - The parent shield for object (read only) @var{MotorNumber} - The motor number (read only) values 1-4 @var{IsRunning} - boolean for if the motor is started (read only) @subheading Methods @deftypefn {} {@var{obj} =} dcmotorv2(@var{mObj}, @var{mnum}) @deftypefnx {} {@var{obj} =} dcmotorv2(@var{mObj}, @var{mnum}, @var{propertyname, propertyvalue} ....) Constructor to create dcmotor object @subsubheading Inputs @var{mObj} - the motor shield object @var{mnum} - The motor number (1 - 4) @var{propertyname, propertyvalue} - Optional property name/value pairs to pass to motor object. Current known properties are: @table @asis @item Speed Initial speed (default 0). Should be a value between -1 and 1. @end table @subsubheading Outputs @var{s} - a dcmotorv2 object @subsubheading Example @example @code { a = arduino() ms = addon(a, "adafruit/motorshieldv2") mtr = dcmotor(ms, 1) } @end example @end deftypefn @deftypefn {} {} start(@var{dcObj}) Start the motor moving in previously set speed/direction @subsubheading Inputs @var{dcObj} - the dcmotor object @subsubheading Outputs None @xseealso{adafruit.motorshieldv2} @end deftypefn @deftypefn {} {} stop(@var{dcObj}) Stop the motor moving @subsubheading Inputs @var{dcObj} - the dcmotor object @subsubheading Outputs None @xseealso{adafruit.motorshieldv2} @end deftypefn @c Arduino Addons arduinoioaddons.adafruit.motorshieldv2 @c ----------------------------------------- @subsection arduinoioaddons.adafruit.motorshieldv2 @cindex motorshieldv2 @deftypefn {} {} arduinoioaddons.adafruit.motorshieldv2 Adafruit motor shield addon @xseealso{addon} @end deftypefn @subsubheading Properties @var{Parent} - the parent arduino object. @var{Pins} - the pins allocated the addon. @var{I2CAddress} - the i2c address used for accessing this shield. @var{PWMFrequency} - the set PWM frequency for this shield. @subheading Methods @deftypefn {} {@var{obj} =} motorshieldv2(@var{arObj}) @deftypefnx {} {@var{obj} =} motorshieldv2(@var{arObj}, @var{propertyname, propertyvalue} ....) Constructor to create motorshieldv2 addon object @subsubheading Inputs @var{arObj} - the arduino parent object @var{propertyname, propertyvalue} - optional property name, value pairs. Current known properties are: @table @asis @item address I2C address of the motor shield (default 0x60) @item pwmfrequency PWM Frequency to set on shield (default 1600) @end table @subsubheading Outputs @var{obj} - created motorshieldv2 object @subsubheading Example @example @code { a = arduino() mtr = addon(a, "adafruit/motorshieldv2") } @end example @end deftypefn @deftypefn {} {@var{s} =} servo(@var{mObj}, @var{mtrnum}) @deftypefnx {} {@var{s} =} servo(@var{mObj}, @var{mtrnum}, @var{propertyname}, @var{propertyvalue} ...) Create a servo object @subsubheading Inputs @var{mObj} - the motor shield object @var{mtrnum} - The servo motor number, where 1 is servo on pin "d10" and 2 is a servo on pin "d9" @var{propertyname}, @var{propertyvalue} - Optional property name/value pairs to pass to servo object. Properties are the same as the base servo object. @subsubheading Outputs @var{s} - a servo object @subsubheading Example @example @code { a = arduino() ms = addon(a, "adafruit/motorshieldv2") # get servo 1 (servo on pin D10) s = ms.servo(1) } @end example The function if the equivalent of calling the arduino.servo with the D9 or D10 pin has the input pin. @xseealso{servo} @end deftypefn @deftypefn {} {@var{s} =} stepper(@var{mObj}, @var{mtrnum}, @var{stepsperrev}) @deftypefnx {} {@var{s} =} stepper(@var{mObj}, @var{mtrnum}, @var{stepsperrev}, @var{propertyname}, @var{propertyvalue} ...) Create a stepper motor object @subsubheading Inputs @var{mObj} - the motor shield object @var{mtrnum} - The stepper motor number (1 or 2) @var{stepsperrev} - Number of steps per revolution. @var{propertyname}, @var{propertyvalue} - Optional property name/value pairs to pass to stepper object. @subsubheading Outputs @var{s} - a stepper object @end deftypefn @deftypefn {} {@var{s} =} dcmotor(@var{mObj}, @var{mtrnum}) @deftypefnx {} {@var{s} =} dcmotor(@var{mObj}, @var{mtrnum}, @var{propertyname}, @var{propertyvalue} ...) Create a dcmotor motor object @subsubheading Inputs @var{mObj} - the motor shield object @var{mtrnum} - The motor number (1 - 4) @var{propertyname}, @var{propertyvalue} - Optional property name/value pairs to pass to motor object. @subsubheading Outputs @var{s} - a dcmotorv2 object @end deftypefn @c Arduino Addons arduinoioaddons.adafruit.stepper @c ----------------------------------------- @subsection arduinoioaddons.adafruit.stepper @cindex stepper @deftypefn {} {} arduinoioaddons.adafruit.stepper Stepper class for stepper control on the adafruit motor shield @xseealso{arduinoioaddons.adafruit.motorshieldv2} @end deftypefn @subsubheading Properties @table @asis @item @var{RPM} The rpm value set for the stepper motor @item StepType the StepType for the stepper (string) which can be "single", "double", "interleave" or "microstep" @item StepsPerRevolution the StepsPerRevoluion for the stepper (read only) @item MotorNumber the motor number for the stepper (read only) value will be 1 or 2. @item Parent the parent shield of this stepper (read only) @end table @subheading Methods @deftypefn {} {@var{obj} =} stepper(@var{mObj}, @var{mnum}, @var{stepsperrev}) @deftypefnx {} {@var{obj} =} stepper(@var{mObj}, @var{mnum}, @var{stepsperrev}, @var{propertyname, propertyvalue} ....) Constructor to create dcmotor object @subsubheading Inputs @var{mObj} - the motor shield object @var{mnum} - The motor number (1 or 2) @var{stepsperrev} - Number of steps per revolution. @var{propertyname, propertyvalue} - Optional property name/value pairs to pass to motor object. Current known properties are: @table @asis @item RPM the RPM for the stepper (revolutions per minute) @item StepType the StepType for the stepper (string) which can be "single", "double", "interleave" or "microstep" @end table @subsubheading Outputs @var{s} - a stepper object @subsubheading Example @example @code { a = arduino() ms = addon(a, "adafruit/motorshieldv2") mtr = stepper(ms, 1, 200) } @end example @end deftypefn @deftypefn {} {} move(@var{sObj}, @var{steps}) Move the motor moving in the specified steps using the configured RPM. @subsubheading Inputs @var{sObj} - the stepper object @subsubheading Outputs None @xseealso{adafruit.motorshieldv2} @end deftypefn @deftypefn {} {} release(@var{sObj}) Release this motor @subsubheading Inputs @var{sObj} - the stepper object @subsubheading Outputs None @xseealso{adafruit.motorshieldv2} @end deftypefn @c --------------------------------------------------- @node Arduino Sensors @section Arduino Sensors @cindex Arduino Sensors @c Arduino Sensors arduinosensor.DS1307 @c ----------------------------------------- @subsection arduinosensor.DS1307 @cindex DS1307 @deftypefn {} {} arduinosensor.DS1307 DS1307 realtime clock sensor @end deftypefn @subheading Methods @deftypefn {} {@var{obj} =} DS1307(@var{arObj}) @deftypefnx {} {@var{obj} =} DS1307(@var{arObj}, @var{propertyname, propertyvalue} ....) Constructor to create DS1307 sensor @subsubheading Inputs @var{arObj} - the arduino parent object @var{propertyname, propertyvalue} - optional property name, value pairs. Current known properties are: Current properties are: @table @asis @item i2caddress I2C address of the DS1307 (default 0x68) @end table @subsubheading Outputs @var{obj} - created DS1307 object @subsubheading Example @example @code { a = arduino() rtc = arduinosensor.DS1307(a) } @end example @end deftypefn @deftypefn {} {@var{date} =} clock(@var{dsObj}) @deftypefnx {} {} clock(@var{dsObj}, @var{date}) Get/set the DS1307 clock @subsubheading Inputs @var{dsObj} - the ds1307 object @var{date} - a date vector in same format as datevec and clock @subsubheading Outputs @var{date} - a date vector in same format as datevec and clock @subsubheading Example @example @code { a = arduino() rtc = arduinosensor.DS1307(a) # get and display rtc time as a date string datestr(rtc.clock) } @end example @xseealso{datevec} @end deftypefn @deftypefn {} {@var{ctrl} =} control(@var{dsObj}) @deftypefnx {} {} control(@var{dsObj}, @var{ctrl}) Get/set the DS1307 clock @subsubheading Inputs @var{dsObj} - the ds1307 object @var{ctrl} - a structure containing the control bit fields. @subsubheading Outputs @var{ctrl} - a structure containing the control bit fields. Control structure fields are: Current properties are: @table @asis @item out Out bit in the control register @item sqwe Square wave enable bit in control register @item rs The combined RS0, RS1 value @end table @end deftypefn @deftypefn {} {@var{YN} =} isstarted(@var{dsObj}) Get whether the RTC clock is currently counting time @subsubheading Inputs @var{dsObj} - the ds1307 object @subsubheading Outputs @var{YN} - returns true if the RTC is counting @xseealso{start, stop} @end deftypefn @deftypefn {} {} start(@var{dsObj}) Start the RTC counting @subsubheading Inputs @var{dsObj} - the ds1307 object @subsubheading Outputs None @xseealso{datevec} @end deftypefn @deftypefn {} {} stop(@var{dsObj}) Stop the RTC counting @subsubheading Inputs @var{dsObj} - the ds1307 object @subsubheading Outputs None @xseealso{datevec} @end deftypefn @c Arduino Sensors arduinosensor.GUVAS12SD @c ----------------------------------------- @subsection arduinosensor.GUVAS12SD @cindex GUVAS12SD @deftypefn {} {} arduinosensor.GUVAS12SD A thin wrapper for the GUVAS12SD analog UV-B sensor @end deftypefn @subheading Methods @deftypefn {} {@var{obj} =} GUVAS12SD(@var{arObj}, @var{pin}) Constructor to create GUVAS12SD sensor @subsubheading Inputs @var{arObj} - the arduino parent object @var{pin} - the analog pin that the sensor is connected to @subsubheading Outputs @var{obj} - created GUVAS12SD object @subsubheading Example @example @code { a = arduino() # create sensor attached to pin a0. sensor = arduinosensor.GUVAS12SD(a, "a0") } @end example @end deftypefn @deftypefn {} {@var{V} =} read(@var{dsObj}) Read the voltage of the sensor @subsubheading Inputs @var{dsObj} - the GUVAS12SD object @subsubheading Outputs @var{V} - read voltage - effectively equivalent to readAnalogPin(arObj, pin). @subsubheading Example @example @code { a = arduino() s = arduinosensor.GUVAS12SD(a) # voltage volts = s.read } @end example @xseealso{arduinosensor.GUVAS12SD} @end deftypefn @deftypefn {} {@var{Idx} =} readIndex(@var{dsObj}) Read the UV index @subsubheading Inputs @var{dsObj} - the GUVAS12SD object @subsubheading Outputs @var{Idx} - the sensor reading as a UV index reading @end deftypefn @deftypefn {} {@var{uA} =} readuA(@var{dsObj}) Read the uA of the sensor @subsubheading Inputs @var{dsObj} - the GUVAS12SD object @subsubheading Outputs @var{uA} - the sensor reading as a uAmp value @end deftypefn @c Arduino Sensors arduinosensor.MPC3002 @c ----------------------------------------- @subsection arduinosensor.MPC3002 @cindex MPC3002 @deftypefn {} {} arduinosensor.MPC3002 MCP3002 ADC sensor @end deftypefn @subheading Methods @deftypefn {} {@var{obj} =} MPC3002(@var{arObj}, @var{selectPin}) @deftypefnx {} {@var{obj} =} MPC3002(@var{arObj}, @var{selectPin}, @var{propertyname, propertyvalue} ....) Constructor to create MPC3002 sensor @subsubheading Inputs @var{arObj} - the arduino parent object @var{selectPin} - the SPI cs select pin @var{propertyname, propertyvalue} - optional property name, value pairs. Current properties are: @table @asis @item referenceVoltage Reference voltage for scaling the ADC inputs (default 5.0) @end table @subsubheading Outputs @var{obj} - created MCP3002 object @subsubheading Example @example @code { a = arduino() sensor = arduinosensor.MPC3002(a, "d10") } @end example @end deftypefn @deftypefn {} {@var{voltage} =} readVoltage(@var{dsObj}, @var{chan}) Read the voltage from a channel @subsubheading Inputs @var{dsObj} - the MPC3002 object @var{chan} - the channel to read (0 or 1) @subsubheading Outputs @var{voltage} - read voltage. @subsubheading Example @example @code { a = arduino() s = arduinosensor.MPC3002(a, "d10") volts = readVoltage(s, 0) } @end example @xseealso{arduinosensor.MPC3002} @end deftypefn @c Arduino Sensors arduinosensor.SI7021 @c ----------------------------------------- @subsection arduinosensor.SI7021 @cindex SI7021 @deftypefn {} {} arduinosensor.SI7021 SI7021 temperature and humidity sensor @end deftypefn @subheading Methods @deftypefn {} {@var{obj} =} SI7021(@var{arObj}) @deftypefnx {} {@var{obj} =} SI7021(@var{arObj}, @var{propertyname, propertyvalue} ....) Constructor to create SI7021 sensor @subsubheading Inputs @var{arObj} - the arduino parent object @var{propertyname, propertyvalue} - optional property name, value pairs. Current known properties are: Current properties are: @table @asis @item i2caddress I2C address of the SI7021 (default 0x40) @end table @subsubheading Outputs @var{obj} - created SI7020 object @subsubheading Example @example @code { a = arduino() sensor = arduinosensor.SI7021(a) } @end example @end deftypefn @deftypefn {} {@var{C} =} temperature(@var{dsObj}) Read the temperature @subsubheading Inputs @var{dsObj} - the si7021 object @subsubheading Outputs @var{C} - read temperature in deg C. @subsubheading Example @example @code { a = arduino() s = arduinosensor.SI7021(a) # get temp temp = s.temperature } @end example @xseealso{arduinosensor.SI7021} @end deftypefn @deftypefn {} {@var{relH} =} humidity(@var{dsObj}) Read the relative humidity @subsubheading Inputs @var{dsObj} - the si7021 object @subsubheading Outputs @var{relH} - relative humidity as a percentage (0 - 100.0) @end deftypefn @deftypefn {} {@var{relH} =} info(@var{dsObj}) Read the sensor info @subsubheading Inputs @var{dsObj} - the si7021 object @subsubheading Outputs @var{inf} - structure containing the sensor information. Structure fields are: @table @asis @item version Chip firmware version @item id sensor id1,id2 value @item type String for detected chip type @end table @end deftypefn @c --------------------------------------------------- @node Arduino I/O package @section Arduino I/O package @cindex Arduino I/O package @c Arduino I/O package arduinoio.AddonBase @c ----------------------------------------- @subsection arduinoio.AddonBase @cindex AddonBase @deftypefn {} {} arduinoio.AddonBase Base class used for arduino library sensors @xseealso{arduinoio.LibraryBase} @end deftypefn @subheading Properties Base properties are expected to be inherited and overwritten in inherited classes. and are constant in order to query through the metaobject mechanism. @var{Parent} - parent librarybase object @subheading Methods @deftypefn {} {@var{ab} =} AddonBase () Constructor of base class @subsubheading Outputs The return value @var{ab} is an object of the arduinio.AddonBase class. @xseealso{arduino, addon} @end deftypefn @deftypefn {} {} disp () Display the addon in a verbose way. @end deftypefn @c Arduino I/O package arduinoio.FilePath @c ----------------------------------------- @subsection arduinoio.FilePath @cindex FilePath @deftypefn {} {@var{retval} =} arduinoio.FilePath (@var{fullpathname}) Get the directory component of a pathname. @subsubheading Inputs @var{fullpathname} filepath to get directory component of. @subsubheading Outputs @var{retval} the directory part of the filename. @end deftypefn @c Arduino I/O package arduinoio.LibFiles @c ----------------------------------------- @subsection arduinoio.LibFiles @cindex LibFiles @deftypefn {} {@var{filelist} =} arduinoio.LibFiles () Get the list of files used for the building arduino library @subsubheading Outputs @var{filelist} - string cell array of files for the arduino project @end deftypefn @c Arduino I/O package arduinoio.LibraryBase @c ----------------------------------------- @subsection arduinoio.LibraryBase @cindex LibraryBase @deftypefn {} {} arduinoio.LibraryBase Base class used for arduino library plugins @xseealso{arduino, listArduinoLibraries, addon} @end deftypefn @subheading Properties Base properties are expected to be inherited and overwritten in inherited classes and are constant in order to query through the metaobject mechanism. @var{LibraryName} - name of the addon library @var{DependentLibraries} - array of dependent library names that must be included when installing this plugin. @var{CppHeaderFile} - name (if any) of header file that will be included into the arduino project when adding this library. @var{CppSourceFile} - name (if any) of source file that will be included into the arduino project when adding this library. @var{CppClassName} - name of the cpp class for the addon library. project when adding this library. @var{Pins} - pins allocated to the addon @var{Parent} - parent arduino object. @subheading Methods @deftypefn {} {@var{lb} =} LibraryBase () Constructor of base class The constructor is usually not called but called indirectly from the addon function. @subsubheading Outputs The return value @var{lb} is an object of the arduinio.LibraryBase class. @xseealso{arduino, listArduinoLibraries, addon} @end deftypefn @deftypefn {} {} disp () Display the addon in a verbose way. @end deftypefn @c Arduino I/O package arduinoio.getBoardConfig @c ----------------------------------------- @subsection arduinoio.getBoardConfig @cindex getBoardConfig @deftypefn {} {@var{retval} =} arduinoio.getBoardConfig (@var{boardname}) Return the configuration for a known arduino board type Function is used to get the expected pin/board configuration for a named board type which is used to verify and identify the functionality of the board. @subsubheading Inputs @var{boardname} - name of board to get configuration of ie: "uno" @subsubheading Outputs @var{retval} configuration struct. @end deftypefn @c --------------------------------------------------- @node Matlab Compatibility Classes @section Matlab Compatibility Classes @cindex Matlab Compatibility Classes @c Matlab Compatibility Classes matlabshared.addon.LibraryBase @c ----------------------------------------- @subsection matlabshared.addon.LibraryBase @cindex LibraryBase @deftypefn {} {} matlabshared.addon.LibraryBase Compatability class used for arduino library plugins using matlabshared.addons.LibraryBase @xseealso{arduinoio.LibraryBase, arduino, listArduinoLibraries, addon} @end deftypefn @subheading Properties Base properties are expected to be inherited and overwritten in inherited classes and are constant in order to query through the metaobject mechanism. @var{LibraryName} - name of the addon library @var{DependentLibraries} - array of dependent library names that must be included when installing this plugin. @var{CppHeaderFile} - name (if any) of header file that will be included into the arduino project when adding this library. @var{CppSourceFile} - name (if any) of source file that will be included into the arduino project when adding this library. @var{CppClassName} - name of the cpp class for the addon library. project when adding this library. @var{Pins} - pins allocated to the addon @var{Parent} - parent arduino object. @subheading Methods @deftypefn {} {@var{lb} =} LibraryBase () Constructor of base class The constructor is usually not called but called indirectly from the addon function. @subsubheading Outputs The return value @var{lb} is an object of the matlabshare.addons.LibraryBase class. @xseealso{arduino, listArduinoLibraries, addon} @end deftypefn @deftypefn {} {} disp () Display the addon in a verbose way. @end deftypefn @c --------------------------------------------------- @node Sensors @section Sensors @cindex Sensors @c Sensors bme280 @c ----------------------------------------- @subsection bme280 @cindex bme280 @deftypefn {} {} bme280 BME280 pressure, temperature and humidity sensor @end deftypefn @subheading Methods @deftypefn {} {@var{obj} =} bme280(@var{arObj}) @deftypefnx {} {@var{obj} =} bme280(@var{arObj}, @var{propertyname, propertyvalue} ....) Constructor to create BME280 sensor @subsubheading Inputs @var{arObj} - the arduino parent object @var{propertyname, propertyvalue} - optional property name, value pairs. Current known properties are: Current properties are: @table @asis @item I2CAddress I2C address of the sensor (default 0x40) @item Bus I2C bus - 0 or 1 (default 0) @end table @subsubheading Outputs @var{obj} - created object @subsubheading Example @example @code { a = arduino() sensor = bme280(a) } @end example @end deftypefn @deftypefn {} {[@var{C}, @var{timestamp}] =} readTemperature(@var{obj}) Read the temperature @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{C} - read temperature in deg C. @var{timestamp} - timestamp when read @subsubheading Example @example @code { a = arduino() s = bme280(a) # get temp temp = s.readTemperature } @end example @xseealso{bme280} @end deftypefn @deftypefn {} {[@var{relH}, @var{timestamp}] =} readHumidity(@var{obj}) Read the relative humidity @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{relH} - relative humidity as a percentage (0 - 100.0) @var{timestamp} - timestamp when read @end deftypefn @deftypefn {} {[@var{P}, @var{timestamp}] =} readPressure(@var{obj}) Read the pressure @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{P} - pressure reading from sensor. @var{timestamp} - timestamp when read @end deftypefn @deftypefn {} {[@var{readings}, @var{overrun}] =} read(@var{obj}) @deftypefnx {} {[@var{P}, @var{H}, @var{C}, @var{timestamp}, @var{overrun}] =} read(@var{obj}) Read the sensor data @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{P} - pressure reading from sensor. @var{H} - humidity reading from sensor. @var{C} - temperature reading from sensor. @var{timestamp} - timestamp when read @var{overrun} - overrun flag. @var{readings} - table structure with fields for Timestamp, Pressure, Temperature and Humidity. @end deftypefn @deftypefn {} {@var{inf} =} info(@var{obj}) Read the sensor info @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{inf} - structure containing the sensor information. Structure fields are: @table @asis @item Version Chip firmware version @item SensorId sensor id value @item Type sensor type 'bme280' @item Status Status value read from sensor @end table @end deftypefn @deftypefn {} {} flush(@var{obj}) Flush sensor data @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs None @end deftypefn @deftypefn {} {} release(@var{obj}) Release the resources of the sensor @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs None @end deftypefn @c Sensors bno055 @c ----------------------------------------- @subsection bno055 @cindex bno055 @deftypefn {} {} bno055 BNO055 9 axis orientation sensor @end deftypefn @subheading Methods @deftypefn {} {@var{obj} =} bno055(@var{arObj}) @deftypefnx {} {@var{obj} =} bno055(@var{arObj}, @var{propertyname, propertyvalue} ....) Constructor to create BME280 sensor @subsubheading Inputs @var{arObj} - the arduino parent object @var{propertyname, propertyvalue} - optional property name, value pairs. Current known properties are: Current properties are: @table @asis @item I2CAddress I2C address of the sensor (default 0x40) @item Bus I2C bus - 0 or 1 (default 0) @item OperatingMode Operating mode 'ndof' or 'amg' @end table @subsubheading Outputs @var{obj} - created object @subsubheading Example @example @code { a = arduino() sensor = bno055(a) } @end example @end deftypefn @deftypefn {} {[@var{C}, @var{timestamp}] =} readTemperature(@var{obj}) Read the temperature @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{C} - read temperature in deg C. @var{timestamp} - timestamp when read @subsubheading Example @example @code { a = arduino() s = bno055(a) # get temp temp = s.readTemperature } @end example @xseealso{bno055} @end deftypefn @deftypefn {} {[@var{readVal}, @var{timestamp}] =} readAcceleration(@var{obj}) Read the acceleration rate @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{readVal} - the 3 acceleration values @var{timestamp} - timestamp when read @end deftypefn @deftypefn {} {[@var{readVal}, @var{timestamp}] =} readAngularVelocity(@var{obj}) Read the angular velocity @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{readVal} - the 3 angular velocity values @var{timestamp} - timestamp when read @end deftypefn @deftypefn {} {[@var{readVal}, @var{timestamp}] =} readMagneticField(@var{obj}) Read the magnetic field components @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{readVal} - the 3 magnetic field values @var{timestamp} - timestamp when read @end deftypefn @deftypefn {} {[@var{readVal}, @var{timestamp}] =} readOrientation(@var{obj}) Read the oriientation components @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{readVal} - the 3 orientation values @var{timestamp} - timestamp when read @end deftypefn @deftypefn {} {[@var{readings}, @var{overrun}] =} read(@var{obj}) @deftypefnx {} {[@var{accel}, @var{gyro}, @var{mag}, @var{timestamp}, @var{overrun}] =} read(@var{obj}) @deftypefnx {} {[@var{accel}, @var{gyro}, @var{mag}, @var{orientation}, @var{timestamp}, @var{overrun}] =} read(@var{obj}) Read the sensor data @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{accel} - acceleration reading from sensor. @var{gyro} - angular acceleration reading from sensor. @var{mag} - magnetic field reading from sensor. @var{orientation} - orientation reading from sensor. @var{timestamp} - timestamp when read @var{overrun} - overrun flag. @var{readings} - table structure with fields for Timestamp, Acceleration, AngularVelocity, MagneticField, Orientation. @end deftypefn @deftypefn {} {@var{inf} =} readCalibrationStatus(@var{obj}) Read the sensor calibration status @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{status} - structure containing the calibration information. Structure fields are: @table @asis @item System System calibrarion @item Accelerometer Accelerometer calibration status @item Gyroscope Gyroscope calibration status @item Magnetometer Magnetometer calibration status @end table Values for each will be either 'uncalibrated', 'partial' or 'full'. @end deftypefn @deftypefn {} {@var{inf} =} info(@var{obj}) Read the sensor info @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{inf} - structure containing the sensor information. Structure fields are: @table @asis @item Version Software firmware version @item SensorId sensor id value @item Type sensor type 'bno055' @end table @end deftypefn @deftypefn {} {} flush(@var{obj}) Flush sensor data @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs None @end deftypefn @deftypefn {} {} release(@var{obj}) Release the resources of the sensor @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs None @end deftypefn @c Sensors lis3dh @c ----------------------------------------- @subsection lis3dh @cindex lis3dh @deftypefn {} {} lis3dh LIS3DH 3 degrees sensor @end deftypefn @subheading Methods @deftypefn {} {@var{obj} =} lis3dh(@var{arObj}) @deftypefnx {} {@var{obj} =} lis3dh(@var{arObj}, @var{propertyname, propertyvalue} ....) Constructor to create LIS3DH sensor @subsubheading Inputs @var{arObj} - the arduino parent object @var{propertyname, propertyvalue} - optional property name, value pairs. Current known properties are: Current properties are: @table @asis @item I2CAddress I2C address of the sensor (default 0x40) @item Bus I2C bus - 0 or 1 (default 0) @end table @subsubheading Outputs @var{obj} - created object @subsubheading Example @example @code { a = arduino() sensor = lis3dh(a) } @end example @end deftypefn @deftypefn {} {[@var{readVal}, @var{timestamp}] =} readAcceleration(@var{obj}) Read the acceleration rate @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{readVal} - the 3 acceleration values @var{timestamp} - timestamp when read @end deftypefn @deftypefn {} {[@var{readings}, @var{overrun}] =} read(@var{obj}) @deftypefnx {} {[@var{accel}, @var{timestamp}, @var{overrun}] =} read(@var{obj}) Read the sensor data @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{accel} - acceleration reading from sensor. @var{timestamp} - timestamp when read @var{overrun} - overrun flag. @var{readings} - table structure with fields for Timestamp, Acceleration. @end deftypefn @deftypefn {} {@var{inf} =} info(@var{obj}) Read the sensor info @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{inf} - structure containing the sensor information. Structure fields are: @table @asis @item SensorId sensor id value @item Type sensor type 'lis3dh' @item Status sensor status value @end table @end deftypefn @deftypefn {} {} flush(@var{obj}) Flush sensor data @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs None @end deftypefn @deftypefn {} {} release(@var{obj}) Release the resources of the sensor @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs None @end deftypefn @c Sensors lps22hb @c ----------------------------------------- @subsection lps22hb @cindex lps22hb @deftypefn {} {} lps22hb LPS22HB absolute pressure and temperature sensor @end deftypefn @subheading Methods @deftypefn {} {@var{obj} =} lps22hb(@var{arObj}) @deftypefnx {} {@var{obj} =} lps22hb(@var{arObj}, @var{propertyname, propertyvalue} ....) Constructor to create LPS22HB sensor @subsubheading Inputs @var{arObj} - the arduino parent object @var{propertyname, propertyvalue} - optional property name, value pairs. Current known properties are: Current properties are: @table @asis @item I2CAddress I2C address of the sensor (default 0x5C) @item Bus I2C bus - 0 or 1 (default 0) @end table @subsubheading Outputs @var{obj} - created object @subsubheading Example @example @code { a = arduino() sensor = lps22hb(a) } @end example @end deftypefn @deftypefn {} {[@var{C}, @var{timestamp}] =} readTemperature(@var{obj}) Read the temperature @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{C} - read temperature in deg C. @var{timestamp} - timestamp when read @subsubheading Example @example @code { a = arduino() s = lps22hb(a) # get temp temp = s.readTemperature } @end example @xseealso{lps22hb} @end deftypefn @deftypefn {} {[@var{P}, @var{timestamp}] =} readPressure(@var{obj}) Read the pressure @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{P} - pressure reading from sensor. @var{timestamp} - timestamp when read @end deftypefn @deftypefn {} {[@var{readings}, @var{overrun}] =} read(@var{obj}) @deftypefnx {} {[@var{P}, @var{C}, @var{timestamp}, @var{overrun}] =} read(@var{obj}) Read the sensor data @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{P} - pressure reading from sensor. @var{C} - temperature reading from sensor. @var{timestamp} - timestamp when read @var{overrun} - overrun flag. @var{readings} - table structure with fields for Timestamp, Pressure, Temperature and Humidity. @end deftypefn @deftypefn {} {@var{inf} =} info(@var{obj}) Read the sensor info @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{inf} - structure containing the sensor information. Structure fields are: @table @asis @item Version Chip firmware version @item SensorId sensor id value @item Type sensor type 'lps22hb' @item Status Status value read from sensor @end table @end deftypefn @deftypefn {} {} flush(@var{obj}) Flush sensor data @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs None @end deftypefn @deftypefn {} {} release(@var{obj}) Release the resources of the sensor @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs None @end deftypefn @c Sensors lsm6dso @c ----------------------------------------- @subsection lsm6dso @cindex lsm6dso @deftypefn {} {} lsm6dso LSM6DSO 6 degrees sensor @end deftypefn @subheading Methods @deftypefn {} {@var{obj} =} lsm6dso(@var{arObj}) @deftypefnx {} {@var{obj} =} lsm6dso(@var{arObj}, @var{propertyname, propertyvalue} ....) Constructor to create LSM6DSO sensor @subsubheading Inputs @var{arObj} - the arduino parent object @var{propertyname, propertyvalue} - optional property name, value pairs. Current known properties are: Current properties are: @table @asis @item I2CAddress I2C address of the sensor (default 0x40) @item Bus I2C bus - 0 or 1 (default 0) @end table @subsubheading Outputs @var{obj} - created object @subsubheading Example @example @code { a = arduino() sensor = lsm6dso(a) } @end example @end deftypefn @deftypefn {} {[@var{C}, @var{timestamp}] =} readTemperature(@var{obj}) Read the temperature @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{C} - read temperature in deg C. @var{timestamp} - timestamp when read @subsubheading Example @example @code { a = arduino() s = lsm6dso(a) # get temp temp = s.readTemperature } @end example @xseealso{lsm6dso} @end deftypefn @deftypefn {} {[@var{readVal}, @var{timestamp}] =} readAcceleration(@var{obj}) Read the acceleration rate @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{readVal} - the 3 acceleration values @var{timestamp} - timestamp when read @end deftypefn @deftypefn {} {[@var{readVal}, @var{timestamp}] =} readAngularVelocity(@var{obj}) Read the angular velocity @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{readVal} - the 3 angular velocity values @var{timestamp} - timestamp when read @end deftypefn @deftypefn {} {[@var{readings}, @var{overrun}] =} read(@var{obj}) @deftypefnx {} {[@var{accel}, @var{gyro}, @var{mag}, @var{timestamp}, @var{overrun}] =} read(@var{obj}) Read the sensor data @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{accel} - acceleration reading from sensor. @var{gyro} - angular acceleration reading from sensor. @var{timestamp} - timestamp when read @var{overrun} - overrun flag. @var{readings} - table structure with fields for Timestamp, Acceleration, AngularVelocity. @end deftypefn @deftypefn {} {@var{inf} =} info(@var{obj}) Read the sensor info @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{inf} - structure containing the sensor information. Structure fields are: @table @asis @item SensorId sensor id value @item Type sensor type 'lsm6dso' @end table @end deftypefn @deftypefn {} {} flush(@var{obj}) Flush sensor data @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs None @end deftypefn @deftypefn {} {} release(@var{obj}) Release the resources of the sensor @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs None @end deftypefn @c Sensors mpu6050 @c ----------------------------------------- @subsection mpu6050 @cindex mpu6050 @deftypefn {} {} mpu6050 MPU-6050 6 degrees sensor @end deftypefn @subheading Methods @deftypefn {} {@var{obj} =} mpu6050(@var{arObj}) @deftypefnx {} {@var{obj} =} mpu6050(@var{arObj}, @var{propertyname, propertyvalue} ....) Constructor to create MPU-6050 sensor @subsubheading Inputs @var{arObj} - the arduino parent object @var{propertyname, propertyvalue} - optional property name, value pairs. Current known properties are: Current properties are: @table @asis @item I2CAddress I2C address of the sensor (default 0x40) @item Bus I2C bus - 0 or 1 (default 0) @end table @subsubheading Outputs @var{obj} - created object @subsubheading Example @example @code { a = arduino() sensor = mpu6050(a) } @end example @end deftypefn @deftypefn {} {[@var{C}, @var{timestamp}] =} readTemperature(@var{obj}) Read the temperature @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{C} - read temperature in deg C. @var{timestamp} - timestamp when read @subsubheading Example @example @code { a = arduino() s = mpu6050(a) # get temp temp = s.readTemperature } @end example @xseealso{mpu6050} @end deftypefn @deftypefn {} {[@var{readVal}, @var{timestamp}] =} readAcceleration(@var{obj}) Read the acceleration rate @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{readVal} - the 3 acceleration values @var{timestamp} - timestamp when read @end deftypefn @deftypefn {} {[@var{readVal}, @var{timestamp}] =} readAngularVelocity(@var{obj}) Read the angular velocity @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{readVal} - the 3 angular velocity values @var{timestamp} - timestamp when read @end deftypefn @deftypefn {} {[@var{readings}, @var{overrun}] =} read(@var{obj}) @deftypefnx {} {[@var{accel}, @var{gyro}, @var{mag}, @var{timestamp}, @var{overrun}] =} read(@var{obj}) Read the sensor data @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{accel} - acceleration reading from sensor. @var{gyro} - angular acceleration reading from sensor. @var{timestamp} - timestamp when read @var{overrun} - overrun flag. @var{readings} - table structure with fields for Timestamp, Acceleration, AngularVelocity. @end deftypefn @deftypefn {} {@var{inf} =} info(@var{obj}) Read the sensor info @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs @var{inf} - structure containing the sensor information. Structure fields are: @table @asis @item SensorId sensor id value @item Type sensor type 'mpu6050' @end table @end deftypefn @deftypefn {} {} flush(@var{obj}) Flush sensor data @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs None @end deftypefn @deftypefn {} {} release(@var{obj}) Release the resources of the sensor @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs None @end deftypefn @c Sensors si7021 @c ----------------------------------------- @subsection si7021 @cindex si7021 @deftypefn {} {} si7021 SI7021 temperature and humidity sensor @end deftypefn @subheading Methods @deftypefn {} {@var{obj} =} si7021(@var{arObj}) @deftypefnx {} {@var{obj} =} si7021(@var{arObj}, @var{propertyname, propertyvalue} ....) Constructor to create si7021 sensor @subsubheading Inputs @var{arObj} - the arduino parent object @var{propertyname, propertyvalue} - optional property name, value pairs. Current known properties are: Current properties are: @table @asis @item I2Caddress I2C address of the si7021 (default 0x40) @item Bus I2C bus (default 0) @end table @subsubheading Outputs @var{obj} - created SI7020 object @subsubheading Example @example @code { a = arduino() sensor = si7021(a) } @end example @end deftypefn @deftypefn {} {[@var{C}, @var{timestamp}] =} readTemperature(@var{obj}) Read the temperature @subsubheading Inputs @var{obj} - the si7021 object @subsubheading Outputs @var{C} - read temperature in deg C. @var{timestamp} - timestamp when read @subsubheading Example @example @code { a = arduino() s = si7021(a) # get temp temp = s.readTemperature() } @end example @xseealso{si7021} @end deftypefn @deftypefn {} {[@var{relH}, @var{timestamp}] =} readHumidity(@var{obj}) Read the relative humidity @subsubheading Inputs @var{obj} - the si7021 object @subsubheading Outputs @var{relH} - relative humidity as a percentage (0 - 100.0) @var{timestamp} - timestamp when read @end deftypefn @deftypefn {} {[@var{readings}, @var{overrun}] =} read(@var{obj}) @deftypefnx {} {[@var{H}, @var{C}, @var{timestamp}, @var{overrun}] =} read(@var{obj}) Read the sensor data @subsubheading Inputs @var{obj} - the si2071 sensor object @subsubheading Outputs @var{H} - humidity reading from sensor. @var{C} - temperature reading from sensor. @var{timestamp} - timestamp when read @var{overrun} - overrun flag. @var{readings} - table structure with fields for Timestamp, Temperature and Humidity. @end deftypefn @deftypefn {} {@var{relH} =} info(@var{dsObj}) Read the sensor info @subsubheading Inputs @var{dsObj} - the si7021 object @subsubheading Outputs @var{inf} - structure containing the sensor information. Structure fields are: @table @asis @item Version Chip firmware version @item SensorDd sensor id value @item Type String for detected chip type @end table @end deftypefn @deftypefn {} {} flush(@var{obj}) Flush sensor data @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs None @end deftypefn @deftypefn {} {} release(@var{obj}) Release the resources of the sensor @subsubheading Inputs @var{obj} - the sensor object @subsubheading Outputs None @end deftypefn @c --------------------------------------------------- @node Test Functions @section Test Functions @cindex Test Functions @c Test Functions arduino_bistsetup @c ----------------------------------------- @subsection arduino_bistsetup @cindex arduino_bistsetup @deftypefn {} {@var{retval} =} arduino_bistsetup () @deftypefnx {} {@var{retval} =} arduino_bistsetup (@var{propertyname}, @var{propertyvalue}) Install on an arduino the required core libraries to run the BIST tests As part of the setup, the arduino IDE will be opened to allow programming the arduino board. @subsubheading Inputs @var{propertyname}, @var{propertyvalue} - A sequence of property name/value pairs can be given to set defaults while programming. Currently the following properties can be set: @table @asis @item arduinobinary The value should be the name/path of the arduino IDE binary for programming. If not specified, the function will attempt to find the binary itself. @item debug Set the debug flag when checking the arduino @end table @subsubheading Outputs @var{retval} - return 1 if everything installed ok @xseealso{arduino, arduinosetup} @end deftypefn arduino-0.12.1/doc/gpl.texi0000644000000000000000000010433014545566645012431 0ustar00@node Copying @appendix GNU General Public License @cindex warranty @cindex copyright @center Version 3, 29 June 2007 @display Copyright @copyright{} 2007 Free Software Foundation, Inc. @url{http://fsf.org/} Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @end display @heading 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. @heading TERMS AND CONDITIONS @enumerate 0 @item 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. @item 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. @item 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. @item 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. @item 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. @item 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: @enumerate a @item The work must carry prominent notices stating that you modified it, and giving a relevant date. @item 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''. @item 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. @item 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. @end enumerate 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. @item 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: @enumerate a @item 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. @item 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. @item 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. @item 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. @item 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. @end enumerate 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. @item 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: @enumerate a @item Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or @item 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 @item 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 @item Limiting the use for publicity purposes of names of licensors or authors of the material; or @item Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or @item 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. @end enumerate 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. @item 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. @item 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. @item 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. @item 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. @item 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. @item 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. @item 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. @item 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. @item 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. @item 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 enumerate @heading END OF TERMS AND CONDITIONS @heading 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. @smallexample @var{one line to give the program's name and a brief idea of what it does.} Copyright (C) @var{year} @var{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 @url{http://www.gnu.org/licenses/}. @end smallexample 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: @smallexample @var{program} Copyright (C) @var{year} @var{name of author} This program comes with ABSOLUTELY NO WARRANTY; for details type @samp{show w}. This is free software, and you are welcome to redistribute it under certain conditions; type @samp{show c} for details. @end smallexample The hypothetical commands @samp{show w} and @samp{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 @url{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 @url{http://www.gnu.org/philosophy/why-not-lgpl.html}. arduino-0.12.1/doc/macros.texi0000644000000000000000000000624114545566645013135 0ustar00@c Copyright (C) 2012-2019 John W. Eaton @c @c This file is part of Octave. @c @c Octave is free software: you can redistribute it and/or modify it @c under the terms of the GNU General Public License as published by @c the Free Software Foundation, either version 3 of the License, or @c (at your option) any later version. @c @c Octave is distributed in the hope that it will be useful, but @c WITHOUT ANY WARRANTY; without even the implied warranty of @c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @c GNU General Public License for more details. @c @c You should have received a copy of the GNU General Public License @c along with Octave; see the file COPYING. If not, see @c . @c The following macro marks words that aspell should ignore during @c spellchecking. Within Texinfo it has no effect as it merely replaces @c the macro call with the argument itself. @macro nospell {arg} \arg\ @end macro @c The following macro works around the Info/plain text expansion of @code{XXX} @c which is `XXX'. This looks particularly bad when the macro body is @c single or double-quoted text, such as a property value `"position"' @ifinfo @macro qcode{arg} \arg\ @end macro @end ifinfo @ifnotinfo @macro qcode{arg} @code{\arg\} @end macro @end ifnotinfo @c The following macro is used for the on-line help system, but we don't @c want lots of `See also: foo, bar, and baz' strings cluttering the @c printed manual (that information should be in the supporting text for @c each group of functions and variables). @c @c Implementation Note: @c For TeX, @vskip produces a nice separation. @c For Texinfo, '@sp 1' should work, but in practice produces ugly results @c for HTML. We use a simple blank line to produce the correct @c behavior. @c @c We use @xseealso now because Texinfo introduced its own @seealso @c command. But instead of modifying all source files, we'll have the @c munge-texi script convert @seealso to @xseealso. @macro xseealso {args} @iftex @vskip 2pt @end iftex @ifnottex @end ifnottex @ifnotinfo @noindent @strong{See also:} \args\. @end ifnotinfo @ifinfo @noindent See also: \args\. @end ifinfo @end macro @c The following macro works around a situation where the Info/plain text @c expansion of the @code{XXX} macro is `XXX'. The use of the apostrophe @c can be confusing if the code segment itself ends with a transpose operator. @ifinfo @macro tcode{arg} \arg\ @end macro @end ifinfo @ifnotinfo @macro tcode{arg} @code{\arg\} @end macro @end ifnotinfo @c FIXME: someday, when Texinfo 5.X is standard, we might replace this with @c @backslashchar, which is a new addition to Texinfo. @macro xbackslashchar \\ @end macro @c These may be useful for all, not just for octave.texi. @tex \ifx\rgbDarkRed\thisisundefined \def\rgbDarkRed{0.50 0.09 0.12} \fi \ifx\linkcolor\thisisundefined \relax \else \global\def\linkcolor{\rgbDarkRed} \fi \ifx\urlcolor\thisisundefined \relax \else \global\def\urlcolor{\rgbDarkRed} \fi \ifx\urefurlonlylinktrue\thisisundefined \relax \else \global\urefurlonlylinktrue \fi @end tex @c Make the apostrophe in code examples cut-and-paste friendly. @codequoteundirected on arduino-0.12.1/doc/version.texi0000644000000000000000000000013514545566645013332 0ustar00@c autogenerated from Makefile @set VERSION 0.12.1 @set PACKAGE arduino @set DATE 2023-01-04 arduino-0.12.1/inst/0000755000000000000000000000000014545566645011163 5ustar00arduino-0.12.1/inst/+arduinoio/0000755000000000000000000000000014545566645013227 5ustar00arduino-0.12.1/inst/+arduinoio/+config/0000755000000000000000000000000014545566645014547 5ustar00arduino-0.12.1/inst/+arduinoio/+config/config_due.m0000644000000000000000000002062214545566645017031 0ustar00## Copyright (C) 2021 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} config_due (@var{initdata}) ## Private function for setting allowed modes of due board pins ## @end deftypefn function retval = config_due (initdata) retval = {}; # default board info - must be provided # will be filled in on connection. retval.board = ''; retval.baudrate = 9600; retval.mcu = 'cortex-m3'; retval.voltref = 3.3; retval.libs = {}; retval.port = ''; # info expected to be provided by config. retval.description = 'Arduino Due Board'; # pin config retval.pins = {}; retval.pins{end+1} = arduinoio.config.pin_info('D0', 0, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D1', 1, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D2', 2, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D3', 3, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D4', 4, { 'digital', 'pwm', 'interrupt' }); # D87 retval.pins{end+1} = arduinoio.config.pin_info('D5', 5, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D6', 6, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D7', 7, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D8', 8, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D9', 9, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D10', 10, { 'digital', 'pwm', 'interrupt' }); # D77 retval.pins{end+1} = arduinoio.config.pin_info('D11', 11, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D12', 12, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D13', 13, { 'digital', 'pwm' 'led_13', 'led', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D14', 14, { 'digital', 'uart3_tx', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D15', 15, { 'digital', 'uart3_rx', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D16', 16, { 'digital', 'uart2_tx', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D17', 17, { 'digital', 'uart2_rx', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D18', 18, { 'digital', 'uart1_tx', 'interrupt'}); retval.pins{end+1} = arduinoio.config.pin_info('D19', 19, { 'digital', 'uart1_tx', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D20', 20, { 'digital', 'i2c0_sda', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D21', 21, { 'digital', 'i2c0_scl', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D22', 22, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D23', 23, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D24', 24, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D25', 25, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D26', 26, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D27', 27, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D28', 28, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D29', 29, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D30', 30, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D31', 31, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D32', 32, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D33', 33, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D34', 34, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D35', 35, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D36', 36, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D37', 37, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D38', 38, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D39', 39, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D40', 40, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D41', 41, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D42', 42, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D43', 43, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D44', 44, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D45', 45, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D46', 46, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D47', 47, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D48', 48, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D49', 49, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D50', 50, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D51', 51, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D52', 52, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D53', 53, { 'digital', 'interrupt' }); # analogs retval.pins{end+1} = arduinoio.config.pin_info('A0', 54, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A1', 55, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A2', 56, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A3', 57, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A4', 58, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A5', 59, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A6', 60, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A7', 61, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A8', 62, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A9', 63, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A10', 64, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A11', 65, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('D66', 66, { 'digital' }); # DAC0 retval.pins{end+1} = arduinoio.config.pin_info('D67', 67, { 'digital' }); # DAC1 retval.pins{end+1} = arduinoio.config.pin_info('D68', 68, { 'digital' }); # CANRX retval.pins{end+1} = arduinoio.config.pin_info('D69', 69, { 'digital' }); # CANTX retval.pins{end+1} = arduinoio.config.pin_info('D70', 70, { 'digital', 'i2c1_sda' }); retval.pins{end+1} = arduinoio.config.pin_info('D71', 71, { 'digital', 'i2c1_scl' }); retval.pins{end+1} = arduinoio.config.pin_info('D72', 72, { 'digital', 'led_rxl' }); retval.pins{end+1} = arduinoio.config.pin_info('D73', 73, { 'digital', 'led_txl' }); retval.pins{end+1} = arduinoio.config.pin_info('D74', 74, { 'digital', 'spi_miso' }); retval.pins{end+1} = arduinoio.config.pin_info('D75', 75, { 'digital', 'spi_mosi' }); retval.pins{end+1} = arduinoio.config.pin_info('D76', 76, { 'digital', 'spi_sck' }); retval.pins{end+1} = arduinoio.config.pin_info('D77', 77, { 'digital', 'spi_ss' }); #retval.pins{end+1} = arduinoio.config.pin_info('D78', 78, { 'digital', 'spi_ss3' }); #retval.pins{end+1} = arduinoio.config.pin_info('D86', 86, { 'digital', 'spi_ss2' }); #retval.pins{end+1} = arduinoio.config.pin_info('D87', 87, { 'digital', 'spi_ss1' }); endfunction arduino-0.12.1/inst/+arduinoio/+config/config_esp32_dev.m0000644000000000000000000001536014545566645020051 0ustar00## Copyright (C) 2021 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} config_esp32_dev (@var{initdata}) ## Private function for setting allowed modes of esp board pins ## @end deftypefn # configuration generated from esp32/2.0.2/variants/esp32/pins_arduino.h function retval = config_esp32_dev (initdata) retval = {}; # default board info - must be provided # will be filled in on connection. retval.board = ''; retval.baudrate = 9600; retval.mcu = 'eps32'; retval.voltref = 0; retval.libs = {}; retval.port = ''; # info expected to be provided by config. retval.description = 'ESP32 Dev Module'; # pin config retval.pins = {}; retval.pins{end+1} = arduinoio.config.pin_info('D0', 0, { 'digital', 'pwm', 'interrupt', 'analog' }, {'a11'}); retval.pins{end+1} = arduinoio.config.pin_info('D1', 1, { 'digital', 'pwm', 'uart0_tx', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D2', 2, { 'digital', 'pwm', 'interrupt', 'led', 'analog' }, {'a12'}); retval.pins{end+1} = arduinoio.config.pin_info('D3', 3, { 'digital', 'pwm', 'uart0_rx', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D4', 4, { 'digital', 'pwm', 'interrupt', 'analog' }, {'a4'}); retval.pins{end+1} = arduinoio.config.pin_info('D5', 5, { 'digital', 'pwm', 'interrupt', 'spi_ss' }); # dont use #retval.pins{end+1} = arduinoio.config.pin_info('D6', 6, { 'digital', 'pwm', 'interrupt' }); #retval.pins{end+1} = arduinoio.config.pin_info('D7', 7, { 'digital', 'pwm', 'interrupt' }); #retval.pins{end+1} = arduinoio.config.pin_info('D8', 8, { 'digital', 'pwm', 'interrupt' }); #retval.pins{end+1} = arduinoio.config.pin_info('D9', 9, { 'digital', 'pwm', 'interrupt' }); #retval.pins{end+1} = arduinoio.config.pin_info('D10', 10, { 'digital', 'pwm', 'interrupt' }); #retval.pins{end+1} = arduinoio.config.pin_info('D11', 11, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D12', 12, { 'digital', 'pwm', 'interrupt', 'analog' }, {'a15'}); retval.pins{end+1} = arduinoio.config.pin_info('D13', 13, { 'digital', 'pwm', 'interrupt', 'analog' }, {'a14'}); retval.pins{end+1} = arduinoio.config.pin_info('D14', 14, { 'digital', 'pwm', 'interrupt', 'analog' }, {'a16'}); retval.pins{end+1} = arduinoio.config.pin_info('D15', 15, { 'digital', 'pwm', 'interrupt', 'analog' }, {'a13'}); retval.pins{end+1} = arduinoio.config.pin_info('D16', 16, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D17', 17, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D18', 18, { 'digital', 'pwm', 'interrupt', 'spi_sck' }); retval.pins{end+1} = arduinoio.config.pin_info('D19', 19, { 'digital', 'pwm', 'interrupt', 'spi_miso' }); #retval.pins{end+1} = arduinoio.config.pin_info('D20', 20, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D21', 21, { 'digital', 'pwm', 'interrupt', 'i2c_sda' }); retval.pins{end+1} = arduinoio.config.pin_info('D22', 22, { 'digital', 'pwm', 'interrupt', 'i2c_scl' }); retval.pins{end+1} = arduinoio.config.pin_info('D23', 23, { 'digital', 'pwm', 'interrupt', 'spi_mosi' }); #retval.pins{end+1} = arduinoio.config.pin_info('D24', 24, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D25', 25, { 'digital', 'pwm', 'interrupt', 'analog' }, {'a18'}); retval.pins{end+1} = arduinoio.config.pin_info('D26', 26, { 'digital', 'pwm', 'interrupt', 'analog' }, {'a19'}); retval.pins{end+1} = arduinoio.config.pin_info('D27', 27, { 'digital', 'pwm', 'interrupt', 'analog' }, {'a17'}); #retval.pins{end+1} = arduinoio.config.pin_info('D28', 28, { 'digital', 'pwm', 'interrupt' }); #retval.pins{end+1} = arduinoio.config.pin_info('D29', 29, { 'digital', 'pwm', 'interrupt' }); #retval.pins{end+1} = arduinoio.config.pin_info('D30', 30, { 'digital', 'pwm', 'interrupt' }); #retval.pins{end+1} = arduinoio.config.pin_info('D31', 31, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D32', 32, { 'digital', 'pwm', 'interrupt', 'analog' }, {'a4'}); retval.pins{end+1} = arduinoio.config.pin_info('D33', 33, { 'digital', 'pwm', 'interrupt', 'anolog' }, {'a5'}); retval.pins{end+1} = arduinoio.config.pin_info('D34', 34, { 'digital', 'analog' }, {'a6'}); retval.pins{end+1} = arduinoio.config.pin_info('D35', 35, { 'digital', 'analog' }, {'a7'}); retval.pins{end+1} = arduinoio.config.pin_info('D36', 36, { 'digital', 'analog' }, {'a0'}); retval.pins{end+1} = arduinoio.config.pin_info('D37', 37, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D38', 38, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D39', 39, { 'digital', 'analog' }, {'a3'}); %{ analog are in the digital pins retval.pins{end+1} = arduinoio.config.pin_info('A0', 40, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A1', 41, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A2', 42, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A3', 43, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A4', 44, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A5', 45, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A6', 46, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A7', 47, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A8', 48, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A9', 49, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A10', 50, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A11', 51, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A12', 52, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A13', 53, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A14', 54, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A15', 55, { 'digital', 'analog' }); %} endfunction arduino-0.12.1/inst/+arduinoio/+config/config_leonardo.m0000644000000000000000000000674514545566645020071 0ustar00## Copyright (C) 2019 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} config_leonardo (@var{initdata}) ## Private function for setting allowed modes of leonardo board pins ## @end deftypefn function retval = config_leonardo (initdata) retval = {}; # default board info - must be provided # will be filled in on connection. retval.board = 'leonardo'; retval.baudrate = 9600; retval.mcu = ''; retval.voltref = 0; retval.libs = {}; retval.port = ''; # info expected to be provided by config. retval.description = 'Arduino Leonardo Board'; # pin config retval.pins = {}; retval.pins{end+1} = arduinoio.config.pin_info('D0', 0, { 'digital', 'uart1_rx' }); retval.pins{end+1} = arduinoio.config.pin_info('D1', 1, { 'digital', 'uart1_tx' }); retval.pins{end+1} = arduinoio.config.pin_info('D2', 2, { 'digital', 'i2c_sda', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D3', 3, { 'digital', 'i2c_scl', 'interrupt', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D4', 4, { 'digital' }, {"A6"}); # share A6 retval.pins{end+1} = arduinoio.config.pin_info('D5', 5, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D6', 6, { 'digital', 'pwm' }, {"A7"}); # share A7 retval.pins{end+1} = arduinoio.config.pin_info('D7', 7, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D8', 8, { 'digital' }, {"A8"}); # share A8 retval.pins{end+1} = arduinoio.config.pin_info('D9', 9, { 'digital', 'pwm' }, {"A9"}); # share A9 retval.pins{end+1} = arduinoio.config.pin_info('D10', 10, { 'digital', 'pwm' }, {"A10"}); # share A10 retval.pins{end+1} = arduinoio.config.pin_info('D11', 11, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D12', 12, { 'digital' }, {"A11"}); retval.pins{end+1} = arduinoio.config.pin_info('D13', 13, { 'digital', 'led', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D14', 14, { 'digital', 'spi_miso' }); retval.pins{end+1} = arduinoio.config.pin_info('D15', 15, { 'digital', 'spi_sck' }); retval.pins{end+1} = arduinoio.config.pin_info('D16', 16, { 'digital', 'spi_mosi' }); retval.pins{end+1} = arduinoio.config.pin_info('D17', 17, { 'digital', 'spi_ss', 'led' }); retval.pins{end+1} = arduinoio.config.pin_info('A0', 18, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A1', 19, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A2', 20, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A3', 21, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A4', 22, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A5', 23, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('D30', 30, { 'digital', 'led' }); endfunction arduino-0.12.1/inst/+arduinoio/+config/config_lilypad.m0000644000000000000000000000416014545566645017711 0ustar00# configuration generated from /usr/share/arduino/hardware/arduino/avr/variants/standard/pins_arduino.h function retval = config_lilypad (initdata) retval = {}; # default board info - must be provided # will be filled in on connection. retval.board = ''; retval.baudrate = 9600; retval.mcu = ''; retval.voltref = 0; retval.libs = {}; retval.port = ''; # info expected to be provided by config. retval.description = 'lilypad arduino'; # pin config retval.pins = {}; retval.pins{end+1} = arduinoio.config.pin_info('D0', 0, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D1', 1, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D2', 2, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D3', 3, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D4', 4, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D5', 5, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D6', 6, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D7', 7, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D8', 8, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D9', 9, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D10', 10, { 'digital', 'spi_ss' }); retval.pins{end+1} = arduinoio.config.pin_info('D11', 11, { 'digital', 'spi_mosi' }); retval.pins{end+1} = arduinoio.config.pin_info('D12', 12, { 'digital', 'spi_miso' }); retval.pins{end+1} = arduinoio.config.pin_info('D13', 13, { 'digital', 'spi_sck', 'led' }); retval.pins{end+1} = arduinoio.config.pin_info('A0', 14, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A1', 15, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A2', 16, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A3', 17, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A4', 18, { 'digital', 'i2c_sda', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A5', 19, { 'digital', 'i2c_scl', 'analog' }); endfunction arduino-0.12.1/inst/+arduinoio/+config/config_mega2560.m0000644000000000000000000001566714545566645017517 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} config_mega (@var{initdata}) ## Private function for setting allowed modes of mega board pins ## @end deftypefn function retval = config_mega2560 (initdata) retval = []; # default board info - must be provided # will be filled in on connection. retval.board = ''; retval.baudrate = 9600; retval.mcu = ''; retval.voltref = 0; retval.libs = {}; retval.port = ''; # info expected to be provided by config. retval.description = 'Arduino Mega2560/1260 Board'; # pin config retval.pins = {}; retval.pins{end+1} = arduinoio.config.pin_info('D0', 0, { 'digital', 'uart' }); retval.pins{end+1} = arduinoio.config.pin_info('D1', 1, { 'digital', 'uart' }); retval.pins{end+1} = arduinoio.config.pin_info('D2', 2, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D3', 3, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D4', 4, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D5', 5, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D6', 6, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D7', 7, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D8', 8, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D9', 9, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D10', 10, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D11', 11, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D12', 12, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D13', 13, { 'digital', 'led', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D14', 14, { 'digital', 'uart3_tx' }); retval.pins{end+1} = arduinoio.config.pin_info('D15', 15, { 'digital', 'uart3_rx' }); retval.pins{end+1} = arduinoio.config.pin_info('D16', 16, { 'digital', 'uart2_tx' }); retval.pins{end+1} = arduinoio.config.pin_info('D17', 17, { 'digital', 'uart2_rx' }); retval.pins{end+1} = arduinoio.config.pin_info('D18', 18, { 'digital', 'uart1_tx', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D19', 19, { 'digital', 'uart1_rx', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D20', 20, { 'digital', 'i2c_sda', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D21', 21, { 'digital', 'i2c_scl', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D22', 22, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D23', 23, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D24', 24, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D25', 25, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D26', 26, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D27', 27, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D28', 28, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D29', 29, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D30', 30, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D31', 31, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D32', 32, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D33', 33, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D34', 34, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D35', 35, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D36', 36, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D37', 37, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D38', 38, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D39', 39, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D40', 40, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D41', 41, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D42', 42, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D43', 43, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D44', 44, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D45', 45, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D46', 46, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D47', 47, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D48', 48, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D49', 49, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D50', 50, { 'digital', 'spi_miso' }); retval.pins{end+1} = arduinoio.config.pin_info('D51', 51, { 'digital', 'spi_mosi' }); retval.pins{end+1} = arduinoio.config.pin_info('D52', 52, { 'digital', 'spi_sck' }); retval.pins{end+1} = arduinoio.config.pin_info('D53', 53, { 'digital', 'spi_ss' }); retval.pins{end+1} = arduinoio.config.pin_info('A0', 54, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A1', 55, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A2', 56, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A3', 57, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A4', 58, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A5', 59, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A6', 60, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A7', 61, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A8', 62, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A9', 63, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A10', 64, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A11', 65, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A12', 66, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A13', 67, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A14', 68, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A15', 69, { 'digital', 'analog' }); endfunction arduino-0.12.1/inst/+arduinoio/+config/config_micro.m0000644000000000000000000000657114545566645017374 0ustar00## Copyright (C) 2019 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} config_micro (@var{initdata}) ## Private function for setting allowed modes of micro board pins ## @end deftypefn function retval = config_micro (initdata) retval = {}; # default board info - must be provided # will be filled in on connection. retval.board = 'micro'; retval.baudrate = 9600; retval.mcu = ''; retval.voltref = 0; retval.libs = {}; retval.port = ''; # info expected to be provided by config. retval.description = 'Arduino Micro Board'; # pin config retval.pins = {}; retval.pins{end+1} = arduinoio.config.pin_info('D0', 0, { 'digital', 'uart1_rx' }); retval.pins{end+1} = arduinoio.config.pin_info('D1', 1, { 'digital', 'uart1_tx' }); retval.pins{end+1} = arduinoio.config.pin_info('D2', 2, { 'digital', 'i2c_sda', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D3', 3, { 'digital', 'i2c_scl', 'interrupt', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D4', 4, { 'digital' }, {"A6"}); # share A6 retval.pins{end+1} = arduinoio.config.pin_info('D5', 5, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D6', 6, { 'digital', 'pwm' }, {"A7"}); # share A7 retval.pins{end+1} = arduinoio.config.pin_info('D7', 7, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D8', 8, { 'digital' }, {"A8"}); # share A8 retval.pins{end+1} = arduinoio.config.pin_info('D9', 9, { 'digital', 'pwm' }, {"A9"}); # share A9 retval.pins{end+1} = arduinoio.config.pin_info('D10', 10, { 'digital', 'pwm' }, {"A10"}); # share A10 retval.pins{end+1} = arduinoio.config.pin_info('D11', 11, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D12', 12, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D13', 13, { 'digital', 'led', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D14', 14, { 'digital', 'spi_miso' }); retval.pins{end+1} = arduinoio.config.pin_info('D15', 15, { 'digital', 'spi_sck' }); retval.pins{end+1} = arduinoio.config.pin_info('D16', 16, { 'digital', 'spi_mosi' }); retval.pins{end+1} = arduinoio.config.pin_info('D17', 17, { 'digital', 'spi_ss', 'led' }); retval.pins{end+1} = arduinoio.config.pin_info('A0', 18, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A1', 19, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A2', 20, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A3', 21, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A4', 22, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A5', 23, { 'digital', 'analog' }); endfunction arduino-0.12.1/inst/+arduinoio/+config/config_mkr1000.m0000644000000000000000000000577714545566645017364 0ustar00# configuration generated from arduino/hardware/samd/1.8.11/variants/mkr1000/variant.h function retval = config_mkr1000 (initdata) retval = {}; # default board info - must be provided # will be filled in on connection. retval.board = ''; retval.baudrate = 9600; retval.mcu = 'cortex-m0plus'; retval.voltref = 3.3; retval.libs = {}; retval.port = ''; # info expected to be provided by config. retval.description = 'MKR 1000 Board'; # pin config retval.pins = {}; retval.pins{end+1} = arduinoio.config.pin_info('D0', 0, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D1', 1, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D2', 2, { 'digital', 'i2s_sck', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D3', 3, { 'digital', 'i2s_fs', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D4', 4, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D5', 5, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D6', 6, { 'digital', 'led', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D7', 7, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D8', 8, { 'digital', 'spi_mosi', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D9', 9, { 'digital', 'spi_sck' }); retval.pins{end+1} = arduinoio.config.pin_info('D10', 10, { 'digital', 'spi_miso', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D11', 11, { 'digital', 'i2c_sda' }); retval.pins{end+1} = arduinoio.config.pin_info('D12', 12, { 'digital', 'i2c_scl' }); retval.pins{end+1} = arduinoio.config.pin_info('D13', 13, { 'digital', 'uart1_rx' }); retval.pins{end+1} = arduinoio.config.pin_info('D14', 14, { 'digital', 'uart1_tx' }); retval.pins{end+1} = arduinoio.config.pin_info('A0', 15, { 'digital', 'analog', 'dac0' }, {"D15"}); retval.pins{end+1} = arduinoio.config.pin_info('A1', 16, { 'digital', 'analog', 'interrupt' }, {"D16"}); retval.pins{end+1} = arduinoio.config.pin_info('A2', 17, { 'digital', 'analog', 'interrupt' }, {"D17"}); retval.pins{end+1} = arduinoio.config.pin_info('A3', 18, { 'digital', 'analog', 'pwm' }, {"D18"}); retval.pins{end+1} = arduinoio.config.pin_info('A4', 19, { 'digital', 'analog', 'pwm' }, {"D19"}); retval.pins{end+1} = arduinoio.config.pin_info('A5', 20, { 'digital', 'analog' }, {"D20"}); retval.pins{end+1} = arduinoio.config.pin_info('A6', 21, { 'digital', 'analog' }, {"D21"}); retval.pins{end+1} = arduinoio.config.pin_info('D24', 24, { 'digital', 'spi_ss' }); # SPI connected to WINC1501B retval.pins{end+1} = arduinoio.config.pin_info('D26', 26, { 'digital', 'spi1_mosi' }); retval.pins{end+1} = arduinoio.config.pin_info('D27', 27, { 'digital', 'spi1_sck' }); retval.pins{end+1} = arduinoio.config.pin_info('D28', 28, { 'digital', 'spi1_ss' }); retval.pins{end+1} = arduinoio.config.pin_info('D29', 29, { 'digital', 'spi1_miso' }); endfunction arduino-0.12.1/inst/+arduinoio/+config/config_mkrzero.m0000644000000000000000000000723614545566645017753 0ustar00## Copyright (C) 2020 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} config_mkrzero (@var{initdata}) ## Private function for setting allowed modes of mkrzero board pins ## @end deftypefn # configuration generated from mkrzero/variant.h function retval = config_mkrzero (initdata) retval = {}; # default board info - must be provided # will be filled in on connection. retval.board = ''; retval.baudrate = 9600; retval.mcu = 'cortex-m0plus'; retval.voltref = 3.3; retval.libs = {}; retval.port = ''; # info expected to be provided by config. retval.description = 'MKR Zero Board'; # pin config retval.pins = {}; retval.pins{end+1} = arduinoio.config.pin_info('D0', 0, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D1', 1, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D2', 2, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D3', 3, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D4', 4, { 'digital', 'pwm', 'spi0_ss' }); retval.pins{end+1} = arduinoio.config.pin_info('D5', 5, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D6', 6, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D7', 7, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D8', 8, { 'digital', 'pwm', 'spi0_mosi' }); retval.pins{end+1} = arduinoio.config.pin_info('D9', 9, { 'digital', 'spi0_sck' }); retval.pins{end+1} = arduinoio.config.pin_info('D10', 10, { 'digital', 'pwm', 'spi0_miso' }); retval.pins{end+1} = arduinoio.config.pin_info('D11', 11, { 'digital', 'i2c_sda' }); retval.pins{end+1} = arduinoio.config.pin_info('D12', 12, { 'digital', 'pwm', 'i2c_scl' }); retval.pins{end+1} = arduinoio.config.pin_info('D13', 13, { 'digital', 'uart1_rx' }); retval.pins{end+1} = arduinoio.config.pin_info('D14', 14, { 'digital', 'uart1_tx' }); retval.pins{end+1} = arduinoio.config.pin_info('A0', 15, { 'digital', 'analog' }, {"D15"}); retval.pins{end+1} = arduinoio.config.pin_info('A1', 16, { 'digital', 'analog' }, {"D16"}); retval.pins{end+1} = arduinoio.config.pin_info('A2', 17, { 'digital', 'analog' }, {"D17"}); retval.pins{end+1} = arduinoio.config.pin_info('A3', 18, { 'digital', 'analog' }, {"D18"}); retval.pins{end+1} = arduinoio.config.pin_info('A4', 19, { 'digital', 'analog' }, {"D19"}); retval.pins{end+1} = arduinoio.config.pin_info('A5', 20, { 'digital', 'analog' }, {"D20"}); retval.pins{end+1} = arduinoio.config.pin_info('A6', 21, { 'digital', 'analog' }, {"D21"}); retval.pins{end+1} = arduinoio.config.pin_info('D26', 26, { 'digital', 'spi1_mosi' }); retval.pins{end+1} = arduinoio.config.pin_info('D27', 27, { 'digital', 'spi1_sck' }); retval.pins{end+1} = arduinoio.config.pin_info('D28', 28, { 'digital', 'spi1_ss' }); retval.pins{end+1} = arduinoio.config.pin_info('D29', 29, { 'digital', 'spi1_miso' }); retval.pins{end+1} = arduinoio.config.pin_info('D32', 32, { 'digital', 'led' }); endfunction arduino-0.12.1/inst/+arduinoio/+config/config_nano.m0000644000000000000000000000631014545566645017205 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} config_uno (@var{initdata}) ## Private function for setting allowed modes of uno board pins ## @end deftypefn # configuration generated from /usr/share/arduino/hardware/arduino/avr/variants/standard/pins_arduino.h function retval = config_nano (initdata) retval = []; # default board info - must be provided # will be filled in on connection retval.board = "nano"; retval.baudrate = 9600; retval.mcu = ''; retval.voltref = 50; retval.libs = {}; retval.port = ""; # info expected to be provided by config. retval.description = 'Arduino Nano Board'; # pin config retval.pins = {}; retval.pins{end+1} = arduinoio.config.pin_info("D0", 0, { 'digital' , 'uart'}); retval.pins{end+1} = arduinoio.config.pin_info("D1", 1, { 'digital' , 'uart'}); retval.pins{end+1} = arduinoio.config.pin_info("D2", 2, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info("D3", 3, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info("D4", 4, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info("D5", 5, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info("D6", 6, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info("D7", 7, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info("D8", 8, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info("D9", 9, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info("D10", 10, { 'digital', 'pwm', 'spi0_ss' }); retval.pins{end+1} = arduinoio.config.pin_info("D11", 11, { 'digital', 'pwm', 'spi0_mosi' }); retval.pins{end+1} = arduinoio.config.pin_info("D12", 12, { 'digital', 'pwm', 'spi0_miso' }); retval.pins{end+1} = arduinoio.config.pin_info("D13", 13, { 'digital', 'pwm', 'spi0_sck', 'led' }); retval.pins{end+1} = arduinoio.config.pin_info("A0", 14, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info("A1", 15, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info("A2", 16, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info("A3", 17, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info("A4", 18, { 'digital', 'analog', 'i2c_sda' }); retval.pins{end+1} = arduinoio.config.pin_info("A5", 19, { 'digital', 'analog', 'i2c_scl' }); retval.pins{end+1} = arduinoio.config.pin_info("A6", 20, { 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info("A7", 21, { 'analog' }); endfunction arduino-0.12.1/inst/+arduinoio/+config/config_nano_33_ble.m0000644000000000000000000000604714545566645020343 0ustar00# configuration generated from ARDUINO_NANO33BLE/pins_arduino.h function retval = config_nano_33_ble (initdata) retval = {}; # default board info - must be provided # will be filled in on connection. retval.board = 'nano_33_ble'; retval.baudrate = 9600; retval.mcu = 'nRF52840'; retval.voltref = 0; retval.libs = {}; retval.port = ''; # info expected to be provided by config. retval.description = 'Arduino Nano 33 BLE'; # pin config retval.pins = {}; retval.pins{end+1} = arduinoio.config.pin_info('D0', 0, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D1', 1, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D2', 2, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D3', 3, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D4', 4, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D5', 5, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D6', 6, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D7', 7, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D8', 8, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D9', 9, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D10', 10, { 'digital', 'spi_ss', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D11', 11, { 'digital', 'spi_mosi', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D12', 12, { 'digital', 'spi_miso', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D13', 13, { 'digital', 'led', 'spi_sck', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('A0', 14, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A1', 15, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A2', 16, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A3', 17, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A4', 18, { 'digital', 'analog', 'i2c0_sda' }); retval.pins{end+1} = arduinoio.config.pin_info('A5', 19, { 'digital', 'analog', 'i2c0_scl' }); retval.pins{end+1} = arduinoio.config.pin_info('A6', 20, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A7', 21, { 'digital', 'analog' }); # I/O tp on board chips retval.pins{end+1} = arduinoio.config.pin_info('D26', 26, { 'interrupt' }); # APDS int retval.pins{end+1} = arduinoio.config.pin_info('D27', 27, { 'digital' }); # PDM pwr retval.pins{end+1} = arduinoio.config.pin_info('D28', 28, { 'digital' }); # PDM clk retval.pins{end+1} = arduinoio.config.pin_info('D29', 29, { 'digital' }); # PDM din retval.pins{end+1} = arduinoio.config.pin_info('D30', 30, { 'i2c1_sda' }); retval.pins{end+1} = arduinoio.config.pin_info('D31', 31, { 'i2c1_scl' }); retval.pins{end+1} = arduinoio.config.pin_info('D32', 32, { 'digital' }); # enable i2c pullup retval.pins{end+1} = arduinoio.config.pin_info('D33', 33, { 'digital' }); # enable i2c 3.3v endfunction arduino-0.12.1/inst/+arduinoio/+config/config_nano_esp32.m0000644000000000000000000000703314545566645020224 0ustar00## Copyright (C) 2023 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} config_nano_esp32 (@var{initdata}) ## Private function for setting allowed modes of nano esp32 board pins ## @end deftypefn function retval = config_nano_esp32 (initdata) retval = []; # default board info - must be provided # will be filled in on connection retval.board = "nano_esp32"; retval.baudrate = 9600; retval.mcu = ''; retval.voltref = 33; retval.libs = {}; retval.port = ""; # info expected to be provided by config. retval.description = 'Arduino Nano ESP32 Board'; # pin config retval.pins = {}; retval.pins{end+1} = arduinoio.config.pin_info("D0", 0, { 'digital' , 'uart_rx'}); retval.pins{end+1} = arduinoio.config.pin_info("D1", 1, { 'digital' , 'uart_tx'}); retval.pins{end+1} = arduinoio.config.pin_info("D2", 2, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info("D3", 3, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info("D4", 4, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info("D5", 5, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info("D6", 6, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info("D7", 7, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info("D8", 8, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info("D9", 9, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info("D10", 10, { 'digital', 'pwm', 'spi0_ss', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info("D11", 11, { 'digital', 'pwm', 'spi0_mosi', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info("D12", 12, { 'digital', 'pwm', 'spi0_miso', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info("D13", 13, { 'digital', 'pwm', 'spi0_sck', 'led', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info("D14", 14, { 'digital', 'pwm', 'led_r', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info("D15", 15, { 'digital', 'pwm', 'led_g', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info("D16", 16, { 'digital', 'pwm', 'led_b', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info("A0", 17, { 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info("A1", 18, { 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info("A2", 19, { 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info("A3", 20, { 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info("A4", 21, { 'digital', 'analog', 'i2c_sda' }); retval.pins{end+1} = arduinoio.config.pin_info("A5", 22, { 'digital', 'analog', 'i2c_scl' }); retval.pins{end+1} = arduinoio.config.pin_info("A6", 23, { 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info("A7", 24, { 'analog' }); endfunction arduino-0.12.1/inst/+arduinoio/+config/config_nano_every.m0000644000000000000000000000620414545566645020421 0ustar00## Copyright (C) 2019 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} config_every (@var{initdata}) ## Private function for setting allowed modes of nano_every board pins ## @end deftypefn function retval = config_nano_every (initdata) retval = []; # default board info - must be provided # will be filled in on connection retval.board = "nano_every"; retval.baudrate = 9600; retval.mcu = ''; retval.voltref = 50; retval.libs = {}; retval.port = ""; # info expected to be provided by config. retval.description = 'Arduino Nano Every Board'; # pin config retval.pins = {}; retval.pins{end+1} = arduinoio.config.pin_info("D0", 0, { 'digital' , 'uart1_tx'}); retval.pins{end+1} = arduinoio.config.pin_info("D1", 1, { 'digital' , 'uart1_rx'}); retval.pins{end+1} = arduinoio.config.pin_info("D2", 2, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info("D3", 3, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info("D4", 4, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info("D5", 5, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info("D6", 6, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info("D7", 7, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info("D8", 8, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info("D9", 9, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info("D10", 10, { 'digital', 'pwm', 'spi0_ss' }); retval.pins{end+1} = arduinoio.config.pin_info("D11", 11, { 'digital', 'spi0_mosi' }); retval.pins{end+1} = arduinoio.config.pin_info("D12", 12, { 'digital', 'spi0_miso' }); retval.pins{end+1} = arduinoio.config.pin_info("D13", 13, { 'digital', 'spi0_sck', 'led' }); retval.pins{end+1} = arduinoio.config.pin_info("A0", 14, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info("A1", 15, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info("A2", 16, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info("A3", 17, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info("A4", 18, { 'digital', 'analog', 'i2c_sda' }); retval.pins{end+1} = arduinoio.config.pin_info("A5", 19, { 'digital', 'analog', 'i2c_scl' }); retval.pins{end+1} = arduinoio.config.pin_info("A6", 20, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info("A7", 21, { 'digital', 'analog' }); endfunction arduino-0.12.1/inst/+arduinoio/+config/config_nano_rp2040_connect.m0000644000000000000000000000650614545566645021734 0ustar00# configuration generated from mbed_nano/2.4.1/variants/NANO_RP2040_CONNECT/pins_arduino.h function retval = config_nano_rp2040_connect (initdata) retval = {}; # default board info - must be provided # will be filled in on connection. retval.board = ''; retval.baudrate = 9600; retval.mcu = 'cortex-m0plus'; retval.voltref = 0; retval.libs = {}; retval.port = ''; # info expected to be provided by config. retval.description = 'Arduino Nano RP2040 Connect'; # pin config retval.pins = {}; retval.pins{end+1} = arduinoio.config.pin_info('D0', 0, { 'digital', 'uart_tx' }); retval.pins{end+1} = arduinoio.config.pin_info('D1', 1, { 'digital', 'uart_rx' }); retval.pins{end+1} = arduinoio.config.pin_info('D2', 2, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D3', 3, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D4', 4, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D5', 5, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D6', 6, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D7', 7, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D8', 8, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D9', 9, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D10', 10, { 'digital', 'spi_ss', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D11', 11, { 'digital', 'spi_mosi', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D12', 12, { 'digital', 'spi_miso', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D13', 13, { 'digital', 'led', 'spi_sck', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('A0', 14, { 'digital', 'analog', 'pwm', 'interrupt' }, {'D14'}); retval.pins{end+1} = arduinoio.config.pin_info('A1', 15, { 'digital', 'analog', 'pwm', 'interrupt' }, {'D15'}); retval.pins{end+1} = arduinoio.config.pin_info('A2', 16, { 'digital', 'analog', 'pwm', 'interrupt' }, {'D16'}); retval.pins{end+1} = arduinoio.config.pin_info('A3', 17, { 'digital', 'analog', 'pwm', 'interrupt' }, {'D17'}); retval.pins{end+1} = arduinoio.config.pin_info('D18', 18, { 'digital', 'i2c_sda', 'analog' }, {'A4'}); retval.pins{end+1} = arduinoio.config.pin_info('D19', 19, { 'digital', 'i2c_scl', 'analog' }, {'A5'}); retval.pins{end+1} = arduinoio.config.pin_info('A6', 20, { 'analog' }, {'D20'}); retval.pins{end+1} = arduinoio.config.pin_info('A7', 21, { 'analog' }, {'D21'}); #retval.pins{end+1} = arduinoio.config.pin_info('D22', 22, { 'digital', 'pdm_din', 'pwm', 'interrupt' }); #retval.pins{end+1} = arduinoio.config.pin_info('D23', 23, { 'digital', 'pdm_clk', 'pwm', 'interrupt' }); #retval.pins{end+1} = arduinoio.config.pin_info('D24', 24, { 'digital' }); #retval.pins{end+1} = arduinoio.config.pin_info('D25', 25, { 'digital' }); #retval.pins{end+1} = arduinoio.config.pin_info('D26', 26, { 'digital' }); #retval.pins{end+1} = arduinoio.config.pin_info('D27', 27, { 'digital' }); #retval.pins{end+1} = arduinoio.config.pin_info('D28', 28, { 'digital' }); #retval.pins{end+1} = arduinoio.config.pin_info('D29', 29, { 'digital' }); endfunction arduino-0.12.1/inst/+arduinoio/+config/config_promicro.m0000644000000000000000000000707014545566645020110 0ustar00## Copyright (C) 2019-2021 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} config_promicro (@var{initdata}) ## Private function for setting allowed modes of promicro board pins ## @end deftypefn function retval = config_promicro (initdata) retval = {}; # default board info - must be provided # will be filled in on connection. retval.board = 'promicro'; retval.baudrate = 9600; retval.mcu = ''; retval.voltref = 0; retval.libs = {}; retval.port = ''; # info expected to be provided by config. retval.description = 'Arduino Pro Micro Board'; # pin config retval.pins = {}; retval.pins{end+1} = arduinoio.config.pin_info('D0', 0, { 'digital', 'uart1_rx' }); retval.pins{end+1} = arduinoio.config.pin_info('D1', 1, { 'digital', 'uart1_tx' }); retval.pins{end+1} = arduinoio.config.pin_info('D2', 2, { 'digital', 'i2c_sda', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D3', 3, { 'digital', 'i2c_scl', 'interrupt', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D4', 4, { 'digital' }, {"A6"}); # share A6 retval.pins{end+1} = arduinoio.config.pin_info('D5', 5, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D6', 6, { 'digital', 'pwm' }, {"A7"}); # share A7 retval.pins{end+1} = arduinoio.config.pin_info('D7', 7, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D8', 8, { 'digital' }, {"A8"}); # share A8 retval.pins{end+1} = arduinoio.config.pin_info('D9', 9, { 'digital', 'pwm' }, {"A9"}); # share A9 retval.pins{end+1} = arduinoio.config.pin_info('D10', 10, { 'digital', 'pwm' }, {"A10"}); # share A10 # retval.pins{end+1} = arduinoio.config.pin_info('D11', 11, { 'digital', 'pwm' }); # retval.pins{end+1} = arduinoio.config.pin_info('D12', 12, { 'digital' }); # retval.pins{end+1} = arduinoio.config.pin_info('D13', 13, { 'digital', 'led', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D14', 14, { 'digital', 'spi_miso' }); retval.pins{end+1} = arduinoio.config.pin_info('D15', 15, { 'digital', 'spi_sck' }); retval.pins{end+1} = arduinoio.config.pin_info('D16', 16, { 'digital', 'spi_mosi' }); retval.pins{end+1} = arduinoio.config.pin_info('D17', 17, { 'digital', 'spi_ss', 'led' }); retval.pins{end+1} = arduinoio.config.pin_info('A0', 18, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A1', 19, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A2', 20, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A3', 21, { 'digital', 'analog' }); # retval.pins{end+1} = arduinoio.config.pin_info('A4', 22, { 'digital', 'analog' }); # retval.pins{end+1} = arduinoio.config.pin_info('A5', 23, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('D24', 24, { 'digital' }); # A6 retval.pins{end+1} = arduinoio.config.pin_info('D30', 30, { 'digital', 'led' }); endfunction arduino-0.12.1/inst/+arduinoio/+config/config_promini.m0000644000000000000000000000665614545566645017744 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} config_promini (@var{initdata}) ## Private function for setting allowed modes of promini board pins ## @end deftypefn function retval = config_promini (initdata) retval = []; # default board info - must be provided # will be filled in on connection retval.board = "promini"; retval.baudrate = 9600; retval.mcu = ''; retval.voltref = 0; retval.libs = {}; retval.port = ""; # info expected to be provided by config. retval.description = 'Arduino Pro/Pro Mini Board'; # pin config retval.pins = {}; #0=D0 RX retval.pins{end+1} = arduinoio.config.pin_info("D0", 0, { 'digital' , 'uart'}); #1=D1 TX retval.pins{end+1} = arduinoio.config.pin_info("D1", 1, { 'digital' , 'uart'}); #2=D2 retval.pins{end+1} = arduinoio.config.pin_info("D2", 2, { 'digital', 'interrupt' }); #3=D3 PWM retval.pins{end+1} = arduinoio.config.pin_info("D3", 3, { 'digital', 'pwm', 'interrupt' }); #4=D4 retval.pins{end+1} = arduinoio.config.pin_info("D4", 4, { 'digital' }); #5=D5 PWM retval.pins{end+1} = arduinoio.config.pin_info("D5", 5, { 'digital', 'pwm' }); #6=D6 PWM retval.pins{end+1} = arduinoio.config.pin_info("D6", 6, { 'digital', 'pwm' }); #7=D7 retval.pins{end+1} = arduinoio.config.pin_info("D7", 7, { 'digital' }); #8=D8 retval.pins{end+1} = arduinoio.config.pin_info("D8", 8, { 'digital' }); #9=D9 PWM retval.pins{end+1} = arduinoio.config.pin_info("D9", 9, { 'digital', 'pwm' }); #10=D10 PWM SS retval.pins{end+1} = arduinoio.config.pin_info("D10", 10, { 'digital', 'pwm', 'spi0_ss' }); #11=D11 PWM MOSI retval.pins{end+1} = arduinoio.config.pin_info("D11", 11, { 'digital', 'pwm', 'spi0_mosi' }); #12=D12 MISO retval.pins{end+1} = arduinoio.config.pin_info("D12", 12, { 'digital', 'pwm', 'spi0_miso' }); #13=D13 SCK LED retval.pins{end+1} = arduinoio.config.pin_info("D13", 13, { 'digital', 'pwm', 'spi0_sck', 'led' }); #14=D14 A0 retval.pins{end+1} = arduinoio.config.pin_info("A0", 14, { 'digital', 'analog' }); #15=D15 A1 retval.pins{end+1} = arduinoio.config.pin_info("A1", 15, { 'digital', 'analog' }); #16=D16 A2 retval.pins{end+1} = arduinoio.config.pin_info("A2", 16, { 'digital', 'analog' }); #17=D17 A3 retval.pins{end+1} = arduinoio.config.pin_info("A3", 17, { 'digital', 'analog' }); #18=D18 A4 I2C_SDA retval.pins{end+1} = arduinoio.config.pin_info("A4", 18, { 'digital', 'analog', 'i2c_sda' }); #19=D19 A5 I2C_SCL retval.pins{end+1} = arduinoio.config.pin_info("A5", 19, { 'digital', 'analog', 'i2c_scl' }); #20=D20 A6 retval.pins{end+1} = arduinoio.config.pin_info("A6", 20, { 'digital', 'analog' }); #21=D21 A7 retval.pins{end+1} = arduinoio.config.pin_info("A7", 21, { 'digital', 'analog' }); endfunction arduino-0.12.1/inst/+arduinoio/+config/config_raspi_pico.m0000644000000000000000000000552214545566645020406 0ustar00# raspi pico 2040 # configuration generated from mbed_rp2040/2.2.0/variants/RASPBERRY_PI_PICO/pins_arduino.h function retval = config_raspi_pico (initdata) retval = {}; # default board info - must be provided # will be filled in on connection. retval.board = ''; retval.baudrate = 9600; retval.mcu = 'cortex-m0plus'; retval.voltref = 0; retval.libs = {}; retval.port = ''; # info expected to be provided by config. retval.description = 'Raspberry Pi Pico'; # pin config retval.pins = {}; retval.pins{end+1} = arduinoio.config.pin_info('D0', 0, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D1', 1, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D2', 2, { 'digital', 'spi_sck' }); retval.pins{end+1} = arduinoio.config.pin_info('D3', 3, { 'digital', 'spi_mosi' }); retval.pins{end+1} = arduinoio.config.pin_info('D4', 4, { 'digital', 'spi_miso' }); retval.pins{end+1} = arduinoio.config.pin_info('D5', 5, { 'digital', 'spi_ss' }); retval.pins{end+1} = arduinoio.config.pin_info('D6', 6, { 'digital', 'i2c_sda' }); retval.pins{end+1} = arduinoio.config.pin_info('D7', 7, { 'digital', 'i2c_scl' }); retval.pins{end+1} = arduinoio.config.pin_info('D8', 8, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D9', 9, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D10', 10, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D11', 11, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D12', 12, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D13', 13, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D14', 14, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D15', 15, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D16', 16, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D17', 17, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D18', 18, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D19', 19, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D20', 20, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D21', 21, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D22', 22, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D23', 23, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D24', 24, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D25', 25, { 'digital','led' }); retval.pins{end+1} = arduinoio.config.pin_info('A0', 26, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A1', 27, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A2', 28, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A3', 29, { 'digital', 'analog' }); endfunction arduino-0.12.1/inst/+arduinoio/+config/config_sparkfunsamd21.m0000644000000000000000000000724714545566645021125 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} config_sparkfunsamd21 (@var{initdata}) ## Private function for setting allowed modes of sparkfun samd21 mini/dev board pins ## @end deftypefn function retval = config_sparkfunsamd21 (initdata) retval = {}; # default board info - must be provided # will be filled in on connection. retval.board = ''; retval.baudrate = 9600; retval.mcu = 'samd21'; retval.voltref = 3.3; retval.libs = {}; retval.port = ''; # info expected to be provided by config. retval.description = 'Sparkfun SAMD21 Dev/Mini Board'; # pin config retval.pins = {}; retval.pins{end+1} = arduinoio.config.pin_info('D0', 0, { 'digital', 'i2s_fs', 'uart', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D1', 1, { 'digital', 'i2s_sck', 'uart', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D2', 2, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D3', 3, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D4', 4, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D5', 5, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D6', 6, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D7', 7, { 'digital', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D8', 8, { 'digital', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D9', 9, { 'digital', 'i2s_sd', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D10', 10, { 'digital', 'spi_ss', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D11', 11, { 'digital', 'spi_mosi', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D12', 12, { 'digital', 'spi_miso', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D13', 13, { 'digital', 'led_13', 'spi_sck', 'pwm', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('A0', 14, { 'digital', 'analog', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('A1', 15, { 'digital', 'analog', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('A2', 16, { 'digital', 'analog', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('A3', 17, { 'digital', 'analog', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('A4', 18, { 'digital', 'analog', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('A5', 19, { 'digital', 'analog', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D20', 20, { 'digital', 'i2c_sda', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D21', 21, { 'digital', 'i2c_scl', 'interrupt' }); # pins 22-24 ?? retval.pins{end+1} = arduinoio.config.pin_info('D25', 25, { 'digital', 'led_rxl', 'interrupt' }); retval.pins{end+1} = arduinoio.config.pin_info('D26', 26, { 'digital', 'led_txl', 'interrupt' }); endfunction arduino-0.12.1/inst/+arduinoio/+config/config_uno.m0000644000000000000000000000640014545566645017053 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} config_uno (@var{initdata}) ## Private function for setting allowed modes of uno board pins ## @end deftypefn function retval = config_uno (initdata) retval = []; # default board info - must be provided # will be filled in on connection retval.board = "uno"; retval.baudrate = 9600; retval.mcu = ''; retval.voltref = 0; retval.libs = {}; retval.port = ""; # info expected to be provided by config. retval.description = 'Arduino Uno R3 Board'; # pin config retval.pins = {}; #0=D0 RX retval.pins{end+1} = arduinoio.config.pin_info("D0", 0, { 'digital' , 'uart'}); #1=D1 TX retval.pins{end+1} = arduinoio.config.pin_info("D1", 1, { 'digital' , 'uart'}); #2=D2 retval.pins{end+1} = arduinoio.config.pin_info("D2", 2, { 'digital', 'interrupt' }); #3=D3 PWM retval.pins{end+1} = arduinoio.config.pin_info("D3", 3, { 'digital', 'pwm', 'interrupt' }); #4=D4 retval.pins{end+1} = arduinoio.config.pin_info("D4", 4, { 'digital' }); #5=D5 PWM retval.pins{end+1} = arduinoio.config.pin_info("D5", 5, { 'digital', 'pwm' }); #6=D6 PWM retval.pins{end+1} = arduinoio.config.pin_info("D6", 6, { 'digital', 'pwm' }); #7=D7 retval.pins{end+1} = arduinoio.config.pin_info("D7", 7, { 'digital' }); #8=D8 retval.pins{end+1} = arduinoio.config.pin_info("D8", 8, { 'digital' }); #9=D9 PWM retval.pins{end+1} = arduinoio.config.pin_info("D9", 9, { 'digital', 'pwm' }); #10=D10 PWM SS retval.pins{end+1} = arduinoio.config.pin_info("D10", 10, { 'digital', 'pwm', 'spi0_ss' }); #11=D11 PWM MOSI retval.pins{end+1} = arduinoio.config.pin_info("D11", 11, { 'digital', 'pwm', 'spi0_mosi' }); #12=D12 MISO retval.pins{end+1} = arduinoio.config.pin_info("D12", 12, { 'digital', 'pwm', 'spi0_miso' }); #13=D13 SCK LED retval.pins{end+1} = arduinoio.config.pin_info("D13", 13, { 'digital', 'pwm', 'spi0_sck', 'led' }); #14=D14 A0 retval.pins{end+1} = arduinoio.config.pin_info("A0", 14, { 'digital', 'analog' }); #15=D15 A1 retval.pins{end+1} = arduinoio.config.pin_info("A1", 15, { 'digital', 'analog' }); #16=D16 A2 retval.pins{end+1} = arduinoio.config.pin_info("A2", 16, { 'digital', 'analog' }); #17=D17 A3 retval.pins{end+1} = arduinoio.config.pin_info("A3", 17, { 'digital', 'analog' }); #18=D18 A4 I2C_SDA retval.pins{end+1} = arduinoio.config.pin_info("A4", 18, { 'digital', 'analog', 'i2c_sda' }); #19=D19 A5 I2C_SCL retval.pins{end+1} = arduinoio.config.pin_info("A5", 19, { 'digital', 'analog', 'i2c_scl' }); # additionals ? #20=D20 A6 #21=D21 A7 endfunction arduino-0.12.1/inst/+arduinoio/+config/config_uno_minima_r4.m0000644000000000000000000000425414545566645021017 0ustar00 function retval = config_uno_minima_r4 (initdata) retval = {}; retval.board = 'uno_minima_r4'; retval.baudrate = 9600; retval.mcu = ''; retval.voltref = 0; retval.libs = {}; retval.port = ''; # info expected to be provided by config. retval.description = 'Arduino Uno Minima R4 Board'; # pin config retval.pins = {}; retval.pins{end+1} = arduinoio.config.pin_info('D0', 0, { 'digital', 'uart_rx' }); retval.pins{end+1} = arduinoio.config.pin_info('D1', 1, { 'digital', 'uart_tx' }); retval.pins{end+1} = arduinoio.config.pin_info('D2', 2, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D3', 3, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D4', 4, { 'digital', 'can0_tx' }); retval.pins{end+1} = arduinoio.config.pin_info('D5', 5, { 'digital', 'can0_rx', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D6', 6, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D7', 7, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D8', 8, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D9', 9, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D10', 10, { 'digital', 'spi_ss', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D11', 11, { 'digital', 'spi_mosi', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D12', 12, { 'digital', 'spi_miso' }); retval.pins{end+1} = arduinoio.config.pin_info('D13', 13, { 'digital', 'led', 'spi_sck' }); retval.pins{end+1} = arduinoio.config.pin_info('A0', 14, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A1', 15, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A2', 16, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A3', 17, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A4', 18, { 'digital', 'analog', 'i2c_sda' }); retval.pins{end+1} = arduinoio.config.pin_info('A5', 19, { 'digital', 'analog' 'i2c_scl' }); retval.pins{end+1} = arduinoio.config.pin_info('D20', 20, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D21', 21, { 'digital' }); endfunction arduino-0.12.1/inst/+arduinoio/+config/config_uno_wifi_r2.m0000644000000000000000000001061214545566645020474 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} config_uno_wifi_r2 (@var{initdata}) ## Private function for setting allowed modes of uno board pins ## @end deftypefn function retval = config_uno_wifi_r2 (initdata) retval = []; # default board info - must be provided # will be filled in on connection retval.board = "uno_wifi_r2"; retval.baudrate = 9600; retval.mcu = ''; retval.voltref = 0; retval.libs = {}; retval.port = ""; # info expected to be provided by config. retval.description = 'Arduino Uno WIFI R2 Board'; # pin config retval.pins = {}; #0=D0 RX retval.pins{end+1} = arduinoio.config.pin_info("D0", 0, { 'digital' , 'uart'}); #1=D1 TX retval.pins{end+1} = arduinoio.config.pin_info("D1", 1, { 'digital' , 'uart'}); #2=D2 retval.pins{end+1} = arduinoio.config.pin_info("D2", 2, { 'digital', 'interrupt' }); #3=D3 PWM retval.pins{end+1} = arduinoio.config.pin_info("D3", 3, { 'digital', 'pwm', 'interrupt' }); #4=D4 retval.pins{end+1} = arduinoio.config.pin_info("D4", 4, { 'digital', 'interrupt' }); #5=D5 PWM retval.pins{end+1} = arduinoio.config.pin_info("D5", 5, { 'digital', 'pwm', 'interrupt' }); #6=D6 PWM retval.pins{end+1} = arduinoio.config.pin_info("D6", 6, { 'digital', 'pwm', 'interrupt' }); #7=D7 retval.pins{end+1} = arduinoio.config.pin_info("D7", 7, { 'digital', 'interrupt' }); #8=D8 retval.pins{end+1} = arduinoio.config.pin_info("D8", 8, { 'digital', 'interrupt' }); #9=D9 PWM retval.pins{end+1} = arduinoio.config.pin_info("D9", 9, { 'digital', 'pwm', 'interrupt' }); #10=D10 PWM SS retval.pins{end+1} = arduinoio.config.pin_info("D10", 10, { 'digital', 'pwm', 'interrupt' }); #11=D11 retval.pins{end+1} = arduinoio.config.pin_info("D11", 11, { 'digital', 'interrupt' }); #12=D12 retval.pins{end+1} = arduinoio.config.pin_info("D12", 12, { 'digital', 'interrupt' }); #13=D13 retval.pins{end+1} = arduinoio.config.pin_info("D13", 13, { 'digital', 'interrupt' }); #14=D14 A0 retval.pins{end+1} = arduinoio.config.pin_info("A0", 14, { 'digital', 'analog', 'interrupt' }, {"D14"}); #15=D15 A1 retval.pins{end+1} = arduinoio.config.pin_info("A1", 15, { 'digital', 'analog', 'interrupt' }, {"D15"}); #16=D16 A2 retval.pins{end+1} = arduinoio.config.pin_info("A2", 16, { 'digital', 'analog', 'interrupt' }, {"D16"}); #17=D17 A3 retval.pins{end+1} = arduinoio.config.pin_info("A3", 17, { 'digital', 'analog', 'interrupt' }, {"D17"}); #18=D18 A4 I2C_SDA retval.pins{end+1} = arduinoio.config.pin_info("A4", 18, { 'digital', 'analog', 'interrupt' }, {"D18"}); #19=D19 A5 I2C_SCL retval.pins{end+1} = arduinoio.config.pin_info("A5", 19, { 'digital', 'analog', 'interrupt' }, {"D19"}); # additionals ? #20=D20 retval.pins{end+1} = arduinoio.config.pin_info("D20", 20, { 'i2c_sda' }); #21=D21 retval.pins{end+1} = arduinoio.config.pin_info("D21", 21, { 'i2c_scl' }); retval.pins{end+1} = arduinoio.config.pin_info("D22", 22, { 'digital', 'spi0_ss' }); #25=D25 retval.pins{end+1} = arduinoio.config.pin_info("D25", 25, { 'digital', 'led' }); #26=D26 #retval.pins{end+1} = arduinoio.config.pin_info("D26", 26, { 'digital'}); #30=D30 retval.pins{end+1} = arduinoio.config.pin_info("D30", 30, { 'digital', 'imu_ss'}); #32=D32 retval.pins{end+1} = arduinoio.config.pin_info("D32", 32, { 'digital', 'spi0_mosi' }); #33=D33 retval.pins{end+1} = arduinoio.config.pin_info("D33", 33, { 'digital', 'spi0_miso' }); #34=D34 retval.pins{end+1} = arduinoio.config.pin_info("D34", 34, { 'digital', 'spi0_sck' }); #35=D35 retval.pins{end+1} = arduinoio.config.pin_info("D35", 35, { 'digital', 'wifi_ss' }); #39=D39 retval.pins{end+1} = arduinoio.config.pin_info("D39", 39, { 'digital' }); endfunction arduino-0.12.1/inst/+arduinoio/+config/config_uno_wifi_r4.m0000644000000000000000000000700014545566645020473 0ustar00## Copyright (C) 2023 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} config_uno_wifi_r4 (@var{initdata}) ## Private function for setting allowed modes of uno board pins ## @end deftypefn function retval = config_uno_wifi_r4 (initdata) retval = {}; retval.board = 'uno_wifi_r4'; retval.mcu = 'Renesis RA4M1'; retval.baudrate = 9600; retval.voltref = 0; retval.libs = {}; retval.port = ''; # info expected to be provided by config. retval.description = 'Arduino Uno WIFI R4 Board'; # pin config retval.pins = {}; retval.pins{end+1} = arduinoio.config.pin_info('D0', 0, { 'digital', 'uart2_tx' }); retval.pins{end+1} = arduinoio.config.pin_info('D1', 1, { 'digital', 'uart2_rx' }); retval.pins{end+1} = arduinoio.config.pin_info('D2', 2, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D3', 3, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D4', 4, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D5', 5, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D6', 6, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D7', 7, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D8', 8, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D9', 9, { 'digital', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D10', 10, { 'digital', 'spi_ss', 'can0_tx', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D11', 11, { 'digital', 'spi_mosi', 'pwm' }); retval.pins{end+1} = arduinoio.config.pin_info('D12', 12, { 'digital', 'spi_miso' }); retval.pins{end+1} = arduinoio.config.pin_info('D13', 13, { 'digital', 'led', 'spi_sck', 'can0_rx' }); retval.pins{end+1} = arduinoio.config.pin_info('A0', 14, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A1', 15, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A2', 16, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A3', 17, { 'digital', 'analog' }); retval.pins{end+1} = arduinoio.config.pin_info('A4', 18, { 'digital', 'analog', 'i2c_sda' }); retval.pins{end+1} = arduinoio.config.pin_info('A5', 19, { 'digital', 'analog', 'i2c_scl' }); retval.pins{end+1} = arduinoio.config.pin_info('D20', 20, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D21', 21, { 'digital' }); retval.pins{end+1} = arduinoio.config.pin_info('D22', 22, { 'uart1_tx' }); retval.pins{end+1} = arduinoio.config.pin_info('D23', 23, { 'uart1_rx' }); retval.pins{end+1} = arduinoio.config.pin_info('D24', 24, { 'uart3_tx' }); retval.pins{end+1} = arduinoio.config.pin_info('D25', 25, { 'uart3_rx' }); retval.pins{end+1} = arduinoio.config.pin_info('D26', 26, { 'i2c1_scl' }); retval.pins{end+1} = arduinoio.config.pin_info('D27', 27, { 'i2c1_sda' }); endfunction arduino-0.12.1/inst/+arduinoio/+config/pin_info.m0000644000000000000000000000174414545566645016534 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. see ## . ## -*- texinfo -*- ## @deftypefn {} {@var{value} =} pin_info (@var{name}) ## Private function ## @end deftypefn function retval = pin_info (name, id, modes, alt) retval = []; if (nargin < 4) alt = {}; endif retval.name = lower(name); retval.id = id; retval.modes = lower(modes); retval.owner = ""; retval.mode = "unset"; retval.altnames = lower(alt); endfunction arduino-0.12.1/inst/+arduinoio/AddonBase.m0000644000000000000000000000350414545566645015227 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . classdef AddonBase < handle ## -*- texinfo -*- ## @deftypefn {} {} arduinoio.AddonBase ## Base class used for arduino library sensors ## ## @seealso{arduinoio.LibraryBase} ## @end deftypefn ## ## @subheading Properties ## Base properties are expected to be inherited and overwritten in inherited classes. ## and are constant in order to query through the metaobject mechanism. ## ## @var{Parent} - parent librarybase object ## ## @subheading Methods ## @deftypefn {} {@var{ab} =} AddonBase () ## Constructor of base class ## ## @subsubheading Outputs ## The return value @var{ab} is an object of the arduinio.AddonBase class. ## ## @seealso{arduino, addon} ## @end deftypefn ## ## @deftypefn {} {} disp () ## Display the addon in a verbose way. ## @end deftypefn # properties that may be overridden in # subclasses properties (GetAccess = public, SetAccess = protected) Parent = {}; endproperties methods (Access=public) # display the base class properties function disp(this) printf(" addon %s\n", class(this)); endfunction endmethods endclassdef arduino-0.12.1/inst/+arduinoio/FilePath.m0000644000000000000000000000215614545566645015105 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} arduinoio.FilePath (@var{fullpathname}) ## Get the directory component of a pathname. ## ## @subsubheading Inputs ## @var{fullpathname} filepath to get directory component of. ## ## @subsubheading Outputs ## @var{retval} the directory part of the filename. ## @end deftypefn function path = FilePath(fullpathname) path = fileparts(fullpathname); endfunction arduino-0.12.1/inst/+arduinoio/LibFiles.m0000644000000000000000000000234014545566645015075 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{filelist} =} arduinoio.LibFiles () ## Get the list of files used for the building arduino library ## @subsubheading Outputs ## @var{filelist} - string cell array of files for the arduino project ## @end deftypefn function files = LibFiles() files = {}; script = mfilename('fullpath'); [path,~] = fileparts(script); filelist = dir(fullfile(path, "lib", "*.*")); for i=1:numel(filelist) files{end+1} = fullfile(fullfile(path, "lib"), filelist(i).name); endfor endfunction arduino-0.12.1/inst/+arduinoio/LibraryBase.m0000644000000000000000000001015114545566645015602 0ustar00## Copyright (C) 2018-2019 John Donoghue ## ## 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 ## . classdef LibraryBase < handle ## -*- texinfo -*- ## @deftypefn {} {} arduinoio.LibraryBase ## Base class used for arduino library plugins ## ## @seealso{arduino, listArduinoLibraries, addon} ## @end deftypefn ## ## @subheading Properties ## Base properties are expected to be inherited and overwritten in ## inherited classes and are constant in order to query through the ## metaobject mechanism. ## ## @var{LibraryName} - name of the addon library ## ## @var{DependentLibraries} - array of dependent library names that ## must be included when installing this plugin. ## ## @var{CppHeaderFile} - name (if any) of header file that will be ## included into the arduino project when adding this library. ## ## @var{CppSourceFile} - name (if any) of source file that will be ## included into the arduino project when adding this library. ## ## @var{CppClassName} - name of the cpp class for the addon library. ## project when adding this library. ## ## @var{Pins} - pins allocated to the addon ## ## @var{Parent} - parent arduino object. ## ## @subheading Methods ## @deftypefn {} {@var{lb} =} LibraryBase () ## Constructor of base class ## ## The constructor is usually not called but called indirectly ## from the addon function. ## ## @subsubheading Outputs ## The return value @var{lb} is an object of the arduinio.LibraryBase class. ## ## @seealso{arduino, listArduinoLibraries, addon} ## @end deftypefn ## ## @deftypefn {} {} disp () ## Display the addon in a verbose way. ## @end deftypefn # properties that may be overridden in # subclasses properties (Access = protected) LibraryName = ""; DependentLibraries = {}; ArduinoLibraryHeaderFiles = {}; CppHeaderFile = ""; CppSourceFile = ""; CppClassName = ""; endproperties properties (GetAccess = public, SetAccess = protected) Parent = {}; Pins = []; endproperties methods (Static) function info = AddonInfo(fullclassname) info = {}; info.libraryname = ""; info.dependentlibraries = ""; info.cppheaderfile = ""; info.cppsourcefile = ""; info.cppclassname = ""; info.arduinolibraryheaderfiles = ""; data = meta.class.fromName(fullclassname); for ic = 1:numel(data.Properties) p = data.Properties{ic}; if p.Constant pname = lower(p.Name); pvalue = p.DefaultValue; if isfield(info, pname) info.(pname) = pvalue; endif endif endfor info.classname = data.Name; endfunction endmethods methods (Access=public) # display the base class properties function disp(this) printf(" %s with properties\n", class(this)); if numel(this.Pins) == 0 printf(" Pins = {}\n"); else printf(" Pins = {\n"); for i=1:numel(this.Pins) if isnumeric(this.Pins{i}) printf(" %d\n", this.Pins{i}); else printf(" %s\n", this.Pins{i}); endif endfor printf(" }\n"); endif endfunction # overrides of arduino that matlab documentation indirectly # seems to indicate in the examples function [dataout, datasize] = sendCommand(this, varargin) [dataout, datasize] = sendCommand(this.Parent, varargin{:}) endfunction endmethods endclassdef arduino-0.12.1/inst/+arduinoio/boardTypeString.m0000644000000000000000000000416014545566645016526 0ustar00## Copyright (C) 2018-2021 John Donoghue ## ## 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. see ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} __boardTypeString__ (@var{type}) ## Helper function to set convert board id to a (lowercase) string ## @end deftypefn function retval = boardTypeString (id) if nargin != 1 error ('expected id'); endif if ~isnumeric (id) error ('expected id as a number'); endif if ischar (id) id = int (id); endif switch (id) case 0 retval = "uno"; case 1 retval = "mega2560"; case 2 retval = "nano"; case 5 retval = "uno_wifi_r2"; case 6 retval = "nano_every"; case 10 retval = "lilypad"; case 20 retval = "promini"; case 21 retval = "promicro"; case 22 retval = "leonardo"; case 23 retval = "micro"; #case 40 # retval = "zero"; case 41 retval = "sparkfunsamd21"; case 45 retval = "due"; case 50 retval = "mkrzero"; case 51 retval = "mkr1000"; case 60 retval = "nano_33_ble"; case 100 retval = "raspi_pico"; case 101 retval = "nano_rp2040_connect"; case 102 retval = "nano_esp32"; case 111 retval = "esp32_dev"; case 112 retval = "uno_wifi_r4"; case 113 retval = "uno_minima_r4"; otherwise retval = "unknown"; endswitch endfunction %!test %! assert(arduinoio.boardTypeString (0), "uno") %! assert(arduinoio.boardTypeString (1), "mega2560") %! assert(arduinoio.boardTypeString (10), "lilypad") %! assert(arduinoio.boardTypeString (-1), "unknown") arduino-0.12.1/inst/+arduinoio/getBoardConfig.m0000644000000000000000000000272014545566645016263 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} arduinoio.getBoardConfig (@var{boardname}) ## Return the configuration for a known arduino board type ## ## Function is used to get the expected pin/board configuration for a named board type ## which is used to verify and identify the functionality of the board. ## ## @subsubheading Inputs ## @var{boardname} - name of board to get configuration of ie: "uno" ## ## @subsubheading Outputs ## @var{retval} configuration struct. ## @end deftypefn function config = getBoardConfig (board) if strcmp(board, "unknown") error ("unknown board found type"); endif config = eval(sprintf("arduinoio.config.config_%s", board)); endfunction %!test %! c = arduinoio.getBoardConfig("uno"); %! assert(c.board, "uno"); arduino-0.12.1/inst/+arduinoio/lib/0000755000000000000000000000000014545566645013775 5ustar00arduino-0.12.1/inst/+arduinoio/lib/LibraryBase.cpp0000644000000000000000000002252114545566645016702 0ustar00/* * Octave arduino base library * Copyright (C) 2018 John Donoghue * * 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 . */ #include "LibraryBase.h" #include #include "settings.h" #define ARDUINO_SOH 0xA5 #define STATE_SOH 0 #define STATE_EXT 1 #define STATE_CMD 2 #define STATE_SIZE 3 #define STATE_DATA 4 #define STATE_EOM 5 #if defined(OCTAVE_USE_WIFI_COMMS) # if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_RENESAS) #include # else #include # endif char wifi_ssid[] = WIFI_SECRET_SSID; // your network SSID (name) char wifi_pass[] = WIFI_SECRET_PASS; int wifi_status = WL_IDLE_STATUS; WiFiServer wifiServer(WIFI_PORT); WiFiClient wifi_client; #endif #ifndef ARDUINO_BAUDRATE # define ARDUINO_BAUDRATE 9600 #endif // some standard(ish) error messages used throughout the addons const char ERRORMSG_INVALID_NUMBER_OF_ARGS[] PROGMEM = "Invalid number of args"; const char ERRORMSG_UNIMPLEMENTED[] PROGMEM = "Unimplemented feature"; const char ERRORMSG_INVALID_ARGS[] PROGMEM = "Invalid args"; const char ERRORMSG_INVALID_MODE[] PROGMEM = "Invalid mode"; const char ERRORMSG_INVALID_PIN[] PROGMEM = "Invalid pin"; const char ERRORMSG_INVALID_DEVICE[] PROGMEM = "Invalid device id"; static const char ERRORMSG_UNKNOWN_CMDID[] PROGMEM = "Unknown cmdID"; const char * OctaveLibraryBase::getLibraryName () const { return libName.c_str (); } void OctaveLibraryBase::setup () { } void OctaveLibraryBase::loop () { } void OctaveLibraryBase::commandHandler(byte cmdID, byte* inputs, unsigned int payload_size) { commandHandler((uint8_t)cmdID, (uint8_t*)inputs, (uint8_t)payload_size); } void OctaveLibraryBase::commandHandler(uint8_t cmdID, uint8_t* inputs, uint8_t payload_size) { sendErrorMsg_P(ERRORMSG_UNIMPLEMENTED); } void OctaveLibraryBase::sendResponseMsg (uint8_t cmdID, const uint8_t *data, uint8_t sz) { #if defined(OCTAVE_USE_WIFI_COMMS) if(wifi_status == 1) { wifi_client.write ((uint8_t)ARDUINO_SOH); wifi_client.write ((uint8_t)id); wifi_client.write (cmdID); wifi_client.write (sz); if(sz) { wifi_client.write (data, sz); } } #else OCTAVE_COMMS_PORT.write ((uint8_t)ARDUINO_SOH); OCTAVE_COMMS_PORT.write ((uint8_t)id); OCTAVE_COMMS_PORT.write (cmdID); OCTAVE_COMMS_PORT.write (sz); if(sz) { OCTAVE_COMMS_PORT.write (data, sz); } // flush appears to lockup port in some devices //OCTAVE_COMMS_PORT.flush (); #endif } void OctaveLibraryBase::sendWaitMsg () { sendResponseMsg (ARDUINO_WAIT, NULL, 0); } void OctaveLibraryBase::sendErrorMsg (const char *err) { // work out len to max 200 int len = 0; while(err[len] != '\0' && len < 200) len++; sendResponseMsg (ARDUINO_ERROR, (uint8_t *)err, len); } void OctaveLibraryBase::debugPrint (const char *err, ...) { char buffer[201]; va_list args; va_start (args, err); vsnprintf (buffer,200,err, args); va_end (args); // work out len to max 200 int len = 0; while(buffer[len] != '\0' && len < 200) len++; sendResponseMsg (ARDUINO_DEBUG, (uint8_t *)buffer, len); } void OctaveLibraryBase::sendResponseMsg_P (uint8_t cmdID, const uint8_t *data PROGMEM, uint8_t sz) { char tmp[256]; for (int i=0;ilibName.c_str (); } return ""; } uint8_t OctaveArduinoClass::registerLibrary (LibraryBase *lib) { if (libcount < MAX_ARDUINO_LIBS) { lib->id = libcount; libs[libcount] = lib; libcount ++; return libcount-1; } return 255; } uint8_t OctaveArduinoClass::processMessage (uint8_t libid, uint8_t cmd, uint8_t *data, uint8_t sz) { if (libid >= MAX_ARDUINO_LIBS || libs[libid] == 0) { if(libcount > 0) libs[0]->sendErrorMsg_P(ERRORMSG_UNIMPLEMENTED); } else { libs[libid]->commandHandler((byte)cmd, (byte *)data, (unsigned int)sz); return 1; } return 0; } #if defined(WIFI_STATIC_IP) static int get_ip_parts(const char *str, uint8_t parts[4]) { uint8_t i = 0; uint8_t o = 0; while(str[i] != '\0') { if(str[i] == '.') { o ++; if(o < 4) parts[o] = 0; } if(str[i] >= '0' && str[i] <= '9') { if(o < 4) parts[o] = parts[o]*10 + (str[i] - '0'); } i++; } return o; } static IPAddress make_ip_address(const char *str) { uint8_t parts[4]; get_ip_parts(str, parts); return IPAddress(parts[0], parts[1], parts[2], parts[3]); } static IPAddress make_gateway_address(const char *str) { uint8_t parts[4]; get_ip_parts(str, parts); return IPAddress(parts[0], parts[1], parts[2], 1); } #endif void OctaveArduinoClass::init () { OCTAVE_COMMS_PORT.begin (ARDUINO_BAUDRATE); #if defined(OCTAVE_USE_WIFI_COMMS) #ifdef ARDUINO_ARCH_ESP32 WiFi.begin(wifi_ssid, wifi_pass); #endif while(!OCTAVE_COMMS_PORT) {} #if defined(WIFI_STATIC_IP) #ifdef ARDUINO_ARCH_ESP32 WiFi.config(make_ip_address(WIFI_STATIC_IP), make_gateway_address(WIFI_STATIC_IP), IPAddress(255, 255, 0, 0)); #else WiFi.config(make_ip_address(WIFI_STATIC_IP)); #endif #endif while (wifi_status != WL_CONNECTED) { OCTAVE_COMMS_PORT.println("Attempting to connect to nework..."); ///Serial.println(ssid); // Connect to WPA/WPA2 network. Change this line if using open or WEP network: wifi_status = WiFi.begin(wifi_ssid, wifi_pass); // wait 5 seconds for connection: delay(5000); } // show some info about our connection OCTAVE_COMMS_PORT.println("Connected to network"); OCTAVE_COMMS_PORT.print("SSID: "); OCTAVE_COMMS_PORT.println(WiFi.SSID()); // print your WiFi shield's IP address: IPAddress ip = WiFi.localIP(); OCTAVE_COMMS_PORT.print("IP Address: "); OCTAVE_COMMS_PORT.println(ip); // print the received signal strength: long rssi = WiFi.RSSI(); OCTAVE_COMMS_PORT.print("signal strength (RSSI):"); OCTAVE_COMMS_PORT.print(rssi); OCTAVE_COMMS_PORT.println(" dBm"); wifi_status = 0; wifiServer.begin(); #endif for (int i=0; isetup (); } } void OctaveArduinoClass::runLoop() { int ch; #if defined(OCTAVE_USE_WIFI_COMMS) WiFiClient client = wifiServer.available(); if(client.connected()) { //wifi_client = wifiServer.available(); wifi_client = client; if(wifi_status == 0) { OCTAVE_COMMS_PORT.println("Connected"); wifi_status = 1; } } else if(wifi_status == 1 && !wifi_client.connected()) { OCTAVE_COMMS_PORT.println("Disconnected"); wifi_status = 0; } while(wifi_status == 1 && wifi_client.available()) { ch = wifi_client.read(); #else if (OCTAVE_COMMS_PORT.available()) { ch = OCTAVE_COMMS_PORT.read(); #endif switch (msg_state) { case STATE_SOH: msg_hdr[STATE_SOH] = ch; if (ch == ARDUINO_SOH) msg_state = STATE_EXT; break; case STATE_EXT: msg_hdr[STATE_EXT] = ch; msg_state = STATE_CMD; break; case STATE_CMD: msg_hdr[STATE_CMD] = ch; msg_state = STATE_SIZE; break; case STATE_SIZE: msg_hdr[STATE_SIZE] = ch; msg_datapos = 0; if (ch > 0) msg_state = STATE_DATA; else msg_state = STATE_EOM; break; case STATE_DATA: if (msg_datapos < sizeof(msg_data)) msg_data[msg_datapos] = ch; msg_datapos ++; if (msg_datapos == msg_hdr[STATE_SIZE]) msg_state = STATE_EOM; break; default: msg_state = STATE_SOH; break; } if(msg_state == STATE_EOM) { msg_state = STATE_SOH; processMessage (msg_hdr[STATE_EXT], msg_hdr[STATE_CMD], msg_data, msg_hdr[STATE_SIZE]); } } for (int i=0; iloop(); } } arduino-0.12.1/inst/+arduinoio/lib/LibraryBase.h0000644000000000000000000000575014545566645016354 0ustar00/* * Octave arduino library interface * Copyright (C) 2018-2022 John Donoghue * * 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 . */ #ifndef OCTAVE_LIBRARY_BASE_H #define OCTAVE_LIBRARY_BASE_H #include #define VERSION_MAJOR 0 #define VERSION_MINOR 12 #define VERSION_PATCH 1 #if defined(ARDUINO_SAM_DUE) # define OCTAVE_COMMS_PORT SERIAL_PORT_MONITOR #elif defined(SERIAL_PORT_USBVIRTUAL) // sparkfun samed21 dev/mini # define OCTAVE_COMMS_PORT SERIAL_PORT_USBVIRTUAL #elif defined(SERIAL_PORT_MONITOR) # define OCTAVE_COMMS_PORT SERIAL_PORT_MONITOR #else # define OCTAVE_COMMS_PORT Serial #endif class OctaveLibraryBase { public: String libName; int id; virtual void commandHandler(uint8_t cmdID, uint8_t* inputs, uint8_t payload_size); // matlab compatability virtual void commandHandler(byte cmdID, byte* inputs, unsigned int payload_size); virtual void setup(); virtual void loop(); const char * getLibraryName() const; #define ARDUINO_ERROR 255 #define ARDUINO_WAIT 254 #define ARDUINO_DEBUG 253 void sendResponseMsg(uint8_t cmdID, const uint8_t *data, uint8_t sz); void sendResponseMsg_P(uint8_t cmdID, const uint8_t *data PROGMEM, uint8_t sz); void sendErrorMsg(const char *msg); void sendErrorMsg_P(const char *msg PROGMEM); void sendUnknownCmdIDMsg(); void sendInvalidNumArgsMsg(); void sendWaitMsg(); void debugPrint(const char *, ...); }; typedef OctaveLibraryBase LibraryBase; class OctaveArduinoClass { uint8_t msg_state; uint8_t msg_datapos; uint8_t msg_hdr[4]; uint8_t msg_data[256]; #define MAX_ARDUINO_LIBS 20 int libcount; OctaveLibraryBase *libs[MAX_ARDUINO_LIBS]; public: OctaveArduinoClass(); uint8_t registerLibrary(LibraryBase *lib); int getLibCount() const { return libcount; } const char * getLibName(uint8_t idx) const; void init(); void runLoop(); private: uint8_t processMessage(uint8_t libid, uint8_t cmd, uint8_t *data, uint8_t sz); }; // for matlab compatability typedef OctaveArduinoClass MWArduinoClass; // error strings extern const char ERRORMSG_INVALID_NUMBER_OF_ARGS[] PROGMEM; extern const char ERRORMSG_INVALID_ARGS[] PROGMEM; extern const char ERRORMSG_INVALID_MODE[] PROGMEM; extern const char ERRORMSG_INVALID_PIN[] PROGMEM; extern const char ERRORMSG_UNIMPLEMENTED[] PROGMEM; extern const char ERRORMSG_INVALID_DEVICE[] PROGMEM; #endif // OCTAVE_LIBRARY_BASE_H arduino-0.12.1/inst/+arduinoio/lib/OctaveCoreLibrary.cpp0000644000000000000000000002405314545566645020064 0ustar00/* * Octave arduino core interface * Copyright (C) 2018-2019 John Donoghue * * 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 . */ #include "settings.h" #include "OctaveCoreLibrary.h" #if defined(ARDUINO_ARCH_ESP32) && ! defined(ARDUINO_NANO_ESP32) // contains analogWrite #include #endif #define ARDUINO_RESET 0 #define ARDUINO_INIT 1 #define ARDUINO_CONFIGPIN 2 #define ARDUINO_DIGITAL 3 #define ARDUINO_ANALOG 4 #define ARDUINO_PWM 5 #define ARDUINO_PLAYTONE 6 #define ARDUINO_GETLIB 8 #define ARDUINO_VERSION 20 #define ARDUINO_UPTIME 21 // endian flag #define ARDUINO_LITTLEENDIAN 0x00 #define ARDUINO_BIGENDIAN 0x80 #define ARDUINO_ENDIAN ARDUINO_LITTLEENDIAN // TODO: how know what board we are ??? //compiler provides something like: // -DF_CPU=16000000L -DARDUINO=10805 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR // freq ide ver board arch #if defined(ARDUINO_AVR_UNO) #define BOARD_ID 0 #elif defined(ARDUINO_AVR_MEGA2560) #define BOARD_ID 1 #elif defined(ARDUINO_AVR_NANO) #define BOARD_ID 2 #elif defined(ARDUINO_AVR_UNO_WIFI_REV2) #define BOARD_ID 5 #elif defined(ARDUINO_AVR_NANO_EVERY) #define BOARD_ID 6 #elif defined(ARDUINO_AVR_LILYPAD) #define BOARD_ID 10 #elif defined(ARDUINO_AVR_PRO) #define BOARD_ID 20 #elif defined(ARDUINO_AVR_PROMICRO) #define BOARD_ID 21 #elif defined(ARDUINO_AVR_LEONARDO) #define BOARD_ID 22 #elif defined(ARDUINO_AVR_MICRO) #define BOARD_ID 23 #elif defined(ARDUINO_SAMD_ZERO) // sparkfun samed21 dev/mini #if USB_VID == 0x1B4F && USB_PID == 0x8D21 #define BOARD_ID 41 #else // Arduino Zero #define BOARD_ID 40 #endif #elif defined(ARDUINO_SAM_DUE) #define BOARD_ID 45 #define NUM_TOTAL_PINS PINS_COUNT #elif defined(ARDUINO_SAMD_MKRZERO) #define BOARD_ID 50 #define NUM_TOTAL_PINS 33 #elif defined(ARDUINO_SAMD_MKR1000) #define BOARD_ID 51 #define NUM_TOTAL_PINS 30 #elif defined(ARDUINO_ARDUINO_NANO33BLE) #define BOARD_ID 60 #define NUM_TOTAL_PINS 34 #elif defined(ARDUINO_RASPBERRY_PI_PICO) #define BOARD_ID 100 #ifndef ARDUINO_ARCH_MBED #error "Expected mbed architechture" #endif #elif defined(ARDUINO_NANO_RP2040_CONNECT) #define BOARD_ID 101 #define BOARD_VOLTAGE 33 #ifndef ARDUINO_ARCH_MBED #error "Expected mbed architechture" #endif #elif defined(ARDUINO_NANO_ESP32) #define BOARD_ID 102 #define BOARD_VOLTAGE 33 #elif defined(ARDUINO_ESP32_DEV) #define BOARD_ID 111 #define BOARD_VOLTAGE 33 #elif defined(ARDUINO_UNOR4_WIFI) #define BOARD_ID 112 #elif defined(ARDUINO_UNOR4_MINIMA) #define BOARD_ID 113 #else #error "Unknown board type" #endif // board voltage = actualV*10 #ifndef BOARD_VOLTAGE #if defined(ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_NRF52840) || defined (ARDUINO_ARCH_SAM) || defined (ARDUINO_ARCH_RP2040) #define BOARD_VOLTAGE 33 #elif defined(ARDUINO_AVR_PRO) || defined(ARDUINO_AVR_PROMICRO) #if F_CPU == 8000000L #define BOARD_VOLTAGE 33 #else #define BOARD_VOLTAGE 50 #endif #else #define BOARD_VOLTAGE 50 #endif #endif static const int8_t map_config_mode[] PROGMEM = { INPUT, // unset INPUT, // analoginput INPUT, // dig in OUTPUT, // dig out INPUT_PULLUP, // pullup INPUT_PULLUP, //-1, // i2c TODO: ?? OUTPUT, // pwm OUTPUT, // servo OUTPUT, // spi TODO ? INPUT, // interrupt -1, // reserved }; int get_mode(uint8_t m) { if (m < sizeof (map_config_mode)) { return pgm_read_byte_near (map_config_mode + m); } return INPUT; } #define pinToAnalog(a) (a < A0 ? 0 : a-A0) #ifndef NUM_TOTAL_PINS #define NUM_TOTAL_PINS NUM_DIGITAL_PINS #endif //#ifdef UNO_WIFI_REV2_328MODE // #error ("Uno wifi firmware must be compiled without a 328 emultaion enabled") //#endif static uint8_t pinconfig[NUM_TOTAL_PINS]; #if defined (ARDUINO_ARCH_AVR) || defined (ARDUINO_ARCH_MEGAAVR) #include void reset () { wdt_enable (WDTO_1S); while(1) {} } #elif defined (ARDUINO_ARCH_SAMD) || defined (ARDUINO_ARCH_NRF52840) || defined (ARDUINO_ARCH_SAM) || defined (ARDUINO_ARCH_RP2040) || defined(ARDUINO_ARCH_RENESAS) void reset () { // processor software reset NVIC_SystemReset (); } #elif defined (ARDUINO_ARCH_ESP32) void reset () { ESP.restart (); } #else #error("Unimplemented architecture for reset") #endif OctaveCoreLibrary::OctaveCoreLibrary (OctaveArduinoClass &oc) : occlass (oc) { libName = "Core"; oc.registerLibrary (this); // set pins as not set for(unsigned int i = 0; i= sizeof(map_config_mode)) { sendErrorMsg_P (ERRORMSG_INVALID_MODE); } else if (datasz >= 1 && data[0] >= NUM_TOTAL_PINS) { sendErrorMsg_P (ERRORMSG_INVALID_PIN); } else if (datasz == 2 && data[0] < NUM_TOTAL_PINS && data[1] < sizeof(map_config_mode)) { int mode = get_mode (data[1]); pinconfig[data[0]] = data[1]; if (mode != -1) { pinMode (data[0], mode); } sendResponseMsg (cmdID, data, 0); } else { sendInvalidNumArgsMsg (); } break; case ARDUINO_DIGITAL: if (datasz == 1) { val = digitalRead (data[0]); if (val == HIGH) data[1] = 1; else data[1] = 0; sendResponseMsg (cmdID, data, 2); } else if (datasz == 2) { digitalWrite (data[0], data[1] ? HIGH : LOW); sendResponseMsg (cmdID, data, 0); } else { sendInvalidNumArgsMsg (); } break; case ARDUINO_ANALOG: if (datasz == 1) { val = analogRead (pinToAnalog(data[0])); data[1] = (val>>8)&0xff; data[2] = (val)&0xff; sendResponseMsg (cmdID, data, 3); } else { sendInvalidNumArgsMsg (); } break; case ARDUINO_PWM: if (datasz == 2) { analogWrite (data[0], data[1]); sendResponseMsg (cmdID, data, 0); } else { sendInvalidNumArgsMsg (); } break; case ARDUINO_PLAYTONE: if (datasz == 5) { #if defined(ARDUINO_SAM_DUE) sendErrorMsg_P (ERRORMSG_UNIMPLEMENTED); #else // 0 = pin // 1 = freqh // 2 = freql (hz) // 3 = durh // 4 = durl (10ths of second) unsigned long duration = (((unsigned long)(data[3]))<<8 | data[4]) * 100; unsigned int freq = (((unsigned int)(data[1]))<<8 | data[2]); if (freq == 0) noTone (data[0]); else tone (data[0], freq, duration); sendResponseMsg (cmdID, data, 0); #endif } else { sendInvalidNumArgsMsg (); } break; case ARDUINO_VERSION: { data[0] = VERSION_MAJOR; data[1] = VERSION_MINOR; data[2] = VERSION_PATCH; sendResponseMsg (cmdID, data, 3); } break; case ARDUINO_UPTIME: { unsigned long t = millis (); data[0] = (t>>24)&0xff; data[1] = (t>>16)&0xff; data[2] = (t>>8)&0xff; data[3] = (t>>0)&0xff; sendResponseMsg (cmdID, data, 4); } break; default: sendUnknownCmdIDMsg (); break; } } arduino-0.12.1/inst/+arduinoio/lib/OctaveCoreLibrary.h0000644000000000000000000000174114545566645017530 0ustar00/* * Octave arduino core interface * Copyright (C) 2018 John Donoghue * * 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 . */ #include "LibraryBase.h" class OctaveCoreLibrary : public LibraryBase { OctaveArduinoClass &occlass; public: OctaveCoreLibrary(OctaveArduinoClass &oc); void commandHandler(uint8_t cmdID, uint8_t* inputs, uint8_t payload_size); }; arduino-0.12.1/inst/+arduinoio/lib/OctaveI2CLibrary.cpp0000644000000000000000000002704614545566645017556 0ustar00/* * Octave arduino i2c interface * Copyright (C) 2018 John Donoghue * * 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 . */ #include "settings.h" #include "OctaveI2CLibrary.h" #define ARDUINO_SCANI2C 0 #define ARDUINO_CONFIGI2C 1 // replaces below as diff data format //#define ARDUINO_WRITEI2C 2 //#define ARDUINO_READI2C 3 //#define ARDUINO_WRITEI2CREG 4 //#define ARDUINO_READI2CREG 5 // new ids as new data #define ARDUINO_WRITEI2C 6 #define ARDUINO_READI2C 7 #define ARDUINO_WRITEI2CREG 8 #define ARDUINO_READI2CREG 9 #ifdef USE_I2C #include static uint8_t i2c_enabled[2] = { false, false }; static uint8_t i2c_address = 0; #if !defined(WIRE_INTERFACES_COUNT) # if defined(ARDUINO_ARDUINO_NANO33BLE) # define WIRE_INTERFACES_COUNT 2 # else # if defined(WIRE_HOWMANY) # define WIRE_INTERFACES_COUNT WIRE_HOWMANY # else # define WIRE_INTERFACES_COUNT 1 # endif # endif #endif #if !defined(ARDUINO_ARCH_ESP32) #define I2C_SUPPORTS_ENDCALL 1 #endif #endif OctaveI2CLibrary::OctaveI2CLibrary (OctaveArduinoClass &oc) { libName = "I2C"; oc.registerLibrary (this); } void OctaveI2CLibrary::commandHandler (uint8_t cmdID, uint8_t* data, uint8_t datasz) { switch (cmdID) { #ifdef USE_I2C case ARDUINO_WRITEI2C: case ARDUINO_WRITEI2CREG: { if (datasz < 3 || datasz > 32) { // bus // address // data sendInvalidNumArgsMsg (); } else { if (data[0] >= WIRE_INTERFACES_COUNT || data[0] > 1) { sendErrorMsg_P (ERRORMSG_INVALID_DEVICE); return; } if (data[0] == 0) { Wire.beginTransmission (data[1]); // should be i2c_address byte c; for(c=2;c 1 if (data[0] == 1) { Wire1.beginTransmission (data[1]); // should be i2c_address byte c; for(c=2;c= WIRE_INTERFACES_COUNT || data[0] > 1) { sendErrorMsg_P (ERRORMSG_INVALID_DEVICE); return; } if (data[0] == 0) { Wire.requestFrom (data[1], (size_t)data[2]); byte c = 0; byte l = data[2]; if (l > 5) sendWaitMsg (); datasz = 1; for (c=0;c<=l;c++) { if (Wire.available ()) { data[datasz] = Wire.read (); datasz ++; } } } #if WIRE_INTERFACES_COUNT > 1 if (data[0] == 1) { Wire1.requestFrom (data[1], (size_t)data[2]); byte c = 0; byte l = data[2]; if (l > 5) sendWaitMsg (); datasz = 1; for (c=0;c<=l;c++) { if (Wire1.available ()) { data[datasz] = Wire1.read (); datasz ++; } } } #endif sendResponseMsg (cmdID,data, datasz); } break; } case ARDUINO_READI2CREG: { if (datasz < 5) { // bus // address // regsz // reg // numbytes sendInvalidNumArgsMsg (); } else if (datasz != data[2]+4) { sendInvalidNumArgsMsg (); } else { if (data[0] >= WIRE_INTERFACES_COUNT || data[0] > 1) { sendErrorMsg_P (ERRORMSG_INVALID_DEVICE); return; } if (data[0] == 0) { Wire.beginTransmission (data[1]); byte c = 0; for (c=0;c 5) sendWaitMsg (); datasz = 2; for (c=0;c<=l;c++) { if (Wire.available ()) { data[datasz] = Wire.read (); datasz ++; } } } #if WIRE_INTERFACES_COUNT > 1 if (data[0] == 1) { Wire1.beginTransmission (data[1]); byte c = 0; for (c=0;c 5) sendWaitMsg (); datasz = 2; for (c=0;c<=l;c++) { if (Wire1.available ()) { data[datasz] = Wire1.read (); datasz ++; } } } #endif sendResponseMsg (cmdID,data, datasz); } break; } case ARDUINO_SCANI2C: { if (datasz != 2) { sendInvalidNumArgsMsg (); } else { byte error = 1; // bus 0 // address if (data[0] >= WIRE_INTERFACES_COUNT || data[0] > 1) { sendErrorMsg_P (ERRORMSG_INVALID_DEVICE); return; } if (!i2c_enabled[data[0]]) { if(data[0] == 0) Wire.begin (); #if WIRE_INTERFACES_COUNT > 1 if(data[0] == 1) Wire1.begin (); #endif } if (data[0] == 0) { Wire.beginTransmission (data[1]); error = Wire.endTransmission (); } #if WIRE_INTERFACES_COUNT > 1 if (data[0] == 1) { Wire1.beginTransmission (data[1]); error = Wire1.endTransmission (); } #endif if (error == 0) data[2] = 1; else data[2] = 0; if (!i2c_enabled[data[0]]) { #if defined (I2C_SUPPORTS_ENDCALL) if(data[0] == 0) Wire.end (); # if WIRE_INTERFACES_COUNT > 1 if(data[0] == 1) Wire1.end (); # endif #endif } sendResponseMsg (cmdID, data, 3); } break; } case ARDUINO_CONFIGI2C: { if (datasz == 2 || datasz == 3 || datasz == 5) { // i2c bus 0 // enable 1 // i2caddress (optional) // bitratehi // birtarelo if (data[0] >= WIRE_INTERFACES_COUNT || data[0] > 1) { sendErrorMsg_P (ERRORMSG_INVALID_DEVICE); return; } // enable if (data[1] == 1) { i2c_enabled[data[0]] = 1; if (data[0] == 0) { // TODO: i dont think need any more as setting i2c as pullup inputs before making it i2c #if defined(ARDUINO_AVR_NANO_EVERY) || defined (ARDUINO_NANO_RP2040_CONNECT) // arduino every A4,A5 pin is connected to 2 pins each on the micro controller // so need ensure that the non I2C pins are pulled hi so doesnt effect the i2c pins pinMode(18, INPUT_PULLUP); pinMode(19, INPUT_PULLUP); #endif } if (datasz>= 3) i2c_address = data[2]; else i2c_address = 0; if (data[0] == 0) { if (i2c_address > 0) Wire.begin (i2c_address); else Wire.begin (); if (datasz == 5) { int32_t bitrate = (((uint32_t)data[3])<<8) | ((uint32_t)data[4]); Wire.setClock (bitrate*1000L); } } #if WIRE_INTERFACES_COUNT > 1 if (data[0] == 1) { if (i2c_address > 0) Wire1.begin (i2c_address); else Wire1.begin (); if (datasz == 5) { int32_t bitrate = (((uint32_t)data[3])<<8) | ((uint32_t)data[4]); Wire1.setClock (bitrate*1000L); } } #endif } else { // disable #if defined (I2C_SUPPORTS_ENDCALL) if (data[0] == 0) Wire.end (); # if WIRE_INTERFACES_COUNT > 1 if (data[0] == 1) Wire1.end (); # endif #endif i2c_enabled[data[0]] = 0; } sendResponseMsg (cmdID, data, datasz); } else if (datasz == 1) { // query config of device // i2c id // enable // address if (data[0] >= WIRE_INTERFACES_COUNT || data[0] > 1) { sendErrorMsg_P (ERRORMSG_INVALID_DEVICE); return; } data[1] = i2c_enabled[data[0]]; data[2] = i2c_address; sendResponseMsg (cmdID,data, 3); } else { sendInvalidNumArgsMsg (); } break; } #endif default: sendUnknownCmdIDMsg (); break; } } arduino-0.12.1/inst/+arduinoio/lib/OctaveI2CLibrary.h0000644000000000000000000000167714545566645017225 0ustar00/* * Octave arduino i2c interface * Copyright (C) 2018 John Donoghue * * 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 . */ #include "LibraryBase.h" class OctaveI2CLibrary : public LibraryBase { public: OctaveI2CLibrary(OctaveArduinoClass &oc); void commandHandler(uint8_t cmdID, uint8_t* inputs, uint8_t payload_size); }; arduino-0.12.1/inst/+arduinoio/lib/OctaveRotaryEncoderLibrary.cpp0000644000000000000000000001536214545566645021757 0ustar00/* * Octave arduino encoder interface * Copyright (C) 2018 John Donoghue * * 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 . */ #include "settings.h" #include "OctaveRotaryEncoderLibrary.h" #define ARDUINO_RESET_ENCODER 0 #define ARDUINO_CONFIG_ENCODER 1 #define ARDUINO_READPOS_ENCODER 2 #define ARDUINO_READSPEED_ENCODER 3 #ifdef USE_ROTARYENCODER static const char ERRORMSG_CANT_READ[] PROGMEM = "Max encoder reached"; static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0}; #define MAX_ROTARYENCODERS 8 class RotaryEncoder { #define USED 1 #define POLL 2 public: uint8_t flags; uint8_t pins[2]; int16_t cnt; int16_t oldcnt; uint16_t speed; uint8_t state; RotaryEncoder(); uint8_t init (uint8_t p1, uint8_t p2); uint8_t free() { flags = 0; return 0;} uint16_t readCount (); uint16_t readSpeed (); uint8_t resetCount (uint8_t h=0, uint8_t l=0); void poll (); void process (unsigned long diff); }; RotaryEncoder::RotaryEncoder () { flags = 0; } uint8_t RotaryEncoder::init (uint8_t p1, uint8_t p2) { flags = USED | POLL; state = 0; cnt = 0; oldcnt = 0; pins[0] = p1; pins[1] = p2; pinMode (pins[0], INPUT); digitalWrite (pins[0], HIGH); pinMode (pins[1], INPUT); digitalWrite (pins[1], HIGH); return 0; } uint16_t RotaryEncoder::readCount () { return cnt; } uint16_t RotaryEncoder::readSpeed () { return speed; } uint8_t RotaryEncoder::resetCount (uint8_t h, uint8_t l) { uint16_t v= ((uint16_t)h)<<8 | l; cnt = (int16_t)v; oldcnt = cnt; return 0; } void RotaryEncoder::poll () { // get curr state and prev state - gives 16 possible outcomes // wheich can then do a lookup table for detection state = (state<<2) | (digitalRead(pins[1]) ? 2 : 0) | (digitalRead(pins[0]) ? 1 : 0); int8_t dir = enc_states[state&0xf]; if(dir < 0 && cnt > -32000) cnt += dir; if(dir > 0 && cnt < 32000) cnt += dir; } void RotaryEncoder::process (unsigned long t) { //input millis long s = ((cnt - oldcnt) * 1000) / t; if(s < 0) s = -s; if(s > 32000) s = 32000; if(s != 0) speed = s; else if(speed > 0) speed --; oldcnt = cnt; } static RotaryEncoder encoders[MAX_ROTARYENCODERS]; RotaryEncoder * getRotaryEncoder (uint8_t id) { uint8_t i; RotaryEncoder * unused = 0; for (i=0;iinit(data[0], data[2]); sendResponseMsg (cmdID, data, 2); } // free else if (data[1] == 0 && reg->flags && datasz == 2) { reg->free (); sendResponseMsg (cmdID, data, 2); } else { sendErrorMsg_P (ERRORMSG_INVALID_ARGS); } } else { sendErrorMsg_P (ERRORMSG_INVALID_ARGS); } break; } case ARDUINO_RESET_ENCODER: { // 0 = id (currently using the datapin id) RotaryEncoder * reg = getRotaryEncoder(data[0]); if(reg && reg->flags) { data[1] = reg->resetCount (data[1], data[2]); sendResponseMsg (cmdID,data, 2); } else { sendErrorMsg_P (ERRORMSG_INVALID_ARGS); } break; } case ARDUINO_READPOS_ENCODER: { // 0 = id // 1 = reset flag RotaryEncoder * reg = getRotaryEncoder (data[0]); if(reg && reg->flags && datasz == 2) { uint16_t v = reg->readCount (); if (data[1] == 1) reg->resetCount(); data[1] = (v>>8)&0xff; data[2] = (v)&0xff; unsigned long t = millis (); data[3] = (t>>24)&0xff; data[4] = (t>>16)&0xff; data[5] = (t>>8)&0xff; data[6] = (t)&0xff; datasz = 7; sendResponseMsg (cmdID, data, datasz); } else { sendErrorMsg_P (ERRORMSG_INVALID_ARGS); } break; } case ARDUINO_READSPEED_ENCODER: { // 0 = id RotaryEncoder * reg = getRotaryEncoder (data[0]); if(reg && reg->flags && datasz == 1) { uint16_t v = reg->readSpeed (); datasz = 3; data[1] = (v>>8)&0xff; data[2] = (v)&0xff; sendResponseMsg (cmdID, data, datasz); } else { sendErrorMsg_P (ERRORMSG_INVALID_ARGS); } break; } #endif default: sendUnknownCmdIDMsg (); break; } } void OctaveRotaryEncoderLibrary::loop () { #ifdef USE_ROTARYENCODER static unsigned long speedtime = 0; unsigned long newtime; // any thing that needs poll for (int i=0; iflags & POLL) { enc->poll(); } } // do any periodic processing newtime = millis(); if (speedtime < newtime) { unsigned long diff = (newtime - speedtime); if (diff > 50) { speedtime = newtime; for (int i=0; iflags) enc->process(diff); } } } else if (speedtime > newtime) { speedtime = newtime; } #endif } arduino-0.12.1/inst/+arduinoio/lib/OctaveRotaryEncoderLibrary.h0000644000000000000000000000176714545566645021430 0ustar00/* * Octave arduino shift register interface * Copyright (C) 2018 John Donoghue * * 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 . */ #include "LibraryBase.h" class OctaveRotaryEncoderLibrary : public LibraryBase { public: OctaveRotaryEncoderLibrary(OctaveArduinoClass &oc); void commandHandler(uint8_t cmdID, uint8_t* inputs, uint8_t payload_size); virtual void loop(); }; arduino-0.12.1/inst/+arduinoio/lib/OctaveSPILibrary.cpp0000644000000000000000000001140714545566645017626 0ustar00/* * Octave arduino spi interface * Copyright (C) 2018 John Donoghue * * 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 . */ #include "settings.h" #include "OctaveSPILibrary.h" #define ARDUINO_CONFIGSPI 1 #define ARDUINO_READ_WRITE_SPI 2 #ifdef USE_SPI #include class SPIDevice { #define USED 1 #define ENABLED 2 public: uint8_t flags; uint8_t cspin; uint8_t bitorder; uint8_t mode; SPIDevice(); uint8_t init(uint8_t id, uint8_t mode, uint8_t order); uint8_t free(); void set_cs(uint8_t state); int transfer(uint8_t *data, int sz); SPISettings settings(); }; SPIDevice::SPIDevice () { flags = 0; } uint8_t SPIDevice::init (uint8_t id, uint8_t spi_mode, uint8_t spi_bitorder) { flags = USED|ENABLED; cspin = id; if (spi_mode == 0) mode = SPI_MODE0; else if (spi_mode == 1) mode = SPI_MODE1; else if (spi_mode == 2) mode = SPI_MODE2; else if (spi_mode == 3) mode = SPI_MODE3; else mode = SPI_MODE0; bitorder = spi_bitorder; return 0; } uint8_t SPIDevice::free () { flags = 0; return 0; } void SPIDevice::set_cs(uint8_t state) { digitalWrite (cspin, state); } SPISettings SPIDevice::settings() { return SPISettings(4000000, bitorder==0 ? MSBFIRST : LSBFIRST , mode); } int SPIDevice::transfer (uint8_t *data, int sz) { SPI.transfer (data, sz); return 0; } #define MAX_SPI_DEVICES 5 static SPIDevice spidevs[MAX_SPI_DEVICES]; SPIDevice * getSPI (uint8_t id) { uint8_t i; SPIDevice * unused = 0; for (i=0; iinit(data[0], data[2], data[3]); // TODO: first call only ? SPI.begin (); dev->set_cs(HIGH); } else { // TODO: last call only // SPI.end (); dev->free(); } sendResponseMsg (cmdID,data, 2); } else if(datasz == 1) { SPIDevice * dev = getSPI (data[0]); if(dev == 0 || (dev->flags&USED)==0) { sendErrorMsg_P (ERRORMSG_INVALID_DEVICE); return; } // TODO: last call only // SPI.end (); dev->free(); } else { sendInvalidNumArgsMsg (); } break; } case ARDUINO_READ_WRITE_SPI: if (datasz >= 2) { SPIDevice * dev = getSPI (data[0]); if(dev == 0 || (dev->flags&USED)==0) { sendErrorMsg_P (ERRORMSG_INVALID_DEVICE); return; } // begin transaction SPI.beginTransaction (dev->settings()); // set CS low dev->set_cs(LOW); delay (1); // transfer the bytes dev->transfer(&data[1], datasz-1); // set CS hi dev->set_cs(HIGH); delay (1); // endtransaction SPI.endTransaction (); sendResponseMsg (cmdID, data, datasz); } else { sendInvalidNumArgsMsg (); } break; #endif default: sendUnknownCmdIDMsg (); break; } } arduino-0.12.1/inst/+arduinoio/lib/OctaveSPILibrary.h0000644000000000000000000000167714545566645017303 0ustar00/* * Octave arduino spi interface * Copyright (C) 2018 John Donoghue * * 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 . */ #include "LibraryBase.h" class OctaveSPILibrary : public LibraryBase { public: OctaveSPILibrary(OctaveArduinoClass &oc); void commandHandler(uint8_t cmdID, uint8_t* inputs, uint8_t payload_size); }; arduino-0.12.1/inst/+arduinoio/lib/OctaveSerialLibrary.cpp0000644000000000000000000002047014545566645020412 0ustar00/* * Octave arduino serial interface * Copyright (C) 2019 John Donoghue * * 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 . */ #include "settings.h" #include "OctaveSerialLibrary.h" #define ARDUINO_CONFIGSERIAL 1 #define ARDUINO_WRITESERIAL 2 #define ARDUINO_READSERIAL 3 #define ARDUINO_STATSERIAL 4 #ifdef USE_SERIAL #if defined(ARDUINO_AVR_NANO_EVERY) # ifndef SERIAL_PORT_HARDWARE_OPEN # define SERIAL_PORT_HARDWARE_OPEN SERIAL_PORT_HARDWARE # endif #endif #ifndef SERIAL_PORT_HARDWARE_OPEN #error "This device does not support the serial octave serial interface" #endif #if defined(ARDUINO_SAM_DUE) static USARTClass * serial[] = { #else static HardwareSerial * serial[] = { #endif #ifdef SERIAL_PORT_HARDWARE_OPEN1 0, #endif #ifdef SERIAL_PORT_HARDWARE_OPEN2 0, #endif #ifdef SERIAL_PORT_HARDWARE_OPEN3 0, #endif 0 }; #define NUM_SERIAL_PORTS (sizeof(serial)/sizeof(HardwareSerial*)) #endif OctaveSerialLibrary::OctaveSerialLibrary (OctaveArduinoClass &oc) { libName = "Serial"; oc.registerLibrary (this); } void OctaveSerialLibrary::setup () { #ifdef USE_SERIAL serial[0] = &SERIAL_PORT_HARDWARE_OPEN; #ifdef SERIAL_PORT_HARDWARE_OPEN1 serial[1] = &SERIAL_PORT_HARDWARE_OPEN1; #endif #ifdef SERIAL_PORT_HARDWARE_OPEN2 serial[2] = &SERIAL_PORT_HARDWARE_OPEN2; #endif #ifdef SERIAL_PORT_HARDWARE_OPEN3 serial[3] = &SERIAL_PORT_HARDWARE_OPEN3; #endif #endif OctaveLibraryBase::setup (); } void OctaveSerialLibrary::commandHandler (uint8_t cmdID, uint8_t* data, uint8_t datasz) { switch (cmdID) { #ifdef USE_SERIAL case ARDUINO_WRITESERIAL: { if (datasz < 2 || datasz > 32) { // id // data sendInvalidNumArgsMsg (); } else if (data[0] < 1 || data[0] > NUM_SERIAL_PORTS) { sendErrorMsg_P (ERRORMSG_INVALID_DEVICE); } else { uint8_t id = data[0]-1; serial[id]->write (&data[1], datasz-1); data[1] = 1; sendResponseMsg (cmdID, data, 2); } break; } case ARDUINO_READSERIAL: { if (datasz != 3) { // port // numbytes // timeout in 10th of second sendInvalidNumArgsMsg (); } else if (data[0] < 1 || data[0] > NUM_SERIAL_PORTS) { sendErrorMsg_P (ERRORMSG_INVALID_DEVICE); } else { uint8_t id = data[0]-1; uint8_t timeout = data[2]; byte c = 0; byte l = data[1]; // if have a timeout, try wait that time for enough data before returning if (timeout > 0) { sendWaitMsg (); unsigned long t = millis(); unsigned long e = t + timeout * 100; // 10th of a seconf to millis while (e > t && serial[id]->available() < l) { t = millis(); } } datasz = 1; for (c=0; cavailable ()) { data[datasz] = serial[id]->read (); datasz ++; } } sendResponseMsg(cmdID,data, datasz); } break; } case ARDUINO_STATSERIAL: { if (datasz != 1) { // port sendInvalidNumArgsMsg (); } else if (data[0] < 1 || data[0] > NUM_SERIAL_PORTS) { sendErrorMsg_P (ERRORMSG_INVALID_DEVICE); } else { uint8_t id = data[0]-1; data[1] = serial[id]->available (); sendResponseMsg (cmdID, data, 2); } break; } case ARDUINO_CONFIGSERIAL: { if (datasz > 0 && (data[0] < 1 || data[0] > NUM_SERIAL_PORTS)) { sendErrorMsg_P(ERRORMSG_INVALID_DEVICE); } // enable else if (datasz == 9 && data[1] == 1) { uint8_t id = data[0]-1; // data[1] = enable uint32_t baud = ((uint32_t)data[2]<<24) | ((uint32_t)data[3]<<16) | ((uint32_t)data[4]<<8) | data[5]; #if defined(ARDUINO_SAM_DUE) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_SAMD_MKR1000) uint32_t conf = 0; #else uint8_t conf = 0; #endif // data[6] = databits // data[7] = stopbits // data[8] = parity if (data[8] == 2) // parity even { if (data[7] == 1) { switch (data[6]) { case 5: conf = SERIAL_5E1; break; case 6: conf = SERIAL_6E1; break; case 7: conf = SERIAL_7E1; break; default: conf = SERIAL_8E1; break; } } else // 2 stop bits { switch (data[6]) { case 5: conf = SERIAL_5E2; break; case 6: conf = SERIAL_6E2; break; case 7: conf = SERIAL_7E2; break; default: conf = SERIAL_8E2; break; } } } else if (data[8] == 1) // parity odd { if (data[7] == 1) { switch (data[6]) { case 5: conf = SERIAL_5O1; break; case 6: conf = SERIAL_6O1; break; case 7: conf = SERIAL_7O1; break; default: conf = SERIAL_8O1; break; } } else // 2 stop bits { switch (data[6]) { case 5: conf = SERIAL_5O2; break; case 6: conf = SERIAL_6O2; break; case 7: conf = SERIAL_7O2; break; default: conf = SERIAL_8O2; break; } } } else // parity none { if (data[7] == 1) { switch (data[6]) { case 5: conf = SERIAL_5N1; break; case 6: conf = SERIAL_6N1; break; case 7: conf = SERIAL_7N1; break; default: conf = SERIAL_8N1; break; } } else // 2 stop bits { switch (data[6]) { case 5: conf = SERIAL_5N2; break; case 6: conf = SERIAL_6N2; break; case 7: conf = SERIAL_7N2; break; default: conf = SERIAL_8N2; break; } } } #if defined(ARDUINO_SAM_DUE) serial[id]->begin (baud, (USARTClass::USARTModes)conf); #else serial[id]->begin (baud, conf); #endif sendResponseMsg (cmdID, data, 2); } // disable else if (datasz == 2 && data[1] == 0) { uint8_t id = data[0]-1; serial[id]->end (); sendResponseMsg (cmdID, data, 2); } else { sendInvalidNumArgsMsg (); } break; } #endif default: sendUnknownCmdIDMsg(); break; } } arduino-0.12.1/inst/+arduinoio/lib/OctaveSerialLibrary.h0000644000000000000000000000173114545566645020056 0ustar00/* * Octave arduino serial interface * Copyright (C) 2019 John Donoghue * * 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 . */ #include "LibraryBase.h" class OctaveSerialLibrary : public LibraryBase { public: OctaveSerialLibrary(OctaveArduinoClass &oc); void setup(); void commandHandler(uint8_t cmdID, uint8_t* inputs, uint8_t payload_size); }; arduino-0.12.1/inst/+arduinoio/lib/OctaveServoLibrary.cpp0000644000000000000000000000467314545566645020300 0ustar00/* * Octave arduino servo interface * Copyright (C) 2018 John Donoghue * * 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 . */ #include "settings.h" #include "OctaveServoLibrary.h" #define ARDUINO_SERVO 0 #define ARDUINO_CONFIG_SERVO 1 #ifdef USE_SERVO // NOTE: if cant fint servo.h, you probally dont have the Servo library installed // go to Sketch -> Include Library -> Manage Libraries, and select 'Servo' // For ESP boards, it bwill need to be ESP32Servo # if defined(ARDUINO_ARCH_ESP32) #include # else #include # endif Servo servo[NUM_DIGITAL_PINS]; uint16_t servo_pos[NUM_DIGITAL_PINS]; #endif OctaveServoLibrary::OctaveServoLibrary (OctaveArduinoClass &oc) { libName = "Servo"; oc.registerLibrary (this); } void OctaveServoLibrary::commandHandler (uint8_t cmdID, uint8_t* data, uint8_t datasz) { switch (cmdID) { #ifdef USE_SERVO case ARDUINO_SERVO: if (datasz == 1) { uint16_t ms = servo_pos[data[0]]; data[1] = (ms>>8); data[2] = (ms&0xff); sendResponseMsg (cmdID, data, 3); } else if (datasz == 3) { uint16_t ms = ((int)data[1]<<8) | ((int)data[2]); servo_pos[data[0]] = ms; servo[data[0]].writeMicroseconds (ms); sendResponseMsg (cmdID, data, 1); } else { sendInvalidNumArgsMsg (); } break; case ARDUINO_CONFIG_SERVO: if (datasz > 0) { // pin // conf stuff ... ? servo[data[0]].attach (data[0]); sendResponseMsg (cmdID, data, 1); } else { sendInvalidNumArgsMsg (); } break; #endif default: sendUnknownCmdIDMsg (); break; } } arduino-0.12.1/inst/+arduinoio/lib/OctaveServoLibrary.h0000644000000000000000000000170514545566645017736 0ustar00/* * Octave arduino servo interface * Copyright (C) 2018 John Donoghue * * 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 . */ #include "LibraryBase.h" class OctaveServoLibrary : public LibraryBase { public: OctaveServoLibrary(OctaveArduinoClass &oc); void commandHandler(uint8_t cmdID, uint8_t* inputs, uint8_t payload_size); }; arduino-0.12.1/inst/+arduinoio/lib/OctaveShiftRegisterLibrary.cpp0000644000000000000000000002506314545566645021760 0ustar00/* * Octave arduino shift register interface * Copyright (C) 2018 John Donoghue * * 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 . */ #include "settings.h" #include "OctaveShiftRegisterLibrary.h" #define ARDUINO_RESET_SHIFTREG 0 #define ARDUINO_CONFIG_SHIFTREG 1 #define ARDUINO_WRITE_SHIFTREG 2 #define ARDUINO_READ_SHIFTREG 3 #define TYPE_74HC164 0 // input p2s #define TYPE_74HC165 1 // output s2p #define TYPE_74HC595 2 #define SER_74HC595_DATA 0 #define SER_74HC595_CLK 1 #define SER_74HC595_LATCH 2 #define SER_74HC595_RESET 3 #define SER_74HC165_DATA 0 #define SER_74HC165_CLK 1 #define SER_74HC165_LOAD 2 #define SER_74HC165_CLOCKEN 3 #define SER_74HC164_DATA 0 #define SER_74HC164_CLK 1 #define SER_74HC164_RESET 2 static const char ERRORMSG_CANT_READ[] PROGMEM = "This register cant not read"; static const char ERRORMSG_CANT_WRITE[] PROGMEM = "This register can not write"; #ifdef USE_SHIFTREG #define MAX_SHIFT_REGISTERS 8 class ShiftRegister { public: uint8_t used; uint8_t type; uint8_t pins[6]; ShiftRegister (); bool canread (); bool canwrite (); uint8_t init (); uint8_t csenable (bool en); uint8_t latch (); uint8_t read (); uint8_t free () { used = 0; return 0;} uint8_t write (uint8_t); uint8_t reset (); }; ShiftRegister::ShiftRegister () { used = 0; } bool ShiftRegister::canread () { return (type == TYPE_74HC165); } bool ShiftRegister::canwrite () { return (type == TYPE_74HC164 || type == TYPE_74HC595); } uint8_t ShiftRegister::init () { // depends on type of what need do if (type == TYPE_74HC164) { pinMode (pins[SER_74HC164_DATA], OUTPUT); pinMode (pins[SER_74HC164_CLK], OUTPUT); // have reset pin if (used > SER_74HC164_RESET) { pinMode (pins[SER_74HC164_RESET], OUTPUT); digitalWrite (pins[SER_74HC164_RESET], LOW); } digitalWrite (pins[SER_74HC595_CLK], LOW); if (used > SER_74HC164_RESET) { // have reset pin - so unset clr digitalWrite (pins[SER_74HC164_RESET], HIGH); } } if (type == TYPE_74HC165) { // serial data is input pinMode (pins[SER_74HC165_DATA], INPUT); // init with clock and load high pinMode (pins[SER_74HC165_CLK], OUTPUT); pinMode (pins[SER_74HC165_LOAD], OUTPUT); digitalWrite (pins[SER_74HC165_CLK], HIGH); digitalWrite (pins[SER_74HC165_LOAD], HIGH); } if (type == TYPE_74HC595) { pinMode (pins[SER_74HC595_DATA], OUTPUT); pinMode (pins[SER_74HC595_CLK], OUTPUT); // clk pinMode (pins[SER_74HC595_LATCH], OUTPUT); // latch // have reset pin if (used > SER_74HC595_RESET) { pinMode (pins[SER_74HC595_RESET], OUTPUT); // reset (optional) digitalWrite (pins[SER_74HC595_RESET], LOW); } // clock start high digitalWrite (pins[SER_74HC595_CLK], LOW); // latch digitalWrite (pins[SER_74HC595_LATCH], LOW); // have reset pin - so unset clr if (used > SER_74HC595_RESET) { digitalWrite (pins[SER_74HC595_RESET], HIGH); } } return 0; } uint8_t ShiftRegister::csenable (bool en) { if (type == TYPE_74HC164) { // nothing to do } else if (type == TYPE_74HC165) { // enable the clock with clockenalepin digitalWrite (pins[SER_74HC165_CLOCKEN], en ? LOW : HIGH); } else if (type == TYPE_74HC595) { // nothing to do } return 0; } uint8_t ShiftRegister::latch () { if (type == TYPE_74HC164) { // no latch } else if (type == TYPE_74HC165) { // trigger loading, by toggle on loadpin digitalWrite (pins[SER_74HC165_LOAD], LOW); delayMicroseconds (5); digitalWrite (pins[SER_74HC165_LOAD], HIGH); delayMicroseconds (5); } else if (type == TYPE_74HC595) { // latches on rising edge digitalWrite (pins[SER_74HC595_LATCH], HIGH); delayMicroseconds (5); digitalWrite (pins[SER_74HC595_LATCH], LOW); delayMicroseconds (5); } return 0; } uint8_t ShiftRegister::read () { uint8_t val = 0; if (type == TYPE_74HC165) { val = shiftIn(pins[SER_74HC165_DATA], pins[SER_74HC165_CLK], MSBFIRST); } return val; } uint8_t ShiftRegister::write (uint8_t d) { if (type == TYPE_74HC595) { shiftOut (pins[SER_74HC595_DATA], pins[SER_74HC595_CLK], MSBFIRST, d); return 1; } if (type == TYPE_74HC164) { shiftOut (pins[SER_74HC164_DATA], pins[SER_74HC164_CLK], MSBFIRST, d); return 1; } return 0; } uint8_t ShiftRegister::reset () { if (type == TYPE_74HC595) { // have reset pin - so unset clr if (used > SER_74HC595_RESET) { digitalWrite (pins[SER_74HC595_RESET], LOW); delayMicroseconds (5); digitalWrite (pins[SER_74HC595_RESET], HIGH); delayMicroseconds (5); return 1; } } else if (type == TYPE_74HC164) { if (used > SER_74HC164_RESET) { digitalWrite (pins[SER_74HC164_RESET], LOW); delayMicroseconds (5); digitalWrite (pins[SER_74HC164_RESET], HIGH); delayMicroseconds (5); return 1; } } return 0; } static ShiftRegister shiftregs[MAX_SHIFT_REGISTERS]; ShiftRegister * getShiftRegister (uint8_t id) { uint8_t i; ShiftRegister * unused = 0; for (i=0; i 0) { if (shiftregs[i].pins[0] == id) return &shiftregs[i]; } else if (!unused) { unused = &shiftregs[i]; } } return unused; } #endif OctaveShiftRegisterLibrary::OctaveShiftRegisterLibrary(OctaveArduinoClass &oc) { libName = "ShiftRegister"; oc.registerLibrary (this); } void OctaveShiftRegisterLibrary::commandHandler (uint8_t cmdID, uint8_t* data, uint8_t datasz) { switch (cmdID) { #ifdef USE_SHIFTREG case ARDUINO_CONFIG_SHIFTREG: { // 0 = id/datapin // 1 - enable/alloc // [ 2 = type // 3 = pins [] // 4 ... ] ShiftRegister * reg = getShiftRegister (data[0]); if (reg) { // alloc if (data[1] == 1 && datasz >= 4) { // data = DATAPIN E T CLK PIN? PIN? ... // // DATAPIN (doubles as ID) // E = enable (1 vs 0) ie: alloc/free // T = type 0 = 74HC164, ... // CLK clock pin // otherpins // pins used = pins defined reg->used = datasz - 2; // 1st pin is the register id reg->pins[0] = data[0]; reg->type = data[2]; byte c = 0; for (c=0; cused-1; c++) { reg->pins[c+1] = data[3+c]; } reg->init (); sendResponseMsg (cmdID, data, 2); } // free else if (data[1] == 0 && reg->used > 0 && datasz == 2) { reg->used = 0; reg->free (); sendResponseMsg (cmdID, data, 2); } else { sendErrorMsg_P (ERRORMSG_INVALID_ARGS); } } else { sendErrorMsg_P (ERRORMSG_INVALID_ARGS); } break; } case ARDUINO_RESET_SHIFTREG: { // 0 = id (currently using the datapin id) ShiftRegister * reg = getShiftRegister (data[0]); if (reg && reg->used > 0) { data[1] = reg->reset (); sendResponseMsg (cmdID, data, 2); } else { sendErrorMsg_P (ERRORMSG_INVALID_ARGS); } break; } case ARDUINO_WRITE_SHIFTREG: { // 0 = id // byte 0 // [byte1....] ShiftRegister * reg = getShiftRegister(data[0]); if (reg && reg->used > 0 && datasz >= 2) { if (reg->canwrite()) { reg->csenable (true); byte c = 0; for (c=1; cwrite (data[c]); } // num bytes wrote data[1] = datasz-1; datasz = 2; reg->latch (); reg->csenable (false); sendResponseMsg (cmdID, data, datasz); } else { // chip cant do write sendErrorMsg_P (ERRORMSG_CANT_WRITE); } } else { sendErrorMsg_P (ERRORMSG_INVALID_ARGS); } break; } case ARDUINO_READ_SHIFTREG: { // 0 = id // 1 = numbytes ShiftRegister * reg = getShiftRegister (data[0]); if (reg && reg->used > 0 && datasz == 2) { if (reg->canread ()) { reg->csenable (true); reg->latch (); byte c = 0; datasz = data[1]; for (c=1; cread (); } reg->csenable (false); sendResponseMsg (cmdID, data, datasz); } else { // cant read sendErrorMsg_P( ERRORMSG_CANT_READ); } } else { sendErrorMsg_P (ERRORMSG_INVALID_ARGS); } break; } #endif default: sendUnknownCmdIDMsg (); break; } } arduino-0.12.1/inst/+arduinoio/lib/OctaveShiftRegisterLibrary.h0000644000000000000000000000173614545566645021426 0ustar00/* * Octave arduino shift register interface * Copyright (C) 2018 John Donoghue * * 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 . */ #include "LibraryBase.h" class OctaveShiftRegisterLibrary : public LibraryBase { public: OctaveShiftRegisterLibrary(OctaveArduinoClass &oc); void commandHandler(uint8_t cmdID, uint8_t* inputs, uint8_t payload_size); }; arduino-0.12.1/inst/+arduinoio/lib/OctaveUltrasonicLibrary.cpp0000644000000000000000000001077114545566645021321 0ustar00/* * Octave arduino ultrasonic interface * Copyright (C) 2019 John Donoghue * * 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 . */ #include "settings.h" #include "OctaveUltrasonicLibrary.h" #define ARDUINO_CONFIG_ULTRASONIC 1 #define ARDUINO_READ_ULTRASONIC 2 static const char ERRORMSG_CANT_READ[] PROGMEM = "Max ultrasonics reached"; #ifdef USE_ULTRASONIC #define MAX_ULTRASONICS 4 class Ultrasonic { #define USED 1 public: uint8_t flags; uint8_t pins[2]; uint8_t state; Ultrasonic (); uint8_t init (uint8_t p1, uint8_t p2); uint8_t free () { flags = 0; return 0;} uint32_t read (); }; Ultrasonic::Ultrasonic () { flags = 0; } uint8_t Ultrasonic::init (uint8_t p1, uint8_t p2=0xff) { flags = USED; pins[0] = p1; pins[1] = p2; if(p1 == p2) pins[1] = 0xff; pinMode (pins[0], OUTPUT); digitalWrite (pins[0], LOW); if (pins[1] != 0xff) { pinMode (pins[1], INPUT); digitalWrite (pins[1], LOW); } return 0; } uint32_t Ultrasonic::read () { uint32_t duration; digitalWrite (pins[0], LOW); delayMicroseconds (5); // Sets the trigPin on HIGH state for 10 micro seconds digitalWrite (pins[0], HIGH); delayMicroseconds (10); digitalWrite (pins[0], LOW); if (pins[1] == 0xff) { pinMode (pins[0], INPUT); duration = pulseIn(pins[0], HIGH, 250); pinMode (pins[0], OUTPUT); } else { // Reads the echoPin, returns the sound wave travel time in microseconds duration = pulseIn (pins[1], HIGH); //, 250); } return duration; } static Ultrasonic ultrasonics[MAX_ULTRASONICS]; Ultrasonic * getUltrasonic (uint8_t id) { uint8_t i; Ultrasonic * unused = 0; for (i=0; iinit (data[0]); sendResponseMsg (cmdID,data, 2); } else if(data[1] == 1 && datasz == 3) { reg->init (data[0], data[2]); sendResponseMsg (cmdID,data, 2); } // free else if (data[1] == 0 && reg->flags && datasz == 2) { reg->free (); sendResponseMsg(cmdID,data, 2); } else { sendErrorMsg_P (ERRORMSG_INVALID_ARGS); } } else { sendErrorMsg_P (ERRORMSG_INVALID_ARGS); } break; } case ARDUINO_READ_ULTRASONIC: { // 0 = id Ultrasonic * reg = getUltrasonic (data[0]); if (reg && datasz == 1) { uint32_t v = reg->read (); data[1] = (v>>24)&0xff; data[2] = (v>>16)&0xff; data[3] = (v>>8)&0xff; data[4] = (v)&0xff; datasz = 5; sendResponseMsg (cmdID, data, datasz); } else { sendErrorMsg_P (ERRORMSG_INVALID_ARGS); } break; } #endif default: sendUnknownCmdIDMsg (); break; } } arduino-0.12.1/inst/+arduinoio/lib/OctaveUltrasonicLibrary.h0000644000000000000000000000173014545566645020761 0ustar00/* * Octave arduino shift register interface * Copyright (C) 2019 John Donoghue * * 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 . */ #include "LibraryBase.h" class OctaveUltrasonicLibrary : public LibraryBase { public: OctaveUltrasonicLibrary(OctaveArduinoClass &oc); void commandHandler(uint8_t cmdID, uint8_t* inputs, uint8_t payload_size); }; arduino-0.12.1/inst/+arduinoio/lib/octave.ino0000644000000000000000000000411214545566645015763 0ustar00/* * Octave arduino interface * Copyright (C) 2018-2023 John Donoghue * * 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 . */ #include "settings.h" #include "LibraryBase.h" // lib manager / processing static OctaveArduinoClass octavearduino; // include the base library #include "OctaveCoreLibrary.h" OctaveCoreLibrary lib0(octavearduino); #ifdef USE_I2C #include "OctaveI2CLibrary.h" OctaveI2CLibrary lib1(octavearduino); #endif #ifdef USE_SPI #include "OctaveSPILibrary.h" OctaveSPILibrary lib2(octavearduino); #endif #ifdef USE_SERVO #include "OctaveServoLibrary.h" OctaveServoLibrary lib3(octavearduino); #endif #ifdef USE_SHIFTREG #include "OctaveShiftRegisterLibrary.h" OctaveShiftRegisterLibrary lib4(octavearduino); #endif #ifdef USE_ROTARYENCODER #include "OctaveRotaryEncoderLibrary.h" OctaveRotaryEncoderLibrary lib5(octavearduino); #endif #ifdef USE_ULTRASONIC #include "OctaveUltrasonicLibrary.h" OctaveUltrasonicLibrary lib6(octavearduino); #endif #ifdef USE_SERIAL #include "OctaveSerialLibrary.h" OctaveSerialLibrary lib7(octavearduino); #endif // additional addons included from generated addons.h file #include "addons.h" void setup() { #if defined(ARDUINO_ARCH_AVR) // clear watchdog // clear all flags MCUSR = 0; /* Write logical one to WDCE and WDE */ /* Keep old prescaler setting to prevent unintentional time-out */ WDTCSR |= _BV(WDCE) | _BV(WDE); WDTCSR = 0; #endif octavearduino.init(); } void loop() { octavearduino.runLoop(); } arduino-0.12.1/inst/+arduinoioaddons/0000755000000000000000000000000014545566645014420 5ustar00arduino-0.12.1/inst/+arduinoioaddons/+EEPRomAddon/0000755000000000000000000000000014545566645016530 5ustar00arduino-0.12.1/inst/+arduinoioaddons/+EEPRomAddon/EEPRom.m0000644000000000000000000001300714545566645017776 0ustar00## Copyright (C) 2018-2020 John Donoghue ## ## 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 ## . classdef EEPRom < arduinoio.LibraryBase ## -*- texinfo -*- ## @deftypefn {} {} arduinoioaddons.EEPRomAddon.EEPRom ## EEPROM addon for arduino ## ## Allows read and write of uint8 data to the onboard arduino EEPROM. ## ## @subsubheading Example ## Assuming eeprom addon has been programmed into the Arduino: ## @example ## a = arduino (); ## e = addon (a, "eepromaddon/eeprom"); ## write (e, 0, uint8("hello world")); ## str = uint8( read(e, 0, 11) ) ## @end example ## ## @seealso{addon} ## @end deftypefn ## ## @subsubheading Properties ## @var{length} - Size of the EEPROM. ## ## @subheading Methods ## @deftypefn {} {@var{eeprom} =} EEPRom () ## Constructor to create EEPROM device. ## @subsubheading Outputs ## @var{eeprom} - created EEPROM device. ## @end deftypefn ## ## @deftypefn {} {} erase () ## Erase all values in EEPROM (Effectively setting the 0xFF) ## @end deftypefn ## ## @deftypefn {} {} write (@var{address}, @var{uintdata}) ## Write data to EEPROM at the provided address. ## @subsubheading Inputs ## @var{address} - start address to write data to, should be an ## integer between 0 and the size of the EEPROM. ## ## @var{uintdata} a value or array of uint8 data to write to EEPROM. ## @end deftypefn ## ## @deftypefn {} {@var{data} =} read (@var{address}) ## @deftypefnx {} {@var{data} =} read (@var{address}, @var{count}) ## Read data from starting address of EEPROM. ## @subsubheading Inputs ## @var{address} - start address to read data from, should be an ## integer between 0 and the size of the EEPROM. ## ## @var{count} - Number of uint8 values to read from the EEPROM (default is 1) ## ## @subsubheading Outputs ## @var{data} a value or array of uint8 data read from the EEPROM. ## @end deftypefn properties(Access = private) len = 0; endproperties # commands properties(Access = private, Constant = true) INIT_COMMAND = hex2dec('00'); ERASE_COMMAND = hex2dec('01'); READ_COMMAND = hex2dec('02'); WRITE_COMMAND = hex2dec('03'); endproperties properties(Access = protected, Constant = true) LibraryName = 'EEPRomAddon/EEPRom'; DependentLibraries = {}; #ArduinoLibraryHeaderFiles = {}; CppHeaderFile = fullfile(arduinoio.FilePath(mfilename('fullpath')), 'EEPRomAddon.h'); CppClassName = 'EEPRom'; endproperties methods # constructor function obj = EEPRom(parentObj) obj.Parent = parentObj; if nargin != 1 error ("EEPRom: expected arduino parent as only argument"); endif obj.Pins = {}; data = sendCommand(obj.Parent, obj.LibraryName, obj.INIT_COMMAND, []); length = uint16(data(1))*256 + uint16(data(2)) obj.len = length; endfunction function len = length (obj) len = obj.len; endfunction function erase(obj) cmdID = obj.ERASE_COMMAND; sendCommand(obj.Parent, obj.LibraryName, cmdID, []); endfunction function value = read(obj, address, num) cmdID = obj.READ_COMMAND; if nargin != 2 && nargin != 3 error ("EEPRom: expected address and optional number of bytes"); endif if nargin == 2 num = 1; endif if ! isnumeric(address) || address < 0 || address >= obj.len || mod(address, 1) != 0 error ("EEProm: expected address to be between 0 and %d", obj.len); endif if ! isnumeric(num) || num < 0 || num > 128 || mod(num, 1) != 0 error ("EEProm: num expected to be integer between 0 and %d", 128); endif if address + num > obj.len error ("EEPRom: address + num (%d) is out of EEPRom bounds of %d\n", (address+num), obj.len); endif intval = uint16(address); datain = [ bitshift(intval,-8) bitand(intval, 255) num]; dataout = sendCommand(obj.Parent, obj.LibraryName, cmdID, datain); value = dataout; endfunction function write(obj, address, value) cmdID = obj.WRITE_COMMAND; if nargin != 3 error ("EEPRom: expected address and value"); endif if ! isnumeric(address) || address < 0 || address >= obj.len || mod(address, 1) != 0 error ("expected address to be between 0 and %d", obj.len); endif num = numel(value); if num < 0 || num > 128 error ("EEProm: value size expected to be between 0 and %d", 128); endif if (address + num > obj.len) error ("EEPRom: address + numel(value) (%d) is out of EEPRom bounds of %d\n", (address+num), obj.len); endif intval = uint16(address); datain = [ bitshift(intval,-8) bitand(intval, 255) value]; sendCommand(obj.Parent, obj.LibraryName, cmdID, datain); endfunction function disp (obj) printf(" %s with properties\n", class(obj)); printf(" length = %d\n", obj.len); endfunction endmethods endclassdef arduino-0.12.1/inst/+arduinoioaddons/+EEPRomAddon/EEPRomAddon.h0000644000000000000000000000434114545566645020740 0ustar00/* * Copyright (C) 2018 John Donoghue * * 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 * . */ #include "LibraryBase.h" #include // arduino liquid crystal library #define EEPROM_INIT 0x00 #define EEPROM_ERASE 0x01 #define EEPROM_READ 0x02 #define EEPROM_WRITE 0x03 class EEPRom : public LibraryBase { public: EEPRom(OctaveArduinoClass& a) { libName = "EEPRomAddon/EEProm"; a.registerLibrary(this); } void commandHandler(uint8_t cmdId, uint8_t* data, uint8_t datasz) { switch(cmdId) { case EEPROM_INIT: { uint16_t sz = EEPROM.length(); data[0] = (sz>>8)&0xff; data[1] = (sz)&0xff; sendResponseMsg(cmdId, data, 2); break; } case EEPROM_ERASE: { for (int a=0;a= 3) { uint16_t addr = (uint16_t(data[0])<<8) | data[1]; datasz = datasz-2; for(int i=0;i ## ## 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 ## . classdef Echo < arduinoio.LibraryBase ## -*- texinfo -*- ## @deftypefn {} {} arduinoioaddons.ExampleAddon.Echo ## Basic Example matlab/octave code to illustrate creating ## a user addon. ## ## @seealso{addon} ## @end deftypefn ## ## @subsubheading Properties ## @var{Parent} - the parent arduino object. ## ## @var{Pins} - the pins allocated the addon. ## ## @subheading Methods ## @deftypefn {} {@var{obj} =} Echo(arObj) ## Constructor to create Echo addon ## @subsubheading Inputs ## @var{arObj} - the arduino parent object ## ## @subsubheading Outputs ## @var{obj} - created Echo object ## @end deftypefn ## ## @deftypefn {} {@var{response} = } shout(@var{text}) ## Send text to arduino and receive back the echoed reply ## ## @subsubheading Inputs ## @var{text} - text to send to arduino ## ## @subsubheading Outputs ## @var{response} - response from the arduino, which should be the same as ## the input text. ## @end deftypefn # commands properties(Access = private, Constant = true) ECHO_COMMAND = hex2dec('01'); endproperties properties(Access = protected, Constant = true) LibraryName = 'ExampleAddon/Echo'; DependentLibraries = {}; ArduinoLibraryHeaderFiles = {}; CppHeaderFile = fullfile(arduinoio.FilePath(mfilename('fullpath')), 'src', 'Echo.h'); CppClassName = 'Echo'; endproperties methods # constructor function obj = Echo(parentObj) obj.Parent = parentObj; obj.Pins = []; endfunction # function addon can do function out = shout(obj, val) cmdID = obj.ECHO_COMMAND; inputs = [uint8(val)]; output = sendCommand(obj.Parent, obj.LibraryName, cmdID, inputs); # data is just an echo of what we sent out = char(output); endfunction endmethods endclassdef arduino-0.12.1/inst/+arduinoioaddons/+ExampleAddon/src/0000755000000000000000000000000014545566645017623 5ustar00arduino-0.12.1/inst/+arduinoioaddons/+ExampleAddon/src/Echo.h0000644000000000000000000000250014545566645020647 0ustar00/* * Copyright (C) 2018 John Donoghue * * 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 * . */ #include "LibraryBase.h" const char MSG_NEEDS_VALUE[] PROGMEM = "Needs a value to echo"; class Echo : public LibraryBase { public: Echo(OctaveArduinoClass& a) { libName = "ExampleAddon/Echo"; a.registerLibrary(this); } void commandHandler(uint8_t cmdID, uint8_t* data, uint8_t datasz) { switch (cmdID) { case 0x01: { if(datasz == 0) sendErrorMsg_P(MSG_NEEDS_VALUE); else sendResponseMsg(cmdID, data, datasz); break; } default: { // notify of invalid cmd sendUnknownCmdIDMsg(); } } } }; arduino-0.12.1/inst/+arduinoioaddons/+ExampleLCD/0000755000000000000000000000000014545566645016411 5ustar00arduino-0.12.1/inst/+arduinoioaddons/+ExampleLCD/LCD.m0000644000000000000000000001513714545566645017200 0ustar00## Copyright (C) 2018-2020 John Donoghue ## ## 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 ## . classdef LCD < arduinoio.LibraryBase ## -*- texinfo -*- ## @deftypefn {} {} arduinoioaddons.LCDAddon.LCD ## Basic Example octave addon for LCD ## ## Allows basic manipulation of an LCD as a illustration of using ## the addon functionality. ## @subsubheading Example ## Assuming the arduino has been programmed with the lcd addon: ## @example ## a = arduino(); ## lcd = addon(a, "examplelcd/lcd", "d8", "d9", "d4", "d5", "d6", "d7") ## clearLCD(lcd); ## printLCD(lcd, "Hello"); ## # go to next line ## gotoLCD(lcd, 0, 1); ## printLCD(lcd, "World"); ## @end example ## @seealso{addon} ## @end deftypefn ## ## @subsubheading Properties ## @var{Pins} - the pins allocated the LCD display. ## ## @subheading Methods ## @deftypefn {} {@var{lcd} =} LCD(arObj, rs, enable, d0, d1, d2, d3) ## Constructor to create LCD device ## @subsubheading Inputs ## @var{arObj} - the arduino parent object ## ## @var{rs} - the pin to use for the rs line. ## ## @var{enable} - the pin to use for the enable line. ## ## @var{d0} - the pin to use for the d0 line. ## ## @var{d1} - the pin to use for the d1 line. ## ## @var{d2} - the pin to use for the d2 line. ## ## @var{d3} - the pin to use for the d3 line. ## ## @subsubheading Outputs ## @var{lcd} - created LCD object ## @end deftypefn ## ## @deftypefn {} {} freeLCD() ## Free the LCD ## ## Should be called before discarding the LCD ## @subsubheading Inputs ## None. ## ## @subsubheading Outputs ## None. ## @end deftypefn ## ## @deftypefn {} {} clearLCD() ## Clear the LCD display and set the cursor position to the home position. ## ## @subsubheading Inputs ## None. ## ## @subsubheading Outputs ## None. ## @end deftypefn ## ## @deftypefn {} {} printLCD(@var{text}) ## Display text on LCD starting at the current cursor position. ## ## @subsubheading Inputs ## @var{text} - text to display on LCD ## ## @subsubheading Outputs ## None. ## @end deftypefn ## ## @deftypefn {} {} gotoLCD(@var{col}, @var{row}) ## Set the cursor position to row, col ## ## @subsubheading Inputs ## @var{col} - 0 indexed LCD column to position to. ## ## @var{row} - 0 indexed LCD row to position to. ## ## @subsubheading Outputs ## None. ## @end deftypefn # commands properties(Access = private, Constant = true) INIT_COMMAND = hex2dec('00'); FREE_COMMAND = hex2dec('01'); CLEAR_COMMAND = hex2dec('02'); PRINT_COMMAND = hex2dec('03'); SETCURSOR_COMMAND = hex2dec('04'); endproperties properties(Access = protected, Constant = true) LibraryName = 'ExampleLCD/LCD'; DependentLibraries = {}; ArduinoLibraryHeaderFiles = { 'LiquidCrystal/LiquidCrystal.h' }; CppHeaderFile = fullfile(arduinoio.FilePath(mfilename('fullpath')), 'LCDAddon.h'); CppClassName = 'LCD'; endproperties properties(Access=private) ResourceOwner = 'ExampleLCD/LCDAddon'; endproperties methods # constructor function obj = LCD(parentObj, rs, enable, d0, d1, d2, d3) obj.Parent = parentObj; if nargin < 7 error ("LCD: expected input pins rs, enable, d0, d1, d2, d3"); endif # our LCD code only allows 1 lcd at a time count = getResourceCount(obj.Parent, obj.ResourceOwner); if count > 0 error ("ExampleLCD/LCDAddon: can have only one LCD at a time"); endif obj.Pins = {}; data = []; pindata = getPinInfo(obj.Parent, {rs enable d0 d1 d2 d3}); try for p = 1:numel(pindata) pin = pindata{p}; configurePin(obj.Parent, pin.name, "digitaloutput") obj.Pins{end+1} = pin.name; data = [data pin.terminal]; endfor catch # catch any errors and restore pins for p = 1:numel(pindata) pin = pindata{p}; configurePinResource(obj.Parent, pin.name, pin.owner, pin.mode, true) configurePin(obj.Parent, pin.name, pin.mode) endfor rethrow (lasterror); end_try_catch sendCommand(obj.Parent, obj.LibraryName, obj.INIT_COMMAND, data); incrementResourceCount(obj.Parent,obj.ResourceOwner); endfunction function freeLCD(obj) if nargin != 1 warning ("LCD: unexpected additional arguments being ignored"); endif if isobject(obj.Parent) cmdID = obj.FREE_COMMAND; sendCommand(obj.Parent, obj.LibraryName, cmdID); decrementResourceCount(obj.Parent,obj.ResourceOwner); obj.Parent = []; endif endfunction function printLCD(obj, text) if nargin < 2 || !ischar(text) error ("LCD: expected text to display"); endif if nargin != 2 warning ("LCD: unexpected additional arguments being ignored"); endif cmdID = obj.PRINT_COMMAND; sendCommand(obj.Parent, obj.LibraryName, cmdID, [uint8(text) 0]); endfunction function clearLCD(obj) if nargin != 1 warning ("LCD: unexpected additional arguments being ignored"); endif cmdID = obj.CLEAR_COMMAND; sendCommand(obj.Parent, obj.LibraryName, cmdID); endfunction function gotoLCD(obj, col, row) if nargin < 3 error ("LCD: col and row"); endif if nargin != 3 warning ("LCD: unexpected additional arguments being ignored"); endif if !isnumeric(col) || col < 0 || mod(col,1) != 0 error ("LCD: expected col as a numeric integer value"); endif if !isnumeric(row) || row < 0 || mod(row,1) != 0 error ("LCD: expected row as a numeric integer value"); endif cmdID = obj.SETCURSOR_COMMAND; sendCommand(obj.Parent, obj.LibraryName, cmdID, [col row]); endfunction function delete(obj) try ar = obj.Parent; if isobject(ar) freeLCD(obj); endif catch err # do nothing # warning("caught error %s", err.message) end_try_catch endfunction endmethods endclassdef arduino-0.12.1/inst/+arduinoioaddons/+ExampleLCD/LCDAddon.h0000644000000000000000000000553714545566645020144 0ustar00/* * Copyright (C) 2018 John Donoghue * * 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 * . */ #include "LibraryBase.h" #include // arduino liquid crystal library static const char LCD_MSG_ALREADY_INITIALIZED[] PROGMEM = "Already initialized"; static const char LCD_MSG_NOT_INITIALIZED[] PROGMEM = "LCD not initialized"; #define LCD_INIT 0x00 #define LCD_FREE 0x01 #define LCD_CLEAR 0x02 #define LCD_PRINT 0x03 #define LCD_SETCURSOR 0x04 class LCD : public LibraryBase { private: LiquidCrystal *lcd; public: LCD(OctaveArduinoClass& a) { libName = "ExampleLCD/LCD"; a.registerLibrary(this); } void setup() { lcd = 0; } void commandHandler(uint8_t cmdId, uint8_t* data, uint8_t datasz) { switch(cmdId) { case LCD_INIT: { // 0 - 5 = pins to use if (lcd) { sendErrorMsg_P(LCD_MSG_ALREADY_INITIALIZED); } else if(datasz != 6) { sendInvalidNumArgsMsg(); } else { // rs enable, d0, d1, d2, d3 lcd = new LiquidCrystal(data[0], data[1], data[2], data[3], data[4], data[5]); lcd->begin(16, 2); lcd->clear(); sendResponseMsg(cmdId, data, 1); } break; } case LCD_FREE: { if (!lcd) { sendErrorMsg_P(LCD_MSG_NOT_INITIALIZED); } else { delete lcd; lcd = 0; sendResponseMsg(cmdId, 0, 0); } break; } case LCD_CLEAR: { if (!lcd) { sendErrorMsg_P(LCD_MSG_NOT_INITIALIZED); } else { lcd->clear(); sendResponseMsg(cmdId, 0, 0); } break; } case LCD_PRINT: { if (!lcd) { sendErrorMsg_P(LCD_MSG_NOT_INITIALIZED); } else if(datasz > 0) { lcd->print((const char *)data); sendResponseMsg(cmdId, 0, 0); } else { sendInvalidNumArgsMsg(); } break; } case LCD_SETCURSOR: { if (!lcd) { sendErrorMsg_P(LCD_MSG_NOT_INITIALIZED); } else if(datasz == 2) { lcd->setCursor(data[0], data[1]); sendResponseMsg(cmdId, 0, 0); } else { sendInvalidNumArgsMsg(); } break; } default: { // notify of invalid cmd sendUnknownCmdIDMsg(); } break; } } }; arduino-0.12.1/inst/+arduinoioaddons/+RTCAddon/0000755000000000000000000000000014545566645016071 5ustar00arduino-0.12.1/inst/+arduinoioaddons/+RTCAddon/DS1307.m0000644000000000000000000001740214545566645017074 0ustar00## Copyright (C) 2018-2020 John Donoghue ## ## 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 ## . classdef DS1307 < arduinoio.LibraryBase ## -*- texinfo -*- ## @deftypefn {} {} arduinoioaddons.RTCAddon.DS1307 ## DS1307 addon ## ## @seealso{addon} ## @end deftypefn ## ## @subsubheading Properties ## @var{Parent} - the parent arduino object. ## ## @var{Pins} - the pins allocated the addon. ## ## @subheading Methods ## @deftypefn {} {@var{obj} =} DS1307(@var{arObj}) ## @deftypefnx {} {@var{obj} =} DS1307(@var{arObj}, @var{propertyname, propertyvalue} ....) ## Constructor to create DS1307 addon ## @subsubheading Inputs ## @var{arObj} - the arduino parent object ## ## @var{propertyname, propertyvalue} - optional property name, value pairs. ## Current known properties are: ## @table @asis ## @item address ## I2C address of the DS1307 (default 0x68) ## @end table ## ## @subsubheading Outputs ## @var{obj} - created DS1307 object ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## rtc = addon(a, "rtcaddon/ds1307") ## } ## @end example ## @end deftypefn ## ## @deftypefn {} {@var{date} =} clock(@var{dsObj}) ## @deftypefnx {} {} clock(@var{dsObj}, @var{date}) ## Get/set the DS1307 clock ## ## @subsubheading Inputs ## @var{dsObj} - the ds1307 object ## ## @var{date} - a date vector in same format as datevec and clock ## ## @subsubheading Outputs ## @var{date} - a date vector in same format as datevec and clock ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## rtc = addon(a, "rtcaddon/ds1307") ## # get and display rtc time as a date string ## datestr(rtc.clock) ## } ## @end example ## @seealso{datevec} ## @end deftypefn ## ## @deftypefn {} {@var{ctrl} =} control(@var{dsObj}) ## @deftypefnx {} {} control(@var{dsObj}, @var{ctrl}) ## Get/set the DS1307 clock ## ## @subsubheading Inputs ## @var{dsObj} - the ds1307 object ## ## @var{ctrl} - a structure containing the control bit fields. ## ## @subsubheading Outputs ## @var{ctrl} - a structure containing the control bit fields. ## ## Control structure fields are: ## Current properties are: ## @table @asis ## @item out ## Out bit in the control register ## @item sqwe ## Square wave enable bit in control register ## @item rs ## The combined RS0, RS1 value ## @end table ## ## @end deftypefn ## ## @deftypefn {} {@var{YN} =} isstarted(@var{dsObj}) ## Get whether the RTC clock is currently counting time ## ## @subsubheading Inputs ## @var{dsObj} - the ds1307 object ## ## @subsubheading Outputs ## @var{YN} - returns true if the RTC is counting ## ## @seealso{start, stop} ## @end deftypefn ## ## @deftypefn {} {} start(@var{dsObj}) ## Start the RTC counting ## ## @subsubheading Inputs ## @var{dsObj} - the ds1307 object ## ## @subsubheading Outputs ## None ## ## @seealso{datevec} ## @end deftypefn ## ## @deftypefn {} {} stop(@var{dsObj}) ## Stop the RTC counting ## ## @subsubheading Inputs ## @var{dsObj} - the ds1307 object ## ## @subsubheading Outputs ## None ## ## @seealso{datevec} ## @end deftypefn # commands properties(Access = private, Constant = true) INIT_COMMAND = hex2dec('00'); endproperties properties(Access = protected, Constant = true) LibraryName = 'RTCAddon/DS1307'; DependentLibraries = { "i2c" }; ArduinoLibraryHeaderFiles = {}; CppHeaderFile = fullfile(arduinoio.FilePath(mfilename('fullpath')), 'DS1307Addon.h'); CppClassName = 'DS1307Addon'; endproperties properties(Access = private) i2c; address; bcd2dec = @(v) bitshift(v, -4)*10 + bitand(v, 0xf); dec2bcd = @(v) bitshift(floor(v/10), 4) + bitand(mod(v,10), 0xf); endproperties methods # constructor function obj = DS1307(parentObj, varargin) # parse args p = inputParser(CaseSensitive=false, FunctionName='RTCAddon/DS1307'); p.addParameter('Address', 0x68, @isnumeric); p.parse(varargin{:}); # do we have the address ? address = p.Results.Address; i2caddresses = scanI2Cbus(parentObj); idx = find(cellfun ( @(x) strcmp(x, sprintf("0x%02X", address)), i2caddresses)); if isempty(idx) error('RTCAddon/DS1307: matching i2c address found on bus'); endif obj.Parent = parentObj; obj.address = p.Results.Address; obj.i2c = device(parentObj, "i2caddress", obj.address); obj.Pins = obj.i2c.Pins; # our arduino part isn't needed as we are really just using the i2c, but # we have to have the arduino part for lib detections, so lets # send a message to it on init anyway in case sometime in the future # we end up having it do something data = sendCommand(obj.Parent, obj.LibraryName, obj.INIT_COMMAND, []); endfunction function c = clock (obj, settime) if nargin == 2 # set time wd = weekday(datenum(settime)); writeRegister(obj.i2c, 0, ... [obj.dec2bcd(floor(settime(6))), obj.dec2bcd(settime(5)), (obj.dec2bcd(settime(4))), ... wd, obj.dec2bcd(settime(3)), obj.dec2bcd(settime(2)), obj.dec2bcd(mod(settime(1),100))] ... ); else # get time data = readRegister(obj.i2c, 0, 7); secs = double(obj.bcd2dec(bitand(data(1), 0x7f))); mins = double(obj.bcd2dec(data(2))); if bitand(data(3), 0x40) != 0 # 12 hr pm = bitand(data(3), 0x20); hrs = double(obj.bcd2dec(bitand(data(3), 0x2f))); if pm hrs = double(hrs + 12); endif else hrs = double(obj.bcd2dec(bitand(data(3), 0x3f))); endif wday = double(data(4)); day = double(obj.bcd2dec(data(5))); month = double(obj.bcd2dec(data(6))); year = 2000.0 + double(obj.bcd2dec(data(7))); c = double([year, month, day, hrs, mins, secs]); endif endfunction function start(obj) data = readRegister(obj.i2c, 0, 1); data = bitset(data, 8, 0); writeRegister(obj.i2c, 0, data); endfunction function stop(obj) data = readRegister(obj.i2c, 0, 1); data = bitset(data, 8, 1); writeRegister(obj.i2c, 0, data); endfunction function val = isstarted(obj) data = readRegister(obj.i2c, 0, 1); val = bitget(data, 8) == 0; endfunction function bits = control(obj, setbits) if nargin == 1 data = readRegister(obj.i2c, 7, 1); bits = {}; bits.out = bitget(data, 8); bits.sqwe = bitget(data, 5); bits.rs = bitand(data, 0x03); else data = 0; data = bitand(setbits.rs, 0x3); if setbits.out data = data + 0x80; endif if setbits.sqwe data = data + 0x10; endif writeRegister(obj.i2c, 7, data); endif endfunction function disp(this) printf(" %s with properties\n", class(this)); printf(" Address = 0x%X\n", this.address); # show i2c pins as the pins printf(" Pins = {\n"); for i=1:numel(this.Pins) printf(" %s\n", this.Pins{i}); endfor printf(" }\n"); endfunction endmethods endclassdef arduino-0.12.1/inst/+arduinoioaddons/+RTCAddon/DS1307Addon.h0000644000000000000000000000234214545566645020032 0ustar00/* * Copyright (C) 2018 John Donoghue * * 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 * . */ #include "LibraryBase.h" #define DS1307_INIT 0x00 class DS1307Addon : public LibraryBase { public: DS1307Addon(OctaveArduinoClass& a) { libName = "RTCAddon/DS1307"; a.registerLibrary(this); } void commandHandler(uint8_t cmdId, uint8_t* data, uint8_t datasz) { switch(cmdId) { case DS1307_INIT: { sendResponseMsg(cmdId, data, 1); break; } default: { // notify of invalid cmd sendUnknownCmdIDMsg(); } break; } } }; arduino-0.12.1/inst/+arduinoioaddons/+SimpleStepper/0000755000000000000000000000000014545566645017267 5ustar00arduino-0.12.1/inst/+arduinoioaddons/+SimpleStepper/SimpleStepper.m0000644000000000000000000002216614545566645022250 0ustar00## Copyright (C) 2022 John Donoghue ## ## 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 ## . classdef SimpleStepper < arduinoio.LibraryBase ## -*- texinfo -*- ## @deftypefn {} {} arduinoioaddons.SimpleStepper ## Stepper class for stepper control using ULN2003 and compatible drivers ## @end deftypefn ## ## @subsubheading Properties ## @table @asis ## @item @var{Id} ## Id of the stepper (Read only) ## @item @var{Speed} ## Number of steps to do per second. ## @item Status ## Status of stepper (Read only). ## 0 = not moving, 1 = moving, 2 = rotating ## @item Parent ## the Arduino parent (read only) ## @item Pins ## the pins used for the stepper (read only) ## @end table ## ## @subheading Methods ## @deftypefn {} {@var{obj} =} SimpleStepper(@var{aObj}, @var{pin1}, @var{pin2}, @var{pin3}, @var{pin4}) ## @deftypefnx {} {@var{obj} =} SimpleStepper(@var{aObj}, @var{pin1}, @var{pin2}, @var{pin3}, @var{pin4}, @var{pin5}) ## Constructor to create a stepper object ## @subsubheading Inputs ## @var{aObj} - The arduino ## ## @var{pin1} - The first pin of the controller ## ## @var{pin2} - The second pin of the controller ## ## @var{pin3} - The third pin of the controller ## ## @var{pin4} - The fourth pin of the controller ## ## @var{pin5} - The fifth pin of the controller ## ## @subsubheading Outputs ## @var{s} - a simplestepper object ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## # create stepper object ## s = addon(a, "simplestepper/simplestepper", "d2", "d3", "d4", "d5") ## # start rotating left ## s.rotate(-1); ## } ## @end example ## ## @seealso{addon} ## @end deftypefn ## ## @deftypefn {} {} move(@var{sObj}, @var{steps}) ## Move the motor the specified number of steps using the configured Speed. ## ## @subsubheading Inputs ## @var{sObj} - the stepper object ## ## @var{steps} - the number of steps to move. steps less than 0 will be moving left. ## ## @subsubheading Outputs ## None ## ## @seealso{rotate} ## @end deftypefn ## ## @deftypefn {} {} rotate(@var{sObj}, @var{dir}) ## Start steppermotor moving in the specified direction using the configured Speed. ## ## @subsubheading Inputs ## @var{sObj} - the stepper object ## ## @var{dir} - Direction to move. -1 = left, 0 = stop, 1 = right. ## ## @subsubheading Outputs ## None ## ## @seealso{move} ## @end deftypefn ## ## @deftypefn {} {} release(@var{sObj}) ## Release this stepper motor ## ## @subsubheading Inputs ## @var{sObj} - the stepper object ## ## @subsubheading Outputs ## None ## ## @end deftypefn properties(Access = public) Speed = 1; # num secs per tick endproperties properties(GetAccess = public, SetAccess = private) Id = 0; # Id of the object Status = 0; # Status 0,1,2 Pins = []; # pins allocated to this stepper endproperties properties(Access = private) # pin info of pins used by this object PinInfo = []; # var for scope of cleanupduring release cleanup; endproperties properties(Access = protected, Constant = true) # addon properties LibraryName = 'SimpleStepper/SimpleStepper'; CppHeaderFile = fullfile(arduinoio.FilePath(mfilename('fullpath')), 'src', 'SimpleStepperAddon.h'); CppSourceFile = fullfile(arduinoio.FilePath(mfilename('fullpath')), 'src', 'SimpleStepperAddon.cpp'); CppClassName = 'SimpleStepperAddon'; endproperties properties(Access = private, Constant = true) # command will send to the arduino INIT_COMMAND = 0x00; MOVE_COMMAND = 0x01; ROTATE_COMMAND = 0x02; TICKSPERSTEP_COMMAND = 0x03; STATUS_COMMAND = 0x04; RELEASE_COMMAND = 0x10; STATE_COMMAND = 0x20; endproperties methods function obj = SimpleStepper(parentObj, varargin) if (!isa (parentObj, "arduino")) error("expects arduino object"); endif obj.Parent = parentObj; obj.PinInfo = []; # pins follow tmp_pins = {}; for i = 1:length(varargin) validatePin(obj.Parent, varargin{1}, 'digital') tmp_pins{end+1} = getPinInfo(obj.Parent, varargin{i}); endfor if length(tmp_pins) < 4 || length(tmp_pins) > 5 error("expected 4 or 5 pins"); endif obj.PinInfo = tmp_pins; try data = []; for i = 1:length(tmp_pins) configurePin(obj.Parent, tmp_pins{i}.name, "digitaloutput") configurePinResource (obj.Parent, tmp_pins{i}.name, obj.LibraryName, "digitaloutput", true); data(end+1) = tmp_pins{i}.terminal; endfor # use smallest num for id obj.Id = min(data); #obj.Parent.debug =1; [tmp, sz] = sendCommand(obj.Parent, obj.LibraryName, obj.INIT_COMMAND, uint8([obj.Id data])); catch for i=1:numel(tmp_pins) configurePinResource(obj.Parent, tmp_pins{i}.name, tmp_pins{i}.owner, tmp_pins{i}.mode, true) configurePin(obj.Parent, tmp_pins{i}.name, tmp_pins{i}.mode) endfor rethrow (lasterror); end_try_catch obj.cleanup = onCleanup (@() sendCommand(obj.Parent, obj.LibraryName, obj.RELEASE_COMMAND, [obj.Id])); endfunction function release(obj) obj.cleanup = []; # called from cleanup sendCommand(obj.Parent, obj.RELEASE_COMMAND,[obj.Id]); for i=1:numel(obj.PinInfo) configurePinResource(obj.Parent, obj.PinInfo{i}.name, obj.PinInfo{i}.owner, obj.PinInfo{i}.mode, true) configurePin(obj.Parent, obj.PinInfo{i}.name, obj.PinInfo{i}.mode) endfor endfunction function move(obj, steps) cmdID = obj.MOVE_COMMAND; intval = int32(steps); data = [ bitand(bitshift(intval,-24), 255) bitand(bitshift(intval,-16),255) bitand(bitshift(intval,-8),255) bitand(intval, 255)]; sendCommand(obj.Parent, obj.LibraryName, cmdID, [obj.Id data]); endfunction function rotate(obj, dir) cmdID = obj.ROTATE_COMMAND; if dir < -1 || dir > 1 error ("Expected dir to be -1, 0 or 1."); endif dir = typecast(int8(dir), "uint8"); sendCommand(obj.Parent, obj.LibraryName, cmdID, uint8([obj.Id dir])); endfunction function disp(this) printf(" %s with properties\n", class(this)); printf(" Speed = %f\n", this.Speed); printf(" Status = %d\n", this.Status); printf(" Pins = {\n"); for i=1:numel(this.PinInfo) printf(" %s\n", this.PinInfo{i}.name); endfor printf(" }\n"); endfunction endmethods methods (Hidden = true) function retval = state(obj) cmdID = obj.STATE_COMMAND; data = sendCommand(obj.Parent, obj.LibraryName, cmdID, uint8([obj.Id])); retval = {}; retval.Id = data(1); retval.NumPins = double(data(2)); retval.Pins = []; retval.Pins(1) = double(data(3)); retval.Pins(2) = double(data(4)); retval.Pins(3) = double(data(5)); retval.Pins(4) = double(data(6)); retval.Pins(5) = double(data(7)); retval.Status = data(8); retval.Direction = double(typecast(data(9), 'int8')); val = bitshift(uint32(data(10)), 24) + bitshift(uint32(data(11)), 16) + bitshift(uint32(data(12)), 8) + uint32(data(13)); retval.StepsToDo = val; val = bitshift(uint32(data(14)), 24) + bitshift(uint32(data(15)), 16) + bitshift(uint32(data(16)), 8) + uint32(data(17)); retval.TicksPerStep = val; val = bitshift(uint32(data(18)), 24) + bitshift(uint32(data(19)), 16) + bitshift(uint32(data(20)), 8) + uint32(data(21)); retval.LastStepTick = val; endfunction function status = get.Status(obj) cmdID = obj.STATUS_COMMAND; data = sendCommand(obj.Parent, obj.LibraryName, cmdID, [obj.Id]); status = data(2); endfunction function set.Speed(obj, speedval) cmdID = obj.TICKSPERSTEP_COMMAND; if speedval == 0 ticks = 0; elseif(speedval < 0) error ("speed should be number of steps per second"); else ticks = 1000000/speedval; endif intval = uint32(ticks) data = [ bitand(bitshift(intval,-24), 255) bitand(bitshift(intval,-16),255) bitand(bitshift(intval,-8),255) bitand(intval, 255)]; sendCommand(obj.Parent, obj.LibraryName, cmdID, [obj.Id data]); obj.Speed = speedval; endfunction function pins = get.Pins(obj) pins = {}; for i=1:numel (obj.PinInfo) pins{end+1} = obj.PinInfo{i}.name; endfor endfunction endmethods endclassdef arduino-0.12.1/inst/+arduinoioaddons/+SimpleStepper/src/0000755000000000000000000000000014545566645020056 5ustar00arduino-0.12.1/inst/+arduinoioaddons/+SimpleStepper/src/SimpleStepperAddon.cpp0000644000000000000000000003221414545566645024326 0ustar00/* * Copyright (C) 2022 John Donoghue * * 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 * . */ #include "SimpleStepperAddon.h" class AddonStepper { public: uint8_t id; uint8_t curr_step; int8_t direction; uint8_t num_pins; uint8_t pins[5]; unsigned long steps_to_do; unsigned long ticksperstep; unsigned long laststeptick; AddonStepper() { num_pins=0; id=0;} uint8_t status() const { uint8_t s = 0; if (num_pins) { if (direction) s = 2; if (steps_to_do) s = 1; } return s; } unsigned getStepsLeft() const { return steps_to_do; } void setTicksPerStep(unsigned long ticks) { if(ticks == 0) { direction = 0; steps_to_do = 0; } else { ticksperstep = ticks; } } unsigned long getTicksPerStep() const { return ticksperstep; } bool attach(uint8_t id, uint8_t pin1, uint8_t pin2, uint8_t pin3, uint8_t pin4) { detach(); this->id = id; num_pins = 4; pins[0] = pin1; pins[1] = pin2; pins[2] = pin3; pins[3] = pin4; pinMode(pins[0], OUTPUT); pinMode(pins[1], OUTPUT); pinMode(pins[2], OUTPUT); pinMode(pins[3], OUTPUT); direction = 0; laststeptick = 0; curr_step = 0; ticksperstep = 1000000L; steps_to_do = 0; return true; } bool attach(uint8_t id, uint8_t pin1, uint8_t pin2, uint8_t pin3, uint8_t pin4, uint8_t pin5) { detach(); this->id = id; num_pins = 5; pins[0] = pin1; pins[1] = pin2; pins[2] = pin3; pins[3] = pin4; pins[4] = pin5; pinMode(pins[0], OUTPUT); pinMode(pins[1], OUTPUT); pinMode(pins[2], OUTPUT); pinMode(pins[3], OUTPUT); pinMode(pins[4], OUTPUT); direction = 0; laststeptick = 0; curr_step = 0; ticksperstep = 1000000L; steps_to_do = 0; return true; } void detach() { if (num_pins) { digitalWrite(pins[0], LOW); digitalWrite(pins[1], LOW); digitalWrite(pins[2], LOW); digitalWrite(pins[3], LOW); if (num_pins > 4) digitalWrite(pins[4], LOW); } num_pins = 0; } void move(long steps) { direction = 0; steps_to_do = abs(steps); if (steps < 0) { direction = -1; } else { direction = 1; } } void rotate(int8_t dir) { steps_to_do = 0; direction = dir; } void poll() { if (num_pins) { unsigned long now = micros(); if (now - laststeptick >= ticksperstep) { laststeptick = now; if (direction > 0) { curr_step ++; } else if (direction < 0) { if (curr_step == 0) { // dependant on num pins if (num_pins == 4) curr_step = 4; else curr_step = 10; } curr_step --; } else { // no change in step num } // mod based on num pins if (num_pins == 4) { curr_step = curr_step % 4; step4(curr_step); } if (num_pins == 5) { curr_step = curr_step % 10; step5(curr_step); } // moving X steps if (direction != 0 && steps_to_do) { steps_to_do --; if (steps_to_do == 0) direction = 0; } } } } void step5(int step) { // 5 pin switch(step) { case 0: // 01101 digitalWrite(pins[0], LOW); digitalWrite(pins[1], HIGH); digitalWrite(pins[2], HIGH); digitalWrite(pins[3], LOW); digitalWrite(pins[4], HIGH); break; case 1: // 01001 digitalWrite(pins[0], LOW); digitalWrite(pins[1], HIGH); digitalWrite(pins[2], LOW); digitalWrite(pins[3], LOW); digitalWrite(pins[4], HIGH); break; case 2: // 01011 digitalWrite(pins[0], LOW); digitalWrite(pins[1], HIGH); digitalWrite(pins[2], LOW); digitalWrite(pins[3], HIGH); digitalWrite(pins[4], HIGH); break; case 3: // 01010 digitalWrite(pins[0], LOW); digitalWrite(pins[1], HIGH); digitalWrite(pins[2], LOW); digitalWrite(pins[3], HIGH); digitalWrite(pins[4], LOW); break; case 4: // 11010 digitalWrite(pins[0], HIGH); digitalWrite(pins[1], HIGH); digitalWrite(pins[2], LOW); digitalWrite(pins[3], HIGH); digitalWrite(pins[4], LOW); break; case 5: // 10010 digitalWrite(pins[0], HIGH); digitalWrite(pins[1], LOW); digitalWrite(pins[2], LOW); digitalWrite(pins[3], HIGH); digitalWrite(pins[4], LOW); break; case 6: // 10110 digitalWrite(pins[0], HIGH); digitalWrite(pins[1], LOW); digitalWrite(pins[2], HIGH); digitalWrite(pins[3], HIGH); digitalWrite(pins[4], LOW); break; case 7: // 10100 digitalWrite(pins[0], HIGH); digitalWrite(pins[1], LOW); digitalWrite(pins[2], HIGH); digitalWrite(pins[3], LOW); digitalWrite(pins[4], LOW); break; case 8: // 10101 digitalWrite(pins[0], HIGH); digitalWrite(pins[1], LOW); digitalWrite(pins[2], HIGH); digitalWrite(pins[3], LOW); digitalWrite(pins[4], HIGH); break; case 9: // 00101 digitalWrite(pins[0], LOW); digitalWrite(pins[1], LOW); digitalWrite(pins[2], HIGH); digitalWrite(pins[3], LOW); digitalWrite(pins[4], HIGH); break; } } void step4(int step) { // 4 pin switch(step) { case 0: // 1010 digitalWrite(pins[0], HIGH); digitalWrite(pins[1], LOW); digitalWrite(pins[2], HIGH); digitalWrite(pins[3], LOW); break; case 1: // 0110 digitalWrite(pins[0], LOW); digitalWrite(pins[1], HIGH); digitalWrite(pins[2], HIGH); digitalWrite(pins[3], LOW); break; case 2: //0101 digitalWrite(pins[0], LOW); digitalWrite(pins[1], HIGH); digitalWrite(pins[2], LOW); digitalWrite(pins[3], HIGH); break; case 3: //1001 digitalWrite(pins[0], HIGH); digitalWrite(pins[1], LOW); digitalWrite(pins[2], LOW); digitalWrite(pins[3], HIGH); break; } } }; #ifndef MAX_SIMPLESTEPPERS # define MAX_SIMPLESTEPPERS 4 #endif static AddonStepper steppers[MAX_SIMPLESTEPPERS]; static AddonStepper * getStepper (uint8_t id) { uint8_t i; AddonStepper * unused = 0; for (i=0;iattach(data[0], data[1], data[2], data[3], data[4]); sendResponseMsg(cmdID, data, 1); } else if(stepper && datasz == 6) { stepper->attach(data[0], data[1], data[2], data[3], data[4], data[5]); sendResponseMsg(cmdID, data, 1); } else { // really should be a run out resources error sendErrorMsg_P (ERRORMSG_INVALID_ARGS); } break; } case SIMPLESTEPPERADDON_RELEASE: { AddonStepper * stepper = getStepper (data[0]); if(stepper && datasz == 1) { stepper->detach(); sendResponseMsg(cmdID, data, 1); } else { sendErrorMsg_P (ERRORMSG_INVALID_ARGS); } break; } case SIMPLESTEPPERADDON_MOVE: { AddonStepper * stepper = getStepper (data[0]); if (stepper && datasz == 5) { long steps = ((long)data[1] << 24) | ((long)data[2] << 16) | ((long)data[3] << 8) | (long)data[4]; stepper->move(steps); sendResponseMsg(cmdID, data, 1); } else { sendErrorMsg_P (ERRORMSG_INVALID_ARGS); } break; } case SIMPLESTEPPERADDON_ROTATE: { AddonStepper * stepper = getStepper (data[0]); if (stepper && datasz == 2) { stepper->rotate((int8_t)data[1]); sendResponseMsg(cmdID, data, 1); } else { sendErrorMsg_P (ERRORMSG_INVALID_ARGS); } break; } case SIMPLESTEPPERADDON_TICKSPERSTEP: { AddonStepper * stepper = getStepper (data[0]); if (stepper && datasz == 5) { unsigned long ticks = ( (unsigned long)data[1] << 24) | ((unsigned long)data[2] << 16) | ((unsigned long)data[3] << 8) | (unsigned long)data[4]; stepper->setTicksPerStep(ticks); sendResponseMsg(cmdID, data, 1); } else if(stepper && datasz == 1) { unsigned long t = stepper->getTicksPerStep(); data[1] = (t>>24)&0xff; data[2] = (t>>16)&0xff; data[3] = (t>>8)&0xff; data[4] = (t)&0xff; datasz = 5; sendResponseMsg (cmdID, data, datasz); } else { sendErrorMsg_P (ERRORMSG_INVALID_ARGS); } break; } case SIMPLESTEPPERADDON_STATUS: { AddonStepper * stepper = getStepper (data[0]); if (stepper && datasz == 1) { data[1] = stepper->status(); sendResponseMsg (cmdID, data, 2); } else { sendErrorMsg_P (ERRORMSG_INVALID_ARGS); } break; } case SIMPLESTEPPERADDON_STATE: { AddonStepper * stepper = getStepper (data[0]); if (stepper && datasz == 1) { data[1] = stepper->num_pins; data[2] = stepper->pins[0]; data[3] = stepper->pins[1]; data[4] = stepper->pins[2]; data[5] = stepper->pins[3]; data[6] = stepper->pins[4]; data[7] = stepper->status(); data[8] = stepper->direction; unsigned long t = stepper->steps_to_do; data[9] = (t>>24)&0xff; data[10] = (t>>16)&0xff; data[11] = (t>>8)&0xff; data[12] = (t)&0xff; t = stepper->ticksperstep; data[13] = (t>>24)&0xff; data[14] = (t>>16)&0xff; data[15] = (t>>8)&0xff; data[16] = (t)&0xff; t = stepper->laststeptick; data[17] = (t>>24)&0xff; data[18] = (t>>16)&0xff; data[19] = (t>>8)&0xff; data[20] = (t)&0xff; sendResponseMsg (cmdID, data, 21); } else { sendErrorMsg_P (ERRORMSG_INVALID_ARGS); } break; } default: { // notify of invalid cmd sendUnknownCmdIDMsg(); } } } void SimpleStepperAddon::loop() { for (int i = 0;i * * 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 * . */ #include "LibraryBase.h" class SimpleStepperAddon : public LibraryBase { public: SimpleStepperAddon(OctaveArduinoClass& a); void commandHandler(uint8_t cmdID, uint8_t* data, uint8_t datasz); virtual void loop(); }; arduino-0.12.1/inst/+arduinoioaddons/+adafruit/0000755000000000000000000000000014545566645016272 5ustar00arduino-0.12.1/inst/+arduinoioaddons/+adafruit/dcmotorv2.m0000644000000000000000000001200014545566645020360 0ustar00## Copyright (C) 2018-2020 John Donoghue ## ## 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 ## . classdef dcmotorv2 < arduinoio.AddonBase ## -*- texinfo -*- ## @deftypefn {} {} arduinoioaddons.adafruit.dcmotorv2 ## DC Motor class for dc motor control on the adafruit motor shield ## ## @seealso{arduinoioaddons.adafruit.motorshieldv2} ## @end deftypefn ## ## @subsubheading Properties ## @var{Speed} - The speed value set for the motor ## ## @var{Parent} - The parent shield for object (read only) ## ## @var{MotorNumber} - The motor number (read only) values 1-4 ## ## @var{IsRunning} - boolean for if the motor is started (read only) ## ## @subheading Methods ## @deftypefn {} {@var{obj} =} dcmotorv2(@var{mObj}, @var{mnum}) ## @deftypefnx {} {@var{obj} =} dcmotorv2(@var{mObj}, @var{mnum}, @var{propertyname, propertyvalue} ....) ## Constructor to create dcmotor object ## @subsubheading Inputs ## @var{mObj} - the motor shield object ## ## @var{mnum} - The motor number (1 - 4) ## ## @var{propertyname, propertyvalue} - Optional property name/value ## pairs to pass to motor object. ## ## Current known properties are: ## @table @asis ## @item Speed ## Initial speed (default 0). Should be a value between -1 and 1. ## @end table ## ## @subsubheading Outputs ## @var{s} - a dcmotorv2 object ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## ms = addon(a, "adafruit/motorshieldv2") ## mtr = dcmotor(ms, 1) ## } ## @end example ## @end deftypefn ## ## @deftypefn {} {} start(@var{dcObj}) ## Start the motor moving in previously set speed/direction ## ## @subsubheading Inputs ## @var{dcObj} - the dcmotor object ## ## @subsubheading Outputs ## None ## ## @seealso{adafruit.motorshieldv2} ## @end deftypefn ## ## @deftypefn {} {} stop(@var{dcObj}) ## Stop the motor moving ## ## @subsubheading Inputs ## @var{dcObj} - the dcmotor object ## ## @subsubheading Outputs ## None ## ## @seealso{adafruit.motorshieldv2} ## @end deftypefn properties(Access = private, Constant = true) INIT_COMMAND = hex2dec('20'); FREE_COMMAND = hex2dec('21'); START_COMMAND = hex2dec('22'); STOP_COMMAND = hex2dec('23'); endproperties properties(Access = private) cleanup; endproperties properties(GetAccess = public, SetAccess = private) MotorNumber; IsRunning = false; endproperties properties(Access = public) Speed = 0; endproperties methods function this = dcmotorv2(shield, mnum, varargin) validate_shield = @(x) isa(x, "arduinoioaddons.adafruit.motorshieldv2"); validate_mtrnum = @(x) (isnumeric(x) && isscalar(x) && (x >= 1 && x <= 4)); validate_speed = @(x) (isnumeric(x) && (x <= 1 && x >= -1)); p = inputParser(CaseSensitive=false, FunctionName='adafruit/dcmotorv2'); p.addRequired('shield',validate_shield); p.addRequired('mnum',validate_mtrnum); p.addParameter('Speed', 0, validate_speed); p.parse(shield, mnum, varargin{:}); this.Parent = p.Results.shield; this.MotorNumber = p.Results.mnum; this.Speed = p.Results.Speed; sendCommand(this.Parent, this.INIT_COMMAND,[this.MotorNumber-1]); this.cleanup = onCleanup (@() sendCommand(this.Parent, this.FREE_COMMAND, [this.MotorNumber-1])); endfunction function start(this) if this.Speed < 0 direction = 0; speed = -this.Speed*255; else direction = 1; speed = this.Speed*255; endif sendCommand(this.Parent,this.START_COMMAND,[this.MotorNumber-1, direction, speed]); this.IsRunning = true; endfunction function stop(this) sendCommand(this.Parent,this.STOP_COMMAND,[this.MotorNumber-1]); this.IsRunning = false; endfunction function set.Speed(this, newspeed) # check speed -1 .. 0 ... 1 if !isnumeric(newspeed) || newspeed < -1 || newspeed > 1 error("Speed should be between -1 .. 1"); endif this.Speed = newspeed; if this.IsRunning start(this); endif endfunction function disp(this) printf(" %s with properties\n", class(this)); printf(" MotorNumber = %d\n", this.MotorNumber); printf(" Speed = %d\n", this.Speed); printf(" IsRunning = %d\n", this.IsRunning); endfunction endmethods endclassdef arduino-0.12.1/inst/+arduinoioaddons/+adafruit/motorshieldv2.h0000644000000000000000000001643714545566645021257 0ustar00/* * Copyright (C) 2018 John Donoghue * * 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 * . */ #include "LibraryBase.h" #define MTRV2_INIT 0x00 #define MTRV2_FREE 0x01 #define MTRV2_INIT_STEPPER 0x10 #define MTRV2_FREE_STEPPER 0x11 #define MTRV2_MOVE_STEPPER 0x12 #define MTRV2_RELEASE_STEPPER 0x13 #define MTRV2_INIT_DCMOTOR 0x20 #define MTRV2_FREE_DCMOTOR 0x21 #define MTRV2_START_DCMOTOR 0x22 #define MTRV2_STOP_DCMOTOR 0x23 // must add the adatfruit morotrshieldv2 library to arduino for this to compile #include // Create the motor shield object with the default I2C address //Adafruit_MotorShield AFMS = Adafruit_MotorShield(); // Or, create it with a different I2C address (say for stacking) // Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x61); // Select which 'port' M1, M2, M3 or M4. In this case, M1 //Adafruit_DCMotor *myMotor = AFMS.getMotor(0); class MotorShieldV2Addon : public LibraryBase { Adafruit_MotorShield *AFMS; Adafruit_StepperMotor *stepperMotor[2]; Adafruit_DCMotor *dcMotor[4]; public: MotorShieldV2Addon(OctaveArduinoClass& a) { libName = "adafruit/MotorShieldV2"; a.registerLibrary(this); } void init() { byte i; AFMS = 0; for (i=0;i<2;i++) { stepperMotor[i] = 0; } for (i=0;i<4;i++) { dcMotor[i] = 0; } // AFMS.getStepper(200, 2); // myMotor->setSpeed(10); // 10 rpm // myMotor->step(100, FORWARD, SINGLE); // // Adafruit_DCMotor *myMotor = AFMS.getMotor(1); // // turn on motor M1 //myMotor->setSpeed(200); //myMotor->run(RELEASE); // // servo1.attach(10); } void commandHandler(uint8_t cmdId, uint8_t* data, uint8_t datasz) { switch(cmdId) { case MTRV2_INIT: { // send in the address // (currently) we only support a single control board if(datasz != 3) { sendInvalidNumArgsMsg(); } else { // TODO: pwm speed as well AFMS = new Adafruit_MotorShield(data[0]); uint16_t freq = data[1]; freq = (freq<<8)|data[2]; AFMS->begin(freq); // input freq sendResponseMsg(cmdId, data, 1); } break; } case MTRV2_FREE: { if(AFMS) { //AFMS->release(); delete AFMS; AFMS = 0; } sendResponseMsg(cmdId, data, 1); break; } case MTRV2_INIT_DCMOTOR: { // 0 = shieldid (spiaddress) // 1 = motor num if(datasz != 2) { sendInvalidNumArgsMsg(); } else if(data[1] > 3) { // TODO invalid value sendInvalidNumArgsMsg(); } else if(AFMS) { dcMotor[data[1]] = AFMS->getMotor(data[1]+1); if(dcMotor[data[1]]) { dcMotor[data[1]]->setSpeed(0); dcMotor[data[1]]->run(FORWARD); dcMotor[data[1]]->run(RELEASE); sendResponseMsg(cmdId, data, 2); } else { sendInvalidNumArgsMsg(); } } else { sendInvalidNumArgsMsg(); } break; } case MTRV2_FREE_DCMOTOR: { // 0 = shieldid (spiaddress) // 1 = motor num if(datasz != 2) { sendInvalidNumArgsMsg(); } else if(data[1] > 3) { // TODO invalid value sendInvalidNumArgsMsg(); } else { if(dcMotor[data[1]]) { //dcMotor[data[1]]->run(RELEASE); dcMotor[data[1]]->setSpeed(0); dcMotor[data[1]]->run(RELEASE); dcMotor[data[1]] = 0; } sendResponseMsg(cmdId, data, 2); } break; } case MTRV2_STOP_DCMOTOR: { // 0 = shieldid (spiaddress) // 1 = motor num if(datasz != 2) { sendInvalidNumArgsMsg(); } else if(data[1] > 3) { // TODO invalid value sendInvalidNumArgsMsg(); } else { if(dcMotor[data[1]]) { dcMotor[data[1]]->setSpeed(0); dcMotor[data[1]]->run(RELEASE); } sendResponseMsg(cmdId, data, 2); } break; } case MTRV2_START_DCMOTOR: { // 0 = shieldid (spiaddress) // 1 = motor num // 2 = dir 1=forwrf, else reverse // 3 = speed (0..255) if(datasz != 4) { sendInvalidNumArgsMsg(); } else if(data[1] > 3) { // TODO invalid value sendInvalidNumArgsMsg(); } else { if(dcMotor[data[1]]) { dcMotor[data[1]]->setSpeed(data[3]); dcMotor[data[1]]->run((data[2] == 1) ? FORWARD : BACKWARD); sendResponseMsg(cmdId, data, 2); } else { sendInvalidNumArgsMsg(); } } break; } case MTRV2_INIT_STEPPER: { // 0 = shieldid (spiaddress) // 1 = motor num // 2,3 = stepsprerev if(datasz != 4) { sendInvalidNumArgsMsg(); } else if(data[1] > 1) { // TODO invalid value sendInvalidNumArgsMsg(); } else if(AFMS) { uint16_t cnt = data[2]; cnt = (cnt<<8)|data[3]; stepperMotor[data[1]] = AFMS->getStepper(cnt, data[1]+1); if(stepperMotor[data[1]]) { sendResponseMsg(cmdId, data, 2); } else { sendInvalidNumArgsMsg(); } } else { sendInvalidNumArgsMsg(); } break; } case MTRV2_FREE_STEPPER: { // 0 = shieldid (spiaddress) // 1 = motor num if(datasz != 2) { sendInvalidNumArgsMsg(); } else if(data[1] > 1) { // TODO invalid value sendInvalidNumArgsMsg(); } else { if(stepperMotor[data[1]]) { //dcMotor[data[1]]->run(RELEASE); stepperMotor[data[1]]->release(); stepperMotor[data[1]] = 0; } sendResponseMsg(cmdId, data, 2); } break; } case MTRV2_RELEASE_STEPPER: { // 0 = shieldid (spiaddress) // 1 = motor num if(datasz != 2) { sendInvalidNumArgsMsg(); } else if(data[1] > 1) { // TODO invalid value sendInvalidNumArgsMsg(); } else { if(stepperMotor[data[1]]) { stepperMotor[data[1]]->release(); } sendResponseMsg(cmdId, data, 2); } break; } case MTRV2_MOVE_STEPPER: { // 0 = shieldid (spiaddress) // 1 = motor num // 2 = dir 1=forward, else reverse // 3,4 uint16 rpm // 5,6 steps // 7 steptype if(datasz != 8) { sendInvalidNumArgsMsg(); } else if(data[1] > 1) { // TODO invalid value sendInvalidNumArgsMsg(); } else { if(stepperMotor[data[1]]) { uint16_t rpm = data[3]; rpm = rpm<<8 | data[4]; uint16_t steps = data[5]; steps = steps<<8 | data[6]; uint8_t style = data[7]; style = SINGLE; if(style == 1) style = DOUBLE; if(style == 2) style = INTERLEAVE; if(style == 3) style = MICROSTEP; stepperMotor[data[1]]->setSpeed(rpm); sendWaitMsg(); stepperMotor[data[1]]->step(steps, (data[2] == 1) ? FORWARD : BACKWARD, style); sendResponseMsg(cmdId, data, 2); } else { sendInvalidNumArgsMsg(); } } break; } default: { // notify of invalid cmd sendUnknownCmdIDMsg(); } break; } } }; arduino-0.12.1/inst/+arduinoioaddons/+adafruit/motorshieldv2.m0000644000000000000000000001631414545566645021256 0ustar00## Copyright (C) 2018-2020 John Donoghue ## ## 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 ## . classdef motorshieldv2 < arduinoio.LibraryBase ## -*- texinfo -*- ## @deftypefn {} {} arduinoioaddons.adafruit.motorshieldv2 ## Adafruit motor shield addon ## ## @seealso{addon} ## @end deftypefn ## ## @subsubheading Properties ## @var{Parent} - the parent arduino object. ## ## @var{Pins} - the pins allocated the addon. ## ## @var{I2CAddress} - the i2c address used for accessing this shield. ## ## @var{PWMFrequency} - the set PWM frequency for this shield. ## ## @subheading Methods ## @deftypefn {} {@var{obj} =} motorshieldv2(@var{arObj}) ## @deftypefnx {} {@var{obj} =} motorshieldv2(@var{arObj}, @var{propertyname, propertyvalue} ....) ## Constructor to create motorshieldv2 addon object ## @subsubheading Inputs ## @var{arObj} - the arduino parent object ## ## @var{propertyname, propertyvalue} - optional property name, value pairs. ## Current known properties are: ## @table @asis ## @item address ## I2C address of the motor shield (default 0x60) ## @item pwmfrequency ## PWM Frequency to set on shield (default 1600) ## @end table ## ## @subsubheading Outputs ## @var{obj} - created motorshieldv2 object ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## mtr = addon(a, "adafruit/motorshieldv2") ## } ## @end example ## @end deftypefn ## ## @deftypefn {} {@var{s} =} servo(@var{mObj}, @var{mtrnum}) ## @deftypefnx {} {@var{s} =} servo(@var{mObj}, @var{mtrnum}, @var{propertyname}, @var{propertyvalue} ...) ## Create a servo object ## ## @subsubheading Inputs ## @var{mObj} - the motor shield object ## ## @var{mtrnum} - The servo motor number, where 1 is servo on ## pin "d10" and 2 is a servo on pin "d9" ## ## @var{propertyname}, @var{propertyvalue} - Optional property ## name/value pairs to pass to servo object. ## ## Properties are the same as the base servo object. ## ## @subsubheading Outputs ## @var{s} - a servo object ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## ms = addon(a, "adafruit/motorshieldv2") ## # get servo 1 (servo on pin D10) ## s = ms.servo(1) ## } ## @end example ## ## The function if the equivalent of calling the arduino.servo with ## the D9 or D10 pin has the input pin. ## ## @seealso{servo} ## @end deftypefn ## ## @deftypefn {} {@var{s} =} stepper(@var{mObj}, @var{mtrnum}, @var{stepsperrev}) ## @deftypefnx {} {@var{s} =} stepper(@var{mObj}, @var{mtrnum}, @var{stepsperrev}, @var{propertyname}, @var{propertyvalue} ...) ## Create a stepper motor object ## ## @subsubheading Inputs ## @var{mObj} - the motor shield object ## ## @var{mtrnum} - The stepper motor number (1 or 2) ## ## @var{stepsperrev} - Number of steps per revolution. ## ## @var{propertyname}, @var{propertyvalue} - Optional property ## name/value pairs to pass to stepper object. ## ## @subsubheading Outputs ## @var{s} - a stepper object ## ## @end deftypefn ## ## @deftypefn {} {@var{s} =} dcmotor(@var{mObj}, @var{mtrnum}) ## @deftypefnx {} {@var{s} =} dcmotor(@var{mObj}, @var{mtrnum}, @var{propertyname}, @var{propertyvalue} ...) ## Create a dcmotor motor object ## ## @subsubheading Inputs ## @var{mObj} - the motor shield object ## ## @var{mtrnum} - The motor number (1 - 4) ## ## @var{propertyname}, @var{propertyvalue} - Optional property ## name/value pairs to pass to motor object. ## ## @subsubheading Outputs ## @var{s} - a dcmotorv2 object ## ## @end deftypefn # commands properties(Access = private, Constant = true) INIT_COMMAND = hex2dec('00'); FREE_COMMAND = hex2dec('01'); endproperties properties(Access = protected, Constant = true) LibraryName = 'adafruit/MotorShieldV2'; DependentLibraries = { "i2c", "servo" }; ArduinoLibraryHeaderFiles = {}; CppHeaderFile = fullfile(arduinoio.FilePath(mfilename('fullpath')), 'motorshieldv2.h'); CppClassName = 'MotorShieldV2Addon'; endproperties properties(Access = private) i2c; cleanup; endproperties properties(GetAccess = public, SetAccess = private) PWMFrequency; I2CAddress; endproperties methods # constructor function obj = motorshieldv2(parentObj, varargin) # parse args p = inputParser(CaseSensitive=false, FunctionName='adafruit/MotorShieldV2'); p.addParameter('I2CAddress', 0x60, @isnumeric); p.addParameter('PWMFrequency', 1600, @isnumeric); p.parse(varargin{:}); obj.Parent = parentObj; obj.I2CAddress = p.Results.I2CAddress; obj.i2c = device(parentObj, "i2caddress", p.Results.I2CAddress); obj.Pins = obj.i2c.Pins; obj.PWMFrequency = p.Results.PWMFrequency; intval = uint16(obj.PWMFrequency); freq = [ bitshift(intval,-8) bitand(intval, 255)]; data = sendCommand(obj.Parent, obj.LibraryName, obj.INIT_COMMAND, [p.Results.I2CAddress freq]); obj.cleanup = onCleanup (@() sendCommand(obj.Parent, obj.LibraryName, obj.FREE_COMMAND, [p.Results.I2CAddress])); endfunction function s = servo (obj, mnum, varargin) if nargin < 2 error ("Expected shield and mnum") endif pinval = []; if mnum == 1 pinval = "d10"; elseif mnum == 2 pinval = "d9"; else error ("Invalid servo motor number - (should be 1 or 2)") endif s = servo(obj.Parent, pinval, varargin{:}); endfunction function s = stepper (obj, mnum, stepsperrev, varargin) if nargin < 3 error ("Expected shield and mnum and stepsperrev") endif s = arduinoioaddons.adafruit.stepper(obj, mnum, stepsperrev, varargin{:}); endfunction function m = dcmotor (obj, mnum, varargin) if nargin < 2 error ("Expected shield and mnum") endif m = arduinoioaddons.adafruit.dcmotorv2(obj, mnum, varargin{:}); endfunction function disp(this) printf(" %s with properties\n", class(this)); printf(" I2CAddress = %d (0x%X)\n", this.i2c.i2caddress, this.i2c.i2caddress); # show i2c pins as the pins printf(" Pins = {\n"); for i=1:numel(this.Pins) printf(" %s\n", this.Pins{i}); endfor printf(" }\n"); printf(" PWMFrequency = %d\n", this.PWMFrequency); endfunction endmethods methods (Access = public) function data = sendCommand(obj, commandid, data) [data,~] = sendCommand(obj.Parent, obj.LibraryName, commandid, [obj.i2c.i2caddress data]); endfunction endmethods endclassdef arduino-0.12.1/inst/+arduinoioaddons/+adafruit/stepper.m0000644000000000000000000001545214545566645020141 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . classdef stepper < arduinoio.AddonBase ## -*- texinfo -*- ## @deftypefn {} {} arduinoioaddons.adafruit.stepper ## Stepper class for stepper control on the adafruit motor shield ## ## @seealso{arduinoioaddons.adafruit.motorshieldv2} ## @end deftypefn ## ## @subsubheading Properties ## @table @asis ## @item @var{RPM} ## The rpm value set for the stepper motor ## @item StepType ## the StepType for the stepper (string) which can be "single", ## "double", "interleave" or "microstep" ## @item StepsPerRevolution ## the StepsPerRevoluion for the stepper (read only) ## @item MotorNumber ## the motor number for the stepper (read only) value will be 1 or 2. ## @item Parent ## the parent shield of this stepper (read only) ## @end table ## ## @subheading Methods ## @deftypefn {} {@var{obj} =} stepper(@var{mObj}, @var{mnum}, @var{stepsperrev}) ## @deftypefnx {} {@var{obj} =} stepper(@var{mObj}, @var{mnum}, @var{stepsperrev}, @var{propertyname, propertyvalue} ....) ## Constructor to create dcmotor object ## @subsubheading Inputs ## @var{mObj} - the motor shield object ## ## @var{mnum} - The motor number (1 or 2) ## ## @var{stepsperrev} - Number of steps per revolution. ## ## @var{propertyname, propertyvalue} - Optional property ## name/value pairs to pass to motor object. ## ## Current known properties are: ## @table @asis ## @item RPM ## the RPM for the stepper (revolutions per minute) ## @item StepType ## the StepType for the stepper (string) which can be ## "single", "double", "interleave" or "microstep" ## @end table ## ## @subsubheading Outputs ## @var{s} - a stepper object ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## ms = addon(a, "adafruit/motorshieldv2") ## mtr = stepper(ms, 1, 200) ## } ## @end example ## @end deftypefn ## ## @deftypefn {} {} move(@var{sObj}, @var{steps}) ## Move the motor moving in the specified steps using the configured RPM. ## ## @subsubheading Inputs ## @var{sObj} - the stepper object ## ## @subsubheading Outputs ## None ## ## @seealso{adafruit.motorshieldv2} ## @end deftypefn ## ## @deftypefn {} {} release(@var{sObj}) ## Release this motor ## ## @subsubheading Inputs ## @var{sObj} - the stepper object ## ## @subsubheading Outputs ## None ## ## @seealso{adafruit.motorshieldv2} ## @end deftypefn properties(Access = private, Constant = true) INIT_COMMAND = hex2dec('10'); FREE_COMMAND = hex2dec('11'); MOVE_COMMAND = hex2dec('12'); RELEASE_COMMAND = hex2dec('13'); endproperties properties(Access = private) cleanup; endproperties properties(GetAccess = public, SetAccess = private) MotorNumber; StepsPerRevolution = 0; endproperties properties(Access = public) RPM = 0; StepType = "single"; endproperties methods function this = stepper(shield, mnum, stepsperrev, varargin) ## if nargin < 3 ## error ("Expected shield, mnum and stepsperrev") ## endif ## ## if ~isa(shield, "arduinoioaddons.adafruit.motorshieldv2") ## error("Expected shield to be a motorshieldv2 object"); ## endif ## ## # check num is a number ## if mnum != 1 && mnum != 2 ## error("Expected motor number to be 1 or 2"); ## endif p = inputParser(CaseSensitive=false, FunctionName='adafruit/stepper'); validate_shield = @(x) isa(x, "arduinoioaddons.adafruit.motorshieldv2"); validate_mtrnum = @(x) (isnumeric(x) && isscalar(x) && (x ==1 || x ==2)); validate_steps = @(x) (isnumeric(x) && isscalar(x) && (x > 0)); validate_rpm = @(x) (isnumeric(x) && isscalar(x) && (x > 0)); p.addRequired('shield',validate_shield); p.addRequired('mnum',validate_mtrnum); p.addRequired('stepsperrev',validate_steps); p.addParameter('RPM', 0, validate_rpm); p.addParameter('StepType', "single", @(x) any(validatestring(x,{"single", "double", "interleave", "microstep"}))); p.parse(shield, mnum, stepsperrev, varargin{:}); this.Parent = p.Results.shield; this.MotorNumber = p.Results.mnum; this.StepsPerRevolution = p.Results.stepsperrev; this.RPM = p.Results.RPM; this.StepType = p.Results.StepType; intval = uint16(stepsperrev); steps = [ bitshift(intval,-8) bitand(intval, 255)]; sendCommand(this.Parent, this.INIT_COMMAND,[this.MotorNumber-1 steps]); this.cleanup = onCleanup (@() sendCommand(this.Parent, this.FREE_COMMAND, [this.MotorNumber-1 steps])); endfunction function move(this, steps) if steps < 0 direction = 0; steps = -steps; else direction = 1; endif intval = uint16(steps); steps = [ bitshift(intval,-8) bitand(intval, 255)]; intval = uint16(this.RPM); rpm = [ bitshift(intval,-8) bitand(intval, 255)]; steptype = 0; switch lower(this.StepType) case "single" steptype = 0; case "double" steptype = 1; case "interleave" steptype = 2; case "microstep" steptype = 3; endswitch sendCommand(this.Parent,this.MOVE_COMMAND,[this.MotorNumber-1, direction, rpm, steps, steptype]); endfunction function release(this) sendCommand(this.Parent,this.RELEASE_COMMAND,[this.MotorNumber-1]); endfunction function set.RPM(this, newrpm) # check rpm if !isnumeric(newrpm) || newrpm < 0 error("RPM should be a positive number"); endif this.RPM = newrpm; endfunction function set.StepType(this, val) validate_val = validatestring (val, {"single", "double", "interleave", "microstep"}); this.StepType = val; endfunction function disp(this) printf(" %s with properties\n", class(this)); printf(" MotorNumber = %d\n", this.MotorNumber); printf(" RPM = %d\n", this.RPM); printf(" StepsPerRevolution = %d\n", this.StepsPerRevolution); printf(" StepType = %s\n", this.StepType); endfunction endmethods endclassdef arduino-0.12.1/inst/+arduinosensor/0000755000000000000000000000000014545566645014131 5ustar00arduino-0.12.1/inst/+arduinosensor/DS1307.m0000644000000000000000000001603414545566645015134 0ustar00## Copyright (C) 2019-2020 John Donoghue ## ## 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 ## . classdef DS1307 < handle ## -*- texinfo -*- ## @deftypefn {} {} arduinosensor.DS1307 ## DS1307 realtime clock sensor ## @end deftypefn ## ## @subheading Methods ## @deftypefn {} {@var{obj} =} DS1307(@var{arObj}) ## @deftypefnx {} {@var{obj} =} DS1307(@var{arObj}, @var{propertyname, propertyvalue} ....) ## Constructor to create DS1307 sensor ## @subsubheading Inputs ## @var{arObj} - the arduino parent object ## ## @var{propertyname, propertyvalue} - optional property name, value pairs. ## Current known properties are: ## Current properties are: ## @table @asis ## @item i2caddress ## I2C address of the DS1307 (default 0x68) ## @end table ## ## @subsubheading Outputs ## @var{obj} - created DS1307 object ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## rtc = arduinosensor.DS1307(a) ## } ## @end example ## @end deftypefn ## ## @deftypefn {} {@var{date} =} clock(@var{dsObj}) ## @deftypefnx {} {} clock(@var{dsObj}, @var{date}) ## Get/set the DS1307 clock ## ## @subsubheading Inputs ## @var{dsObj} - the ds1307 object ## ## @var{date} - a date vector in same format as datevec and clock ## ## @subsubheading Outputs ## @var{date} - a date vector in same format as datevec and clock ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## rtc = arduinosensor.DS1307(a) ## # get and display rtc time as a date string ## datestr(rtc.clock) ## } ## @end example ## @seealso{datevec} ## @end deftypefn ## ## @deftypefn {} {@var{ctrl} =} control(@var{dsObj}) ## @deftypefnx {} {} control(@var{dsObj}, @var{ctrl}) ## Get/set the DS1307 clock ## ## @subsubheading Inputs ## @var{dsObj} - the ds1307 object ## ## @var{ctrl} - a structure containing the control bit fields. ## ## @subsubheading Outputs ## @var{ctrl} - a structure containing the control bit fields. ## ## Control structure fields are: ## Current properties are: ## @table @asis ## @item out ## Out bit in the control register ## @item sqwe ## Square wave enable bit in control register ## @item rs ## The combined RS0, RS1 value ## @end table ## ## @end deftypefn ## ## @deftypefn {} {@var{YN} =} isstarted(@var{dsObj}) ## Get whether the RTC clock is currently counting time ## ## @subsubheading Inputs ## @var{dsObj} - the ds1307 object ## ## @subsubheading Outputs ## @var{YN} - returns true if the RTC is counting ## ## @seealso{start, stop} ## @end deftypefn ## ## @deftypefn {} {} start(@var{dsObj}) ## Start the RTC counting ## ## @subsubheading Inputs ## @var{dsObj} - the ds1307 object ## ## @subsubheading Outputs ## None ## ## @seealso{datevec} ## @end deftypefn ## ## @deftypefn {} {} stop(@var{dsObj}) ## Stop the RTC counting ## ## @subsubheading Inputs ## @var{dsObj} - the ds1307 object ## ## @subsubheading Outputs ## None ## ## @seealso{datevec} ## @end deftypefn properties(Access = private) i2c; bcd2dec = @(v) bitshift(v, -4)*10 + bitand(v, 0xf); dec2bcd = @(v) bitshift(floor(v/10), 4) + bitand(mod(v,10), 0xf); endproperties methods # constructor function this = DS1307(parentObj, varargin) if nargin < 1 || ! isarduino(parentObj) error('arduinosensor.DS1307: expected arduino object as first parameter'); endif # parse args p = inputParser(CaseSensitive=false, FunctionName='arduinosensor.DS1307'); p.addParameter('I2CAddress', 0x68, @isnumeric); p.parse(varargin{:}); # do we have the address ? address = p.Results.I2CAddress; i2caddresses = scanI2Cbus(parentObj); idx = find(cellfun ( @(x) strcmp(x, sprintf("0x%02X", address)), i2caddresses)); if isempty(idx) error('arduinosensor.DS1307: no matching i2c address found on bus'); endif this.i2c = device(parentObj, "i2caddress", p.Results.I2CAddress); endfunction function c = clock (this, settime) if nargin == 2 # set time wd = weekday(datenum(settime)); writeRegister(this.i2c, 0, ... [this.dec2bcd(floor(settime(6))), this.dec2bcd(settime(5)), (this.dec2bcd(settime(4))), ... wd, this.dec2bcd(settime(3)), this.dec2bcd(settime(2)), this.dec2bcd(mod(settime(1),100))] ... ); else # get time data = readRegister(this.i2c, 0, 7); secs = double(this.bcd2dec(bitand(data(1), 0x7f))); mins = double(this.bcd2dec(data(2))); if bitand(data(3), 0x40) != 0 # 12 hr pm = bitand(data(3), 0x20); hrs = double(this.bcd2dec(bitand(data(3), 0x2f))); if pm hrs = double(hrs + 12); endif else hrs = double(this.bcd2dec(bitand(data(3), 0x3f))); endif wday = double(data(4)); day = double(this.bcd2dec(data(5))); month = double(this.bcd2dec(data(6))); year = 2000.0 + double(this.bcd2dec(data(7))); c = double([year, month, day, hrs, mins, secs]); endif endfunction function start(this) data = readRegister(this.i2c, 0, 1); data = bitset(data, 8, 0); writeRegister(this.i2c, 0, data); endfunction function stop(this) data = readRegister(this.i2c, 0, 1); data = bitset(data, 8, 1); writeRegister(this.i2c, 0, data); endfunction function val = isstarted(this) data = readRegister(this.i2c, 0, 1); val = bitget(data, 8) == 0; endfunction function bits = control(this, setbits) if nargin == 1 data = readRegister(this.i2c, 7, 1); bits = {}; bits.out = bitget(data, 8); bits.sqwe = bitget(data, 5); bits.rs = bitand(data, 0x03); else data = 0; data = bitand(setbits.rs, 0x3); if setbits.out data = data + 0x80; endif if setbits.sqwe data = data + 0x10; endif writeRegister(this.i2c, 7, data); endif endfunction function disp(this) printf(" %s with properties\n", class(this)); if isobject(this.i2c) printf(" I2C Address = 0x%X\n", this.i2c.i2caddress); else printf(" Not connected"); endif endfunction function delete(this) try if isobject(this.i2c) delete(this.i2c); this.i2c = []; endif catch # do nothing end_try_catch endfunction endmethods endclassdef arduino-0.12.1/inst/+arduinosensor/GUVAS12SD.m0000644000000000000000000000737414545566645015601 0ustar00## Copyright (C) 2019-2020 John Donoghue ## ## 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 ## . classdef GUVAS12SD < handle ## -*- texinfo -*- ## @deftypefn {} {} arduinosensor.GUVAS12SD ## A thin wrapper for the GUVAS12SD analog UV-B sensor ## @end deftypefn ## ## @subheading Methods ## @deftypefn {} {@var{obj} =} GUVAS12SD(@var{arObj}, @var{pin}) ## Constructor to create GUVAS12SD sensor ## @subsubheading Inputs ## @var{arObj} - the arduino parent object ## ## @var{pin} - the analog pin that the sensor is connected to ## ## @subsubheading Outputs ## @var{obj} - created GUVAS12SD object ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## # create sensor attached to pin a0. ## sensor = arduinosensor.GUVAS12SD(a, "a0") ## } ## @end example ## @end deftypefn ## ## @deftypefn {} {@var{V} =} read(@var{dsObj}) ## Read the voltage of the sensor ## ## @subsubheading Inputs ## @var{dsObj} - the GUVAS12SD object ## ## @subsubheading Outputs ## @var{V} - read voltage - effectively equivalent to ## readAnalogPin(arObj, pin). ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## s = arduinosensor.GUVAS12SD(a) ## # voltage ## volts = s.read ## } ## @end example ## @seealso{arduinosensor.GUVAS12SD} ## @end deftypefn ## ## @deftypefn {} {@var{Idx} =} readIndex(@var{dsObj}) ## Read the UV index ## ## @subsubheading Inputs ## @var{dsObj} - the GUVAS12SD object ## ## @subsubheading Outputs ## @var{Idx} - the sensor reading as a UV index reading ## @end deftypefn ## ## @deftypefn {} {@var{uA} =} readuA(@var{dsObj}) ## Read the uA of the sensor ## ## @subsubheading Inputs ## @var{dsObj} - the GUVAS12SD object ## ## @subsubheading Outputs ## @var{uA} - the sensor reading as a uAmp value ## @end deftypefn properties(Access = private, constant = true) SCALE_UAMPS = 4.1; SCALE_INDEX = 0.1; endproperties properties(GetAccess = public, SetAccess = private) Pin; Parent; endproperties methods # constructor function this = GUVAS12SD(parentObj, pin, varargin) if nargin < 2 error('arduinosensor.GUVAS12SD: expected arduino and pin object parameters'); endif if ! isarduino(parentObj) error('arduinosensor.GUVAS12SD: expected arduino object as first parameter'); endif # check is an analog pin validatePin(parentObj, pin, "analog"); # lookup/use name for pin (in the case where a terminal num was given instead of a pin number) this.Pin = getPinInfo(parentObj, pin).name; this.Parent = parentObj; endfunction function val = read (this) # Vo = 4.3 * diodeuA # UV index = Vo/0.1 val = readAnalogPin(this.Parent, this.Pin); endfunction function val = readIndex (this) val = read(this)/this.SCALE_INDEX; endfunction function val = readuA (this) val = read(this)/this.SCALE_UAMPS; endfunction function disp(this) printf(" %s with properties\n", class(this)); printf(" Pin = %s\n", this.Pin); endfunction endmethods endclassdef arduino-0.12.1/inst/+arduinosensor/MPC3002.m0000644000000000000000000001021514545566645015232 0ustar00## Copyright (C) 2019-2020 John Donoghue ## ## 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 ## . classdef MPC3002 < handle ## -*- texinfo -*- ## @deftypefn {} {} arduinosensor.MPC3002 ## MCP3002 ADC sensor ## @end deftypefn ## ## @subheading Methods ## @deftypefn {} {@var{obj} =} MPC3002(@var{arObj}, @var{selectPin}) ## @deftypefnx {} {@var{obj} =} MPC3002(@var{arObj}, @var{selectPin}, @var{propertyname, propertyvalue} ....) ## Constructor to create MPC3002 sensor ## @subsubheading Inputs ## @var{arObj} - the arduino parent object ## ## @var{selectPin} - the SPI cs select pin ## ## @var{propertyname, propertyvalue} - optional property name, value pairs. ## ## Current properties are: ## @table @asis ## @item referenceVoltage ## Reference voltage for scaling the ADC inputs (default 5.0) ## @end table ## ## @subsubheading Outputs ## @var{obj} - created MCP3002 object ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## sensor = arduinosensor.MPC3002(a, "d10") ## } ## @end example ## @end deftypefn ## ## @deftypefn {} {@var{voltage} =} readVoltage(@var{dsObj}, @var{chan}) ## Read the voltage from a channel ## ## @subsubheading Inputs ## @var{dsObj} - the MPC3002 object ## ## @var{chan} - the channel to read (0 or 1) ## ## @subsubheading Outputs ## @var{voltage} - read voltage. ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## s = arduinosensor.MPC3002(a, "d10") ## volts = readVoltage(s, 0) ## } ## @end example ## @seealso{arduinosensor.MPC3002} ## @end deftypefn properties(Access = private, constant = true) VERSION = "0.0.1"; CHAN_0_READ = [ hex2dec("DF") hex2dec("FF") ]; CHAN_1_READ = [ hex2dec("EF") hex2dec("FF") ]; endproperties properties(Access = private) spi = []; reference_voltage = 5.0; endproperties methods # constructor function this = MPC3002(parentObj, selectpin, varargin) if nargin < 2 || ! isarduino(parentObj) error('arduinosensor.MPC3002: expected arduino object as first parameter, followed by a select pin'); endif # parse args p = inputParser(CaseSensitive=false, FunctionName='arduinosensor.MPC3002'); p.addParameter('referenceVoltage', 5.0, @isnumeric); p.parse(varargin{:}); this.spi = device(parentObj, "spichipselectpin", selectpin); this.reference_voltage = p.Results.referenceVoltage; # initial read v = writeRead(this.spi, this.CHAN_1_READ); endfunction function volts = readVoltage(this, chan) if nargin < 2 || !isnumeric(chan) || (chan != 1 && chan != 0) error('arduinosensor.MPC3002 read: expected channel number 0 or 1'); endif if chan == 0 cmd = this.CHAN_0_READ; else cmd = this.CHAN_1_READ; endif v = writeRead(this.spi, cmd); adc = bitand (uint16(v(1))*256 + uint16(v(2)), hex2dec('3FF')); volts = double(adc) * this.reference_voltage / 1023.0; endfunction function disp(this) printf(" %s with properties\n", class(this)); printf(" reference voltage = %f\n", this.reference_voltage); if isobject(this.spi) printf(" SPI cs = %s\n", this.spi.spichipselectpin); else printf(" Not connected"); endif endfunction function delete(this) try if isobject(this.spi) delete(this.spi); this.spi = []; endif catch # do nothing end_try_catch endfunction endmethods endclassdef arduino-0.12.1/inst/+arduinosensor/SI7021.m0000644000000000000000000001357714545566645015151 0ustar00## Copyright (C) 2019-2020 John Donoghue ## ## 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 ## . classdef SI7021 < handle ## -*- texinfo -*- ## @deftypefn {} {} arduinosensor.SI7021 ## SI7021 temperature and humidity sensor ## @end deftypefn ## ## @subheading Methods ## @deftypefn {} {@var{obj} =} SI7021(@var{arObj}) ## @deftypefnx {} {@var{obj} =} SI7021(@var{arObj}, @var{propertyname, propertyvalue} ....) ## Constructor to create SI7021 sensor ## @subsubheading Inputs ## @var{arObj} - the arduino parent object ## ## @var{propertyname, propertyvalue} - optional property name, value pairs. ## Current known properties are: ## Current properties are: ## @table @asis ## @item i2caddress ## I2C address of the SI7021 (default 0x40) ## @end table ## ## @subsubheading Outputs ## @var{obj} - created SI7020 object ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## sensor = arduinosensor.SI7021(a) ## } ## @end example ## @end deftypefn ## ## @deftypefn {} {@var{C} =} temperature(@var{dsObj}) ## Read the temperature ## ## @subsubheading Inputs ## @var{dsObj} - the si7021 object ## ## @subsubheading Outputs ## @var{C} - read temperature in deg C. ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## s = arduinosensor.SI7021(a) ## # get temp ## temp = s.temperature ## } ## @end example ## @seealso{arduinosensor.SI7021} ## @end deftypefn ## ## @deftypefn {} {@var{relH} =} humidity(@var{dsObj}) ## Read the relative humidity ## ## @subsubheading Inputs ## @var{dsObj} - the si7021 object ## ## @subsubheading Outputs ## @var{relH} - relative humidity as a percentage (0 - 100.0) ## @end deftypefn ## ## @deftypefn {} {@var{relH} =} info(@var{dsObj}) ## Read the sensor info ## ## @subsubheading Inputs ## @var{dsObj} - the si7021 object ## ## @subsubheading Outputs ## @var{inf} - structure containing the sensor information. ## ## Structure fields are: ## @table @asis ## @item version ## Chip firmware version ## @item id ## sensor id1,id2 value ## @item type ## String for detected chip type ## @end table ## ## @end deftypefn properties(Access = private, constant = true) SENSOR_ID_1 = [ hex2dec("FA") hex2dec("F0") ]; SENSOR_ID_2 = [ hex2dec("FC") hex2dec("C9") ]; SENSOR_VERSION = [ hex2dec("84") hex2dec("B8") ]; TEMP_MEASURE_NOHOLD = hex2dec("F3"); HUMIDITY_MEASURE_NOHOLD = hex2dec("F5"); endproperties properties(Access = private) i2c; endproperties methods # constructor function this = SI7021(parentObj, varargin) if nargin < 1 || ! isarduino(parentObj) error('arduinosensor.SI7021: expected arduino object as first parameter'); endif # parse args p = inputParser(CaseSensitive=false, FunctionName='arduinosensor.SI7021'); p.addParameter('I2CAddress', 0x40, @isnumeric); p.parse(varargin{:}); # do we have the address ? address = p.Results.I2CAddress; i2caddresses = scanI2Cbus(parentObj); idx = find(cellfun ( @(x) strcmp(x, sprintf("0x%02X", address)), i2caddresses)); if isempty(idx) error('arduinosensor.SI7021: no matching i2c address found on bus'); endif this.i2c = device(parentObj, "i2caddress", p.Results.I2CAddress); endfunction function inf = info (this) write (this.i2c, this.SENSOR_ID_1); id1 = read(this.i2c, 1); write (this.i2c, this.SENSOR_ID_2); id2 = read(this.i2c, 1); if id2 == hex2dec("15") type = "Si7021"; elseif id2 == hex2dec("14") type = "Si7020"; elseif id2 == hex2dec("0D") type = "Si7013"; elseif id2 == hex2dec("32") type = "HTU21D"; else type = "Unknown"; endif write (this.i2c, this.SENSOR_VERSION); ver = read(this.i2c, 1); if ver == hex2dec("FF") ver = 1.0; else ver = double(ver)/10.0; endif inf = {}; inf.version = ver; inf.type = type; inf.id = int32(id1)*256 + int32(id2); endfunction function C = temperature (this) % write command to get temp write (this.i2c, uint8([this.TEMP_MEASURE_NOHOLD])); pause (0.02); data = read (this.i2c, 3); value = uint16(data(1))*256 + uint16(data(2)); value = bitand (value, hex2dec("FFFC")); temp_Code = double(value); C = (175.72*temp_Code/65536)-46.85; # F = (C * 1.8) + 32.0; endfunction function H = humidity(this) write (this.i2c, uint8([this.HUMIDITY_MEASURE_NOHOLD])); pause (0.02); data = read (this.i2c, 3); value = uint16(data(1))*256 + uint16(data(2)); value = bitand (value, hex2dec("FFFC")); humidity_Code = double(value); H = (125.0*humidity_Code/65536)-6; endfunction function disp(this) printf(" %s with properties\n", class(this)); if isobject(this.i2c) printf(" I2C Address = 0x%X\n", this.i2c.i2caddress); else printf(" Not connected"); endif endfunction function delete(this) try if isobject(this.i2c) delete(this.i2c); this.i2c = []; endif catch # do nothing end_try_catch endfunction endmethods endclassdef arduino-0.12.1/inst/+matlabshared/0000755000000000000000000000000014545566645013665 5ustar00arduino-0.12.1/inst/+matlabshared/+addon/0000755000000000000000000000000014545566645015025 5ustar00arduino-0.12.1/inst/+matlabshared/+addon/LibraryBase.m0000644000000000000000000000477014545566645017412 0ustar00## Copyright (C) 2021 John Donoghue ## ## 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 ## . classdef LibraryBase < arduinoio.LibraryBase ## -*- texinfo -*- ## @deftypefn {} {} matlabshared.addon.LibraryBase ## Compatability class used for arduino library plugins using ## matlabshared.addons.LibraryBase ## ## @seealso{arduinoio.LibraryBase, arduino, listArduinoLibraries, addon} ## @end deftypefn ## ## @subheading Properties ## Base properties are expected to be inherited and overwritten in ## inherited classes and are constant in order to query through the ## metaobject mechanism. ## ## @var{LibraryName} - name of the addon library ## ## @var{DependentLibraries} - array of dependent library names that ## must be included when installing this plugin. ## ## @var{CppHeaderFile} - name (if any) of header file that will be ## included into the arduino project when adding this library. ## ## @var{CppSourceFile} - name (if any) of source file that will be ## included into the arduino project when adding this library. ## ## @var{CppClassName} - name of the cpp class for the addon library. ## project when adding this library. ## ## @var{Pins} - pins allocated to the addon ## ## @var{Parent} - parent arduino object. ## ## @subheading Methods ## @deftypefn {} {@var{lb} =} LibraryBase () ## Constructor of base class ## ## The constructor is usually not called but called indirectly ## from the addon function. ## ## @subsubheading Outputs ## The return value @var{lb} is an object of the ## matlabshare.addons.LibraryBase class. ## ## @seealso{arduino, listArduinoLibraries, addon} ## @end deftypefn ## ## @deftypefn {} {} disp () ## Display the addon in a verbose way. ## @end deftypefn methods (Access=public) function this = LibraryBase () # nothing to do endfunction endmethods endclassdef arduino-0.12.1/inst/@arduino/0000755000000000000000000000000014545566645012724 5ustar00arduino-0.12.1/inst/@arduino/__freeArduino__.m0000644000000000000000000000161714545566645016146 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. see ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} __freeArduino__ (@var{obj}) ## Private function ## @end deftypefn function retval = __freeArduino__ (obj, port, board) if isobject (obj.connected) fclose(obj.connected); obj.connected = false; endif retval = obj; endfunction arduino-0.12.1/inst/@arduino/__initArduino__.m0000644000000000000000000000775014545566645016174 0ustar00## Copyright (C) 2018-2022 John Donoghue ## ## 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. see ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} __initArduino__ (@var{obj}, @var{port}, @var{board}, @var{scan_only}) ## Private function ## @end deftypefn function retval = __initArduino__ (obj, port, board, scan_only) % send command and get back reponse ARDUINO_INIT = 1; ARDUINO_GETLIB = 8; ok = false; if !isempty(port) || !ischar(port) # port maybe ip address ? if !isempty(regexp(port, "^[0-9]+.[0-9]+.[0-9]+.[0-9]+$")) obj.connected = tcp (port, 9500, 10); else obj.connected = serialport (port, 'BaudRate', obj.BaudRate, 'Timeout', .2); endif # need wait for arduino to potentially startup pause(2); # clear any data in buffers set(obj.connected, "timeout", 0.1); data = fread(obj.connected,100); while length(data) >= 100 data = fread(obj.connected,100); if obj.debug printf("flushing %d bytes of data\n", length(data)); endif endwhile [dataout, status] = __sendCommand__(obj, 0, ARDUINO_INIT); if status != 0 error ("__initArduino__: failed valid response err=%d - %s", status, char(dataout)); endif % uno r3 - atmega32 1E 95 0F sig = (uint32(dataout(1))*256*256) + (uint32(dataout(2))*256) + uint32(dataout(3)); % work out mcu switch sig case 0 mcu = ""; case { hex2dec("1E9502"), hex2dec("009502") } mcu = "atmega32"; case { hex2dec("1E950F"), hex2dec("00950F") } mcu = "atmega328p"; case { hex2dec("1E9514"), hex2dec("009514") } mcu = "atmega328pu"; case hex2dec("1E9801") mcu= "atmega2560"; case hex2dec("1E9703") mcu = "atmega1280"; case hex2dec("1E9702") mcu = "atmega128"; case hex2dec("1E9587") mcu = "atmega32u4"; case hex2dec("1E9651") mcu = "atmega4809"; otherwise mcu = sprintf("unknown_mcu(%X)", sig); endswitch boardtype = arduinoio.boardTypeString(dataout(4)); voltref = double(dataout(5))/10.0; numlib = uint8(dataout(6)); flags = 0; if length(dataout) > 6 flags = dataout(7); endif % check board against config info if ~isempty(board) && !strcmpi(board, boardtype) warning("connected %s arduino does not match requested board type %s", boardtype, board) endif obj.config = arduinoio.getBoardConfig(boardtype); # update values that could change obj.config.port = port; obj.config.baudrate = obj.BaudRate; obj.config.board = boardtype; obj.config.voltref = voltref; obj.config.flags = flags; if isa(obj.connected, "octave_tcp") obj.config.port = 9500; obj.config.deviceaddress = port; endif if ! isempty(mcu) obj.config.mcu = mcu; elseif isempty(obj.config.mcu) obj.config.mcu = "unknown"; endif obj.config.libs = {}; # query libs if ! scan_only for libid = 0:numlib-1 [dataout, status] = __sendCommand__(obj, 0, ARDUINO_GETLIB, [libid]); if status != 0 error ("__initArduino__: failed get lib %d err=%d - %s", libid, status, char(dataout)); else lib = {}; lib.id = libid; lib.name = lower(char(dataout(2:end))); obj.config.libs{end+1} = lib; endif endfor endif else error ("__initArduino__: expected a valid port"); endif retval = obj; endfunction arduino-0.12.1/inst/@arduino/arduino.m0000644000000000000000000003652714545566645014560 0ustar00## Copyright (C) 2018-2019 John Donoghue ## ## 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 ## . classdef arduino < handle ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} arduino () ## @deftypefnx {} {@var{retval} =} arduino (@var{port}) ## @deftypefnx {} {@var{retval} =} arduino (@var{port}, @var{board}) ## @deftypefnx {} {@var{retval} =} arduino (@var{port}, @var{board}[, [@var{propname}, @var{propvalue}]*) ## @deftypefnx {} {@var{retval} =} arduino (@var{iaddress}) ## @deftypefnx {} {@var{retval} =} arduino (@var{ipaddress}, @var{board}) ## Create a arduino object with a connection to an arduino board. ## ## @subsubheading Inputs ## @var{port} - full path of serial port to connect to. For Linux, ## usually /dev/ttySXXX, for windows COMXX. ## ## @var{board} - name of board to connect (default is 'uno'). ## ## @var{propname}, @var{propvalue} - property name and value pair ## for additional properties to pass to the creation of the ## arduino object. ## ## Currently properties are ignored, with the exception of: ## @table @asis ## @item debug ## true / false flag for whether setting debug (default false) ## @item forcebuildon ## true / false flag for whether to force show of the arduino IDE to ## rebuild the installed code on the arduino (default false) ## @item baudrate (read only) ## the communications baudrate to the board. (default 9600) ## @item libraries ## The libraries to be enabled on the arduino board. (default uses whatever is already installed) ## @end table ## ## if the arduino function is called without parameters, it will scan ## for the first available arduino it can find and connect to it. ## ## @subsubheading Outputs ## @var{retval} - a successfully connected arduino object. ## ## @subsubheading Properties ## The arduino object has the following public properties: ## @table @asis ## @item name ## name assigned to the arduino object ## @item debug ## true / false flag for whether debug is turned on ## @item forcebuildon ## true / false flag for whether to force show of the arduino IDE to ## reprogram the arduino ## @item port (read only) ## the communications port the board is connected to. ## @item baudrate (read only) ## the communications baudrate to the board. ## @item board (read only) ## The name of the board type that the arduino connected to ## @item libraries (read only) ## The libraries currently programmed onto the board ## @item availablepins ## The pins available for use on the board ## @item analogreference ## The analog voltage reference ## @end table ## @seealso{scanForArduinos, arduinosetup} ## @end deftypefn properties (Access = private) config = {}; resources = {}; connected = false; endproperties properties (Access = public) name = ""; debug = false; endproperties # matlab compatible properties properties (SetAccess = private) AvailablePins = []; Libraries = []; AnalogReference = 5.0; Board = ""; Port = ""; BaudRate = 9600; endproperties properties (SetAccess = private, Hidden = true) DeviceAddress = ""; endproperties methods (Access = public) function this = arduino (varargin) if (nargin == 0) arduinos = scanForArduinos (1); if isempty (arduinos) error ("arduino: No arduinos found on serial scan"); endif this.name = "arduino"; c = arduinoio.getBoardConfig(arduinos{1}.board); this.BaudRate = c.baudrate; this = __initArduino__ (this, arduinos{1}.port, arduinos{1}.board, 0); elseif (nargin == 1) arg0 = varargin{1}; if (isa (arg0, "arduino")) # copy this.config = arg0.config; this.resources = arg0.resources; this.name = arg0.name; this.connected = arg0.connected; elseif ischar(arg0) # port given this.name = "arduino"; this.connected = false; this = __initArduino__ (this, arg0, "", 0); else error ("arduino: port must be a string"); endif else # at least port, board [optional property pairs] port = varargin{1}; board = varargin{2}; if isempty (port) arduinos = scanForArduinos (1, board); if isempty (arduinos) error ("arduino: No matching arduinos found on serial scan"); endif port = arduinos{1}.port; board = arduinos{1}.board; c = arduinoio.getBoardConfig(arduinos{1}.board); this.BaudRate = c.baudrate; elseif !ischar (port) error ("arduino: port must be a string"); endif if !ischar (port) error ("arduino: board must be a string"); endif if mod (nargin, 2) != 0 error ("arduino: expected property name, value pairs"); endif if !iscellstr (varargin (3:2:nargin)) error ("arduino: expected property names to be strings"); endif this.name = ["arduino " board]; requiredlibs = {}; forcebuild = false; forcebuildon = false; scan_only = false; for i = 3:2:nargin propname = tolower (varargin{i}); propvalue = varargin{i+1}; #printf("%s = %s\n", propname, propvalue); if strcmp (propname,"debug") if propvalue this.debug = 1; endif endif if strcmp (propname,"_scan_only") # internal property scan_only = propvalue; endif if strcmp (propname,"libraries") if ischar (propvalue) requiredlibs{end+1} = propvalue; elseif iscellstr (propvalue) requiredlibs = propvalue; else error ("arduino: expect libraries value to be a libraryname or cellarray of library names"); endif endif if strcmp (propname,"forcebuildon") if islogical (propvalue) || (isnumeric(propvalue) && (propvalue == 1 || propvalue == 0)) forcebuildon = propvalue; else error ("arduino: expect forcebuildon to be true or false"); endif endif if strcmp (propname,"baudrate") if !isnumeric(propvalue) error ("arduino: expect baudrate to be numeric"); else this.BaudRate = int32(propvalue); if this.BaudRate < 1200 error ("arduino: Invalid baudrate"); endif endif endif # older option that probally should remove if strcmp (propname,"forcebuild") if islogical (propvalue) || (isnumeric(propvalue) && (propvalue == 1 || propvalue == 0)) forcebuild = propvalue; else error ("arduino: expect forcebuild to be true or false"); endif endif endfor this = __initArduino__ (this, port, board, scan_only); # check have requested libs reprogram = false; if forcebuildon reprogram = true; elseif ! scan_only availablelibs = listArduinoLibraries (); for i = 1:numel (requiredlibs) lib = requiredlibs{i}; id = this.get_lib (lib); if id < 0 idx = find( cellfun(@(x) strcmpi(x, lib), availablelibs), 1); if isempty (idx) error ('arduino: unknown library "%s"', lib); elseif forcebuild warning ('arduino: not configured with library "%s" - will need to reprogram', lib); reprogram = true; else error ('arduino: not configured with library "%s" - please rerun arduinosetup with library, or set forcebuild', lib); endif endif endfor endif if reprogram printf("starting reprogram process ....\n") # free arduino resources, reprom and then reinit this = __freeArduino__(this); if !arduinosetup ('libraries', requiredlibs, 'baudrate', this.BaudRate) error ("arduinosetup returned a failure, so did not reprogram") endif this = __initArduino__ (this, port, board, 0); endif endif endfunction endmethods methods (Hidden = true) # helper functions function set_debug (this, d) this.debug = d; endfunction function d = get_debug (this) this = this.debug; endfunction # helper functions that get/set values in the private config function m = get_mcu (this) m = this.config.mcu; endfunction function m = get_flags (this) m = this.config.flags; endfunction function m = get_endian (this) if bitand(this.config.flags, 0x80) != 0 m = "B"; else m = "L"; endif endfunction function id = get_lib (this, name) idx = find( cellfun(@(x) strcmpi(x.name, name), this.config.libs), 1); if isempty (idx) id = -1; else id = this.config.libs{idx}.id; endif endfunction function set_pin (this, pin, info) if ischar(pin) idx = find (cellfun(@(x) strcmpi (x.name, pin), this.config.pins), 1); else idx = find (cellfun(@(x) (x.d == pin), this.config.pins), 1); endif if isempty (idx) error ("arduino: unknown pin"); endif this.config.pins{idx} = info; endfunction function info = get_pin (this, pin) if ischar(pin) idx = find (cellfun(@(x) strcmpi (x.name, pin), this.config.pins), 1); else idx = find (cellfun(@(x) (x.id == pin), this.config.pins), 1); endif if isempty (idx) error (["arduino: unknown pin " pin]); endif info = this.config.pins{idx}; endfunction function info = get_altpin (this, pin) idx = find (cellfun(@(x) (sum(strcmpi (x.altnames, pin))>0), this.config.pins), 1); if !isempty (idx) info = this.config.pins{idx}; else info = {}; endif endfunction function retval = get_group(this,type) retval = {}; for i = 1:numel (this.config.pins) pininfo = this.config.pins{i}; idx = find (cellfun(@(x) strncmpi (x, type, length (type)), pininfo.modes), 1); if !isempty(idx) values = strsplit (pininfo.modes{idx}, "_"); info = {}; info.name = pininfo.name; info.func = values{2}; info.mode = pininfo.mode; info.owner = pininfo.owner; retval{end+1}= info; endif endfor endfunction function retval = get_pingroup(this, pin, type) retval = {}; pininfo = this.get_pin(pin); idx = find (cellfun(@(x) strncmpi(x, type, length(type)), pininfo.modes), 1); if !isempty (idx) # possibly this will be in format of # type[XX]_YY where XX is a number ir: spi0, spi1 etc, ## _YY will be the pinfunction ie: scl, miso etc values = strsplit (pininfo.modes{idx}, "_"); type = values{1}; for i = 1:numel (this.config.pins) pininfo = this.config.pins{i}; idx = find (cellfun(@(x) strncmpi(x, type, length (type)), pininfo.modes), 1); if !isempty(idx) values = strsplit(pininfo.modes{idx}, "_"); info = {}; info.name = pininfo.name; info.func = values{2}; info.mode = pininfo.mode; info.owner = pininfo.owner; retval{end+1}= info; endif endfor endif endfunction function ref = analogreference(this) ref = this.config.voltref; endfunction function pins = availablepins(this) pins = {}; for i=1:numel (this.config.pins) pins{end+1} = this.config.pins{i}.name; endfor endfunction function libs = libraries(this) libs = {}; for i=1:numel (this.config.libs) if ! strcmpi(this.config.libs{i}.name, "core") libs{end+1} = this.config.libs{i}.name; endif endfor endfunction function p = port(this) p = this.config.port; endfunction function b = board(this) b = this.config.board; endfunction function set_resource (this, resource, res) resource = tolower (resource); # make sure noone tries to change the name used for searching res.name = resource; idx = find (cellfun(@(x) strcmp(x.name, resource), this.resources), 1); if isempty (idx) this.resources{end+1} = res; else this.resources{idx} = res; endif endfunction function res = get_resource (this, resource) resource = tolower(resource); idx = find (cellfun(@(x) strcmp(x.name, resource), this.resources), 1); if isempty (idx) # none currently res = {}; res.name = resource; res.count = 0; res.owner = ""; res.props = struct(); else res = this.resources{idx}; endif endfunction function v = board_voltage (this) v = this.config.voltref; endfunction function v = get.AvailablePins (this) v = availablepins(this); endfunction function v = get.Libraries (this) v = libraries(this); endfunction function v = get.AnalogReference (this) v = this.config.voltref; endfunction function v = get.Board (this) v = this.config.board; endfunction function v = get.Port (this) v = this.config.port; endfunction function v = get.DeviceAddress (this) v = this.config.deviceaddress; endfunction endmethods endclassdef %!shared arduinos %! arduinos = scanForArduinos(1); %!assert(numel(arduinos), 1); %!test %! ar = arduino(); %! assert(!isempty(ar)); %! assert(ar.port, arduinos{1}.port); %! assert(ar.board, arduinos{1}.board); %! assert(numel(ar.availablepins) > 0); %!test %! ar = arduino(arduinos{1}.port); %! assert(!isempty(ar)); %! assert(ar.port, arduinos{1}.port); %! assert(ar.board, arduinos{1}.board); %!test %! ar = arduino(arduinos{1}.port, arduinos{1}.board); %! assert(!isempty(ar)); %! assert(isa(ar, "arduino")) %! assert(ar.port, arduinos{1}.port); %! assert(ar.board, arduinos{1}.board); %!test %! ar = arduino(); %! # verify have compiled support for functions we will be testing %! assert(!isempty(find(cellfun(@(x) strcmpi(x, "spi"), ar.libraries()), 1))) %! assert(!isempty(find(cellfun(@(x) strcmpi(x, "i2c"), ar.libraries()), 1))) %! assert(!isempty(find(cellfun(@(x) strcmpi(x, "servo"), ar.libraries()), 1))) %! assert(!isempty(find(cellfun(@(x) strcmpi(x, "shiftregister"), ar.libraries()), 1))) %! assert(!isempty(find(cellfun(@(x) strcmpi(x, "rotaryencoder"), ar.libraries()), 1))) arduino-0.12.1/inst/@arduino/checkI2CAddress.m0000644000000000000000000000470314545566645015767 0ustar00## Copyright (C) 2019 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} checkI2CAddress (@var{ar}, @var{address}) ## @deftypefnx {} {@var{retval} =} checkI2CAddress (@var{ar}, @var{address}, @var{bus}) ## Check that an address of given address responds on the I2C bus ## ## @subsubheading Inputs ## @var{ar} - arduino object connected to a arduino board. ## ## @var{address} - I2C address number to check ## ## @var{bus} - bus number to check for I2C device, when multiple buses are available. ## If the bus is not specified, it will default to 0. ## ## @subsubheading Outputs ## @var{retval} - boolean value of true if address responds on the I2C bus ## ## @subsubheading Example ## @example ## @code { ## # create arduino connection. ## ar = arduino(); ## # scan for devices on the I2C bus ## checkI2CAddress (ar) ## # output if a device using that address is attached ## ans = ## 1 ## } ## @end example ## ## @seealso{arduino, scanI2Cbus} ## @end deftypefn function ret = checkI2CAddress (ar, address, bus) persistent ARDUINO_I2C_SCAN = 0; ret = false; if nargin < 2 || nargin > 3 print_usage (); endif if nargin == 2 bus = 0; elseif !isnumeric (bus) || bus < 0 || bus > 1 error ('checkI2CAddress: expected bus to be numeric and 0 or 1'); endif if (!isa (ar, "arduino")) error ("checkI2CAddress: expects arduino object as 1st argument"); endif if !isnumeric (address) || address < 1 || address > 127 error ('checkI2CAddress: expected address to be numeric 1 > address <= 127'); endif # TODO: configure SPI pins if not already done?? [tmp, sz] = sendCommand (ar, "i2c", ARDUINO_I2C_SCAN, [bus address]); if tmp(3) == 1 ret = true; endif endfunction %!test %! ar = arduino(); %! assert(!isempty(ar)); %! checkI2CAddress(ar, 12); arduino-0.12.1/inst/@arduino/configurePin.m0000644000000000000000000001014614545566645015534 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{currmode} =} configurePin (@var{ar}, @var{pin}) ## @deftypefnx {} {} configurePin (@var{ar}, @var{pin}, @var{mode}) ## Set/Get pin mode for a specified pin on arduino connection. ## ## configurePin (@var{ar}, @var{pin}) will get the current mode of the specified pin. ## ## configurePin (@var{ar}, @var{pin}, @var{mode}) will attempt set the pin to the specified ## mode if the mode is unset. ## ## @subsubheading Inputs ## @var{ar} - the arduino object of the connection to an arduino board. ## ## @var{pin} - string name of the pin to set/get the mode of. ## ## @var{mode} - string mode to set the pin to. ## ## @subsubheading Outputs ## @var{mode} - string current mode of the pin. ## ## Valid modes can be: ## @itemize @bullet ## @item AnalogInput ## - Acquire analog signals from pin ## @item DigitalInput ## - Acquire digital signals from pin ## @item DigitalOutput ## - Generate digital signals from pin ## @item I2C ## - Specify a pin to use with I2C protocol ## @item Pullup ## - Specify pin to use a pullup switch ## @item PWM ## - Specify pin to use a pulse width modulator ## @item Servo ## - Specify pin to use a servo ## @item SPI ## - Specify a pin to use with SPI protocol ## @item Interrupt ## - Specify a pin to use for with interrupts ## @item Reserved ## - Specify a pin to be reserved ## @item Unset ## - Clears pin designation. The pin is no longer reserved and can be automatically ## set at the next operation. ## @end itemize ## ## @seealso{arduino} ## ## @end deftypefn function retval = configurePin (obj, pin, mode) persistent ARDUINO_CONFIGPIN = 2; if nargin != 2 && nargin != 3 error ("@arduino.configurePin: expected pin name and value"); endif if !ischar (pin) && !isnumeric (pin) error ("@arduino.configurePin: expected pin name as string"); endif pininfo = obj.get_pin (pin); if nargin == 3 % set mode if !ischar (mode) error ("@arduino.configurePin: expected pin mode as string"); endif mode = tolower (mode); [pinstate, pinmode] = pinStateMode (mode); if strcmp (pinmode,"spi") # check special case of when pin is miso, make it an input idx = find (cellfun(@(x) ~isempty (strfind (x, "_miso")), pininfo.modes), 1); if !isempty (idx) pinstate = 2; endif endif % valid setting for this pin ? if !strcmpi (mode, "unset") && !strcmp(mode, "reserved") validatePin (obj, pin, pinmode); else pinmode = getResourceOwner (obj, pin); endif % own this pin configurePinResource (obj, pin, pinmode, mode); # send config command to arduino datain = uint8 ([pininfo.id pinstate]); [dataout, status] = __sendCommand__ (obj, 0, ARDUINO_CONFIGPIN, datain); if status != 0 error ("@arduino.configurePin: failed to set pin state err=%d - %s", status, char(dataout)); endif else % get mode ? datain = uint8 ([pininfo.id]); [dataout, status] = __sendCommand__ (obj, 0, ARDUINO_CONFIGPIN, datain); if status != 0 error ("@arduino.configurePin: failed to set pin state err=%d - %s", status, char(dataout)); endif retval = pinStateMode (dataout(2)); endif endfunction %!test %! ar = arduino(); %! assert(!isempty(ar)); %! configurePin(ar, "d2", "digitaloutput"); %! assert(configurePin(ar, "d2"), "digitaloutput"); %! configurePin(ar, "d2", "unset"); %! assert(configurePin(ar, "d2"), "unset"); arduino-0.12.1/inst/@arduino/configurePinResource.m0000644000000000000000000001010414545566645017236 0ustar00## Copyright (C) 2018-2019 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{currmode} =} configurePinResource (@var{ar}, @var{pin}) ## @deftypefnx {} {} configurePinResource (@var{ar}, @var{pin}, @var{owner}, @var{mode}) ## @deftypefnx {} {} configurePinResource (@var{ar}, @var{pin}, @var{owner}, @var{mode}, @var{force}) ## Set/Get pin mode for a specified pin on arduino connection. ## ## configurePinResource (@var{ar}, @var{pin}) will get the current mode of the specified pin. ## ## configurePinResource (@var{ar}, @var{pin}, @var{owner}, @var{mode}) will attempt set the pin to the specified ## mode and owner. ## ## If the pin is already owned by another owner, the configure will fail unless the force option is used. ## If the mode is already set, configure will fail unless force is used. ## ## @subsubheading Inputs ## @var{ar} - the arduino object of the connection to an arduino board. ## ## @var{pin} - string name of the pin to set/get the mode of. ## ## @var{mode} - string mode to set the pin to. ## ## @var{owner} - string name to use as the pin owner. ## ## @var{force} - boolean to force mode change. If not set, it will be false. ## ## @subsubheading Outputs ## @var{currmode} - current string mode of the pin. ## ## Valid modes can be: ## @itemize @bullet ## @item AnalogInput ## - Acquire analog signals from pin ## @item DigitalInput ## - Acquire digital signals from pin ## @item DigitalOutput ## - Generate digital signals from pin ## @item I2C ## - Specify a pin to use with I2C protocol ## @item Pullup ## - Specify pin to use a pullup switch ## @item PWM ## - Specify pin to use a pulse width modulator ## @item Servo ## - Specify pin to use a servo ## @item SPI ## - Specify a pin to use with SPI protocol ## @item Interrupt ## - Specify a pin to use with interrupts ## @item Reserved ## - Pin marked reserved, but not for of any particular mode ## @item Unset ## - Clears pin designation. The pin is no longer reserved and can be automatically ## set at the next operation. ## @end itemize ## ## @seealso{arduino, configurePin} ## @end deftypefn function retval = configurePinResource (obj, pin, owner, mode, forceconfig) if nargin != 2 && nargin != 4 && nargin != 5 error ('@arduino.configurePinResource: invalid number of arduments supplied'); endif if !ischar(pin) error ("@arduino.configurePinResource: expected pin name as string"); endif pininfo = obj.get_pin (pin); if nargin == 2 % return current mode retval = pininfo.mode; else if nargin == 4 forceconfig = false; endif if !isempty (pininfo.owner) && !strcmpi (pininfo.owner, owner) && !forceconfig error ("@arduino.configurePinResource: pin already owned"); endif if !strcmpi (pininfo.mode, "unset") && !strcmpi (pininfo.mode, mode) && !forceconfig && !strcmpi (mode, "unset") error ("@arduino.configurePinResource: pin mode already set"); endif if (strcmpi (mode, "unset")) owner = ""; endif pininfo.owner = owner; pininfo.mode = mode; obj.set_pin (pin, pininfo); endif endfunction %!shared ar %! ar = arduino(); %!test %! configurePinResource(ar, "d2", "test", "digitaloutput"); %! assert(getResourceOwner(ar,"d2"), "test") %! assert(getTerminalMode(ar, "d2"), "digitaloutput"); %!test %! configurePinResource(ar, "a0", "test1", "analoginput"); %! assert(getResourceOwner(ar,"a0"), "test1") %! assert(getTerminalMode(ar, "a0"), "analoginput"); arduino-0.12.1/inst/@arduino/decrementResourceCount.m0000644000000000000000000000340314545566645017571 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{count} =} decrementResourceCount (@var{ar}, @var{resource}) ## Decrement the count of a named resource by 1 and return the ## new count. ## ## @subsubheading Inputs ## @var{ar} - connected arduino object ## ## @var{resource} - name of resource to decrement count. ## ## @subsubheading Outputs ## @var{count} = count of uses registered to resource. ## ## @seealso{getResourceCount. incrementResourceCount} ## @end deftypefn function retval = decrementResourceCount (ar, resource) if nargin != 2 print_usage (); endif if !ischar (resource) error ("@arduino.decrementResourceCount: expects resource name"); endif resinfo = ar.get_resource (resource); if resinfo.count == 0 error ("@arduino.decrementResourceCount: resource count is 0"); endif resinfo.count --; ar.set_resource (resource, resinfo); retval = resinfo.count; endfunction %!test %! ar = arduino(); %! assert(!isempty(ar)); %! assert(getResourceCount(ar,"notusedname"), 0); %! assert(incrementResourceCount(ar,"notusedname"), 1); %! assert(getResourceCount(ar,"notusedname"), 1); %! assert(decrementResourceCount(ar,"notusedname"), 0); %! assert(getResourceCount(ar,"notusedname"), 0); arduino-0.12.1/inst/@arduino/delete.m0000644000000000000000000000155514545566645014352 0ustar00## Copyright (C) 2020 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} delete (@var{dev}) ## Free resources of an arduino object. ## ## @subsubheading Inputs ## @var{dev} - object to free ## ## @seealso{arduino} ## @end deftypefn function delete(this) try this.connected = false; catch # do nothing end_try_catch endfunction arduino-0.12.1/inst/@arduino/disp.m0000644000000000000000000000475014545566645014047 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} disp (@var{ar}) ## Display the arduino object in a verbose way, showing the board and available pins. ## ## @subsubheading Inputs ## @var{ar} - the arduino object. ## ## If the arduino object has debug mode set, additional information will be displayed. ## ## @seealso{arduino} ## @end deftypefn function disp (ar) if isobject(ar.connected) printf (" arduino object with fields of: \n"); if isa(ar.connected, "octave_tcp") printf (" deviceaddress = ") disp (ar.config.deviceaddress); endif printf (" port = ") disp (ar.config.port); printf (" board = ") disp (ar.config.board); printf (" libraries = {\n") libs = ar.libraries (); for i=1:numel (libs) printf (" %s\n", libs{i}); endfor printf(" }\n"); # group pins where can nextpin = ""; startpin = {}; endpin = {}; printf (" availablepins = {\n") for i=1:numel (ar.config.pins) pin = ar.config.pins{i}; if !strcmpi(nextpin, pin.name) if !isempty(endpin) printf (" %s - %s\n", startpin.name, endpin.name); elseif !isempty(startpin) printf (" %s\n", startpin.name); endif startpin = pin; endpin = {}; else if isempty(startpin) startpin = pin; else endpin = pin; endif endif parts = sscanf(pin.name, "%c %d"); nextpin = sprintf("%c%d", char(parts(1)), parts(2)+1); endfor if !isempty(endpin) printf (" %s - %s\n", startpin.name, endpin.name); elseif !isempty(startpin) printf (" %s\n", startpin.name); endif printf(" }\n"); else printf (" arduino object disconnected\n"); endif if ar.debug printf (" config = \n"); disp (ar.config); endif endfunction arduino-0.12.1/inst/@arduino/getEndian.m0000644000000000000000000000226414545566645015004 0ustar00## Copyright (C) 2021 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{mcu} =} getEndian (@var{ar}) ## Get the endian used by the connected arduino. ## ## @subsubheading Inputs ## @var{ar} - arduino object connected to a arduino board. ## ## @subsubheading Outputs ## @var{endian} - string representing the endian used by the arduino board. ## ## 'L' means little endian, ## 'B' means big endian ## ## @seealso{arduino, getMCU} ## @end deftypefn function retval = getEndian (obj) retval = obj.get_endian (); endfunction %!test %! ar = arduino (); %! assert (!isempty (ar)); %! mcu = getEndian (ar); %! assert (ischar (mcu)) %! assert (mcu, ar.get_endian ()) arduino-0.12.1/inst/@arduino/getI2CTerminals.m0000644000000000000000000000301614545566645016036 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{pinlist} =} getI2CTerminals (@var{ar}) ## @deftypefnx {} {@var{pinlist} =} getI2CTerminals (@var{ar}, @var{bus}) ## Get a cell list of pin Ids available are used for I2C mode. ## ## @subsubheading Inputs ## @var{ar} - the arduino object. ## ## @var{bus} - optional bus number 0 or 1 for boards that support more than 1 bus. ## ## @subsubheading Outputs ## @var{pinlist} - cell list of pin numbers available for I2C use. ## ## @seealso{arduino} ## @end deftypefn function retval = getI2CTerminals (obj, bus) if nargin < 1 || nargin > 2 print_usage() endif if nargin < 2 bus = 0; endif retval = getTypeTerminals(obj, sprintf("i2c%d", bus)); if isempty(retval) && bus == 0 retval = getTypeTerminals(obj, "i2c"); endif endfunction %!test %! ar = arduino(); %! assert(!isempty(ar)); %! terms = getI2CTerminals(ar); %! assert (numel(terms) > 0) %! # should be pairs of i2c pins %! assert (mod(numel(terms),2), 0) arduino-0.12.1/inst/@arduino/getInterruptTerminals.m0000644000000000000000000000226314545566645017460 0ustar00## Copyright (C) 2019 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{pinlist} =} getInterruptTerminals (@var{ar}) ## Get a cell list of pin Ids available have interrupt functionality ## ## @subsubheading Inputs ## @var{ar} - the arduino object. ## ## @subsubheading Outputs ## @var{pinlist} - cell list of pin numbers available for interrupt use. ## ## @seealso{arduino} ## @end deftypefn function retval = getInterruptTerminals (obj) if nargin != 1 print_usage () endif retval = getTypeTerminals (obj, "interrupt"); endfunction %!test %! ar = arduino(); %! assert(!isempty(ar)); %! terms = getInterruptTerminals(ar); %! assert(!isempty(terms)); arduino-0.12.1/inst/@arduino/getLEDTerminals.m0000644000000000000000000000217414545566645016071 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{pinlist} =} getLEDTerminals (@var{ar}) ## Get a cell list of pin Ids available are connected natively to LEDs. ## ## @subsubheading Inputs ## @var{ar} - the arduino object. ## ## @subsubheading Outputs ## @var{pinlist} - cell list of pin numbers available for LED use. ## ## @seealso{arduino} ## @end deftypefn function retval = getLEDTerminals (obj) if nargin != 1 print_usage () endif retval = getTypeTerminals (obj, "led"); endfunction %!test %! ar = arduino(); %! assert(!isempty(ar)); %! terms = getLEDTerminals(ar); arduino-0.12.1/inst/@arduino/getMCU.m0000644000000000000000000000213514545566645014227 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{mcu} =} getMCU (@var{ar}) ## Get the MCU used by the connected arduino. ## ## @subsubheading Inputs ## @var{ar} - arduino object connected to a arduino board. ## ## @subsubheading Outputs ## @var{mcu} - string representing the mcu used by the arduino board. ## ## @seealso{arduino} ## @end deftypefn function retval = getMCU (obj) retval = obj.get_mcu (); endfunction %!test %! ar = arduino (); %! assert (!isempty (ar)); %! mcu = getMCU (ar); %! assert (ischar (mcu)) %! assert (mcu, ar.get_mcu ()) arduino-0.12.1/inst/@arduino/getPWMTerminals.m0000644000000000000000000000220414545566645016122 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{pinlist} =} getPWMTerminals (@var{ar}) ## Get a cell list of pin Ids available for PWM use. ## ## @subsubheading Inputs ## @var{ar} - the arduino object. ## ## @subsubheading Outputs ## @var{pinlist} - cell list of pin numbers available for PWM use. ## ## @seealso{arduino} ## @end deftypefn function retval = getPWMTerminals(obj) if nargin != 1 print_usage() endif retval = getTypeTerminals(obj, "pwm"); endfunction %!test %! ar = arduino(); %! assert(!isempty(ar)); %! terms = getPWMTerminals(ar); %! assert (numel(terms) > 0) arduino-0.12.1/inst/@arduino/getPinAlias.m0000644000000000000000000000263114545566645015304 0ustar00## Copyright (C) 2021 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{ouy} =} getPinAlias (@var{ar}, @var{pin}) ## Get the pin actual pin name from a pin alias. ## ## For example, the arduino Leonardo, pin "D4" is also "A6". ## ## @subsubheading Inputs ## @var{ar} - the connected arduino object. ## ## @var{pin} - a pin name. ## ## @subsubheading Outputs ## @var{out} - alias pin name, or same as @var{pin} if the pin doesnt have any alias names. ## ## @seealso{arduino, configurePinResource, getResourceOwner} ## @end deftypefn function retval = getPinAlias (obj, pin) if nargin != 2 print_usage () endif if !ischar(pin) error ("Expected pin name") endif p = obj.get_altpin(pin); if isempty(p) p = obj.get_pin(pin); endif retval = p.name; endfunction %!test %! ar = arduino(); %! pin = getPinAlias(ar, "D0"); %! assert (toupper (pin), "D0"); %! clear a arduino-0.12.1/inst/@arduino/getPinInfo.m0000644000000000000000000000711014545566645015143 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{pininfo} =} getPinInfo (@var{ar}, @var{pin}) ## @deftypefnx {} {@var{pininfoarray} =} getPinInfo (@var{ar}, @var{pinarray}) ## Get the pin information from the input pins values. ## ## getPinInfo (@var{ar}, @var{pin}) will get information for a single pin. ## ## getPinInfo (@var{ar}, @var{pinarray}) will get a cell array of pin information ## ## @subsubheading Inputs ## @var{ar} - the connected arduino object. ## ## @var{pin} - a pin number or pin name. ## ## @var{pinarray} - the array of pin numbers or names ## ## The pininfo struct contains the following fields: ## @table @asis ## @item terminal ## Terminal number of the pin ## @item name ## String name of the pin ## @item owner ## Current item owner of the pin ## @item mode ## Current configured mode for the pin ## @end table ## ## @subsubheading Outputs ## @var{pininfo} - struct on pin information. ## ## @var{pininfolist} - cell array of pin info ## ## @seealso{arduino, configurePinResource, getResourceOwner} ## @end deftypefn function retval = getPinInfo (obj, pins) if nargin != 2 print_usage () endif if iscell (pins) retval = {}; for i=1:numel (pins) p = obj.get_pin(pins{i}); inf = {}; inf.name = p.name; inf.terminal = p.id; inf.owner = p.owner; inf.mode = p.mode; retval{end+1} = inf; endfor elseif ischar(pins) p = obj.get_pin(pins); inf = {}; inf.name = p.name; inf.terminal = p.id; inf.owner = p.owner; inf.mode = p.mode; retval = inf; elseif isvector (pins) && numel (pins) == 1 p = obj.get_pin(pins); inf = {}; inf.name = p.name; inf.terminal = p.id; inf.owner = p.owner; inf.mode = p.mode; retval = inf; elseif isvector (pins) retval = {}; for i=1:numel (pins) p = obj.get_pin(pins(i)); inf = {}; inf.name = p.name; inf.terminal = p.id; inf.owner = p.owner; inf.mode = p.mode; retval{end+1} = inf; endfor elseif isnumeric (pins) p = obj.get_pin(pins); inf = {}; inf.name = p.name; inf.terminal = p.id; inf.owner = p.owner; inf.mode = p.mode; retval = inf; else error ("@arduino.getPinInfo: expected pins a array of numbers or names"); endif endfunction %!shared ar %! ar = arduino(); %!test %! info = getPinInfo(ar, 0); %! # terminal 0 is alwars D0 ? %! assert (isstruct (info)); %! assert (!iscell (info)); %! assert (toupper (info.name), "D0"); %! assert (info.terminal, 0); %!test %! info = getPinInfo(ar, "d0"); %! # terminal 0 is alwars D0 ? %! assert (isstruct (info)); %! assert (!iscell (info)); %! assert (toupper (info.name), "D0"); %! assert (info.terminal, 0); %!test %! info = getPinInfo(ar, [0 2]); %! assert(numel(info), 2); %! assert(iscell(info)); %! assert (toupper (info{1}.name), "D0"); %! assert (toupper (info{2}.name), "D2"); %!test %! info = getPinInfo(ar, {"d4", 5}); %! assert(numel(info), 2); %! assert(iscell(info)); %! assert (toupper (info{1}.name), "D4"); %! assert (toupper (info{2}.name), "D5"); arduino-0.12.1/inst/@arduino/getPinsFromTerminals.m0000644000000000000000000000426514545566645017225 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{pinnames} =} getPinsFromTerminals (@var{ar}, @var{terminals}) ## Get the pin names from the input terminal values. ## ## @subsubheading Inputs ## @var{ar} - the connected arduino object. ## ## @var{terminals} - the numeric pin number, or array of pin numbers to get pin names. ## ## @subsubheading Outputs ## @var{pinnames} - the string names of each input pin. If terminals was a single value, the return ## will be a single string, otherwise it will return a cell array of each pin name. ## ## @seealso{arduino, getTerminalsFromPins} ## @end deftypefn function retval = getPinsFromTerminals (obj, terminals) if nargin != 2 print_usage () endif if iscell (terminals) retval = {}; for i=1:numel (terminals) retval{end+1} = obj.get_pin (terminals{i}).name; endfor elseif isvector (terminals) && numel (terminals) == 1 retval = obj.get_pin (terminals).name; elseif isvector (terminals) retval = {}; for i=1:numel (terminals) retval{end+1} = obj.get_pin (terminals(i)).name; endfor elseif isnumeric (terminals) retval = obj.get_pin (terminals).name; else error ("@arduino.getPinsFromTerminals: expected terminals as vector"); endif endfunction %!shared ar %! ar = arduino(); %!assert(!isempty(ar)); %!test %! terms = getPinsFromTerminals(ar, 0); %! # terminal 0 is alwars D0 ? %! assert(ischar(terms)); %! assert(toupper(terms), "D0"); %!test %! terms = getPinsFromTerminals(ar, [0 2]); %! assert(numel(terms), 2); %! assert(iscell(terms)); %! assert(ischar(terms{1})); %! assert(toupper(terms{1}), "D0"); %! assert(toupper(terms{2}), "D2"); arduino-0.12.1/inst/@arduino/getResourceCount.m0000644000000000000000000000253114545566645016403 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{count} =} getResourceCount (@var{ar}, @var{resource}) ## Get the count of uses of a given resource. ## ## @subsubheading Inputs ## @var{ar} - connected arduino object ## ## @var{resource} - name of resource to get count for. ## ## @subsubheading Outputs ## @var{count} = count of uses registered to resource. ## ## @seealso{incrementResourceCount. decrementResourceCount} ## @end deftypefn function retval = getResourceCount (ar, resource) if nargin != 2 print_usage (); endif if !ischar(resource) error ("getResourceCount: expects resource name"); endif resinfo = ar.get_resource(resource); retval = resinfo.count; endfunction %!test %! ar = arduino(); %! assert(!isempty(ar)); %! assert(getResourceCount(ar,"notusedname"), 0); arduino-0.12.1/inst/@arduino/getResourceOwner.m0000644000000000000000000000276514545566645016416 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{owner} =} getResourceOwner (@var{ar}, @var{terminal}) ## Get the owner of pin allocated previously by configurePinResource. ## ## @subsubheading Inputs ## @var{ar} - connected arduino object ## ## @var{terminal} - terminal number to get owner of. ## ## @subsubheading Outputs ## @var{owner} = owner of the terminal pin, or "" if not owned. ## ## @seealso{configurePinResource} ## @end deftypefn function retval = getResourceOwner (obj, terminal) if nargin != 2 print_usage (); endif # note: matlab expects a number only - we will use either if or pin name if !ischar(terminal) && !isnumeric(terminal) error ("getResourceOwner: expects terminal id or pin name"); endif pininfo = obj.get_pin(terminal); retval = pininfo.owner; endfunction %!test %! ar = arduino(); %! assert(!isempty(ar)); %! configurePin(ar, "d2", "digitaloutput"); %! assert(getResourceOwner(ar,"d2"), "digital"); arduino-0.12.1/inst/@arduino/getSPITerminals.m0000644000000000000000000000202314545566645016111 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{pinlist} =} getSPITerminals (@var{ar}) ## Get a cell list of pin Ids available for SPI mode. ## ## @subsubheading Inputs ## @var{ar} - the arduino object. ## ## @subsubheading Outputs ## @var{pinlist} - cell list of pin numbers available for SPI use. ## ## @seealso{arduino} ## @end deftypefn function retval = getSPITerminals(obj) if nargin != 1 print_usage() endif retval = getTypeTerminals(obj, "spi"); endfunction arduino-0.12.1/inst/@arduino/getServoTerminals.m0000644000000000000000000000205314545566645016557 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{pinlist} =} getServoTerminals (@var{ar}) ## Get a cell list of pin Ids available for servo use. ## ## @subsubheading Inputs ## @var{ar} - the arduino object. ## ## @subsubheading Outputs ## @var{pinlist} - cell list of pin numbers available for servo use. ## ## @seealso{arduino, getPWMTerminals} ## @end deftypefn function retval = getServoTerminals(obj) if nargin != 1 print_usage() endif retval = getTypeTerminals(obj, "pwm"); endfunction arduino-0.12.1/inst/@arduino/getSharedResourceProperty.m0000644000000000000000000000323014545566645020263 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{count} =} getSharedResourceProperty (@var{ar}, @var{resource}, @var{property}) ## Get the value of a property from a given resource. ## ## @subsubheading Inputs ## @var{ar} - connected arduino object ## ## @var{resource} - name of resource to get property for. ## ## @var{property} - name of property from the resource. ## ## @subsubheading Outputs ## @var{propvalue} - value of the property ## ## @seealso{getResourceCount, setSharedResourceProperty} ## @end deftypefn function retval = getSharedResourceProperty (ar, resource, propname) if nargin != 3 print_usage (); endif if !ischar(resource) error ("getSharedResourceProperty: expects resource name"); endif if !ischar(propname) error ("getSharedResourceProperty: expects resource property name"); endif resinfo = ar.get_resource(resource); retval = resinfo.props.(tolower(propname)); endfunction %!test %! ar = arduino(); %! assert(!isempty(ar)); %! setSharedResourceProperty(ar, "notusedname", "propname", 16); %! assert(getSharedResourceProperty(ar,"notusedname", "propname"), 16); arduino-0.12.1/inst/@arduino/getTerminalMode.m0000644000000000000000000000270314545566645016164 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{mode} =} getTerminalMode (@var{ar}, @var{terminal}) ## Get the mode of a pin allocated previously by configurePinResource. ## ## @subsubheading Inputs ## @var{ar} - connected arduino object ## ## @var{terminal} - terminal number to get owner of. ## ## @subsubheading Outputs ## @var{mode} - mode of the terminal pin, or "not_set" if not owned. ## ## @seealso{configurePinResource, getResourceOwner} ## @end deftypefn function retval = getTerminalMode (obj, terminal) if nargin != 2 print_usage () endif pininfo = obj.get_pin (terminal); retval = pininfo.mode; endfunction %!test %! ar = arduino(); %! assert(!isempty(ar)); %! term = getTerminalsFromPins(ar, "d2"); %! configurePin(ar, "d2", "digitaloutput"); %! assert(getTerminalMode(ar, term), "digitaloutput"); %! configurePin(ar, "d2", "unset"); %! assert(getTerminalMode(ar, term), "unset"); arduino-0.12.1/inst/@arduino/getTerminalsFromPins.m0000644000000000000000000000317114545566645017220 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{pinnums} =} getTerminalsFromPins (@var{ar}, @var{pins}) ## Get the terminal number for each pin. ## ## @subsubheading Inputs ## @var{ar} - connected arduino object ## ## @var{pins} - single pin name or cell or vector array of pin names. ## ## @subsubheading Outputs ## @var{pinnums} - pin number of each named pin. If the input was a single string, returns a number. ## if the input pins was a vector or cell array, return a cell array of pin numbers corresponding ## to each input pin name. ## ## @seealso{arduino, getPinsFromTerminals} ## @end deftypefn function retval = getTerminalsFromPins(obj, pins) if nargin != 2 print_usage() endif if iscell (pins) retval = {}; for i=1:numel(pins) retval{end+1} = obj.get_pin(pins{i}).id; endfor elseif ischar(pins) retval = obj.get_pin(pins).id; elseif isvector (pins) retval = {}; for i=1:numel(pins) retval{end+1} = obj.get_pin(pins(i)).id; endfor else error ("getTerminalFromPins: expected pins as cell or string"); endif endfunction arduino-0.12.1/inst/@arduino/incrementResourceCount.m0000644000000000000000000000315314545566645017611 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{count} =} incrementResourceCount (@var{ar}, @var{resource}) ## Increment the count value of a named resource by 1 and return the ## new count ## ## @subsubheading Inputs ## @var{ar} - connected arduino object ## ## @var{resource} - name of resource to increment count. ## ## @subsubheading Outputs ## @var{count} = count of uses registered to resource. ## ## @seealso{getResourceCount. decrementResourceCount} ## @end deftypefn function retval = incrementResourceCount (ar, resource) if nargin != 2 print_usage (); endif if !ischar (resource) error ("@arduino.getResourceCount: expects resource name"); endif resinfo = ar.get_resource (resource); resinfo.count ++; ar.set_resource (resource, resinfo); retval = resinfo.count; endfunction %!test %! ar = arduino(); %! assert(!isempty(ar)); %! assert(getResourceCount(ar,"notusedname"), 0); %! assert(incrementResourceCount(ar,"notusedname"), 1); %! assert(getResourceCount(ar,"notusedname"), 1); %! assert(incrementResourceCount(ar,"notusedname"), 2); arduino-0.12.1/inst/@arduino/isTerminalAnalog.m0000644000000000000000000000332614545566645016337 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{ret} = } isTerminalAnalog (@var{obj}, @var{terminal}) ## Return true if pin is capable of analog input ## ## @subsubheading Inputs ## @var{ar} - the connected arduino object ## ## @var{terminal} is a terminal number to check ## ## @subsubheading Outputs ## @var{ret} return 1 if terminal is a analog pin, 0 otherwise ## ## @end deftypefn function retvalue = isTerminalAnalog (obj, terminal) if nargin != 2 error ('@arduino.isTerminalAnalog: expected single terminal value'); endif pininfo = obj.get_pin (terminal); idx = find (cellfun(@(x) strcmpi (x, "analog"), pininfo.modes), 1); if isempty (idx) retvalue = false; else retvalue = true; endif endfunction %!shared ar %! ar = arduino(); %!assert(isTerminalAnalog(ar,"d0"), false); %!assert(isTerminalAnalog(ar,"a0"), true); %!assert(isTerminalAnalog(ar,getTerminalsFromPins(ar, "a0")), true); %!error isTerminalAnalog() %!error isTerminalAnalog(ar) # octave 7 returns: # function called with too many inputs # octave 6 returns: expected single terminal value %!error isTerminalAnalog(ar, "d1", 1) arduino-0.12.1/inst/@arduino/isTerminalDigital.m0000644000000000000000000000342214545566645016510 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{ret} = } isTerminalDigital(@var{obj}, @var{terminal}) ## Return true if pin is capable of digital functions ## ## @subsubheading Inputs ## @var{ar} - the connected arduino object ## ## @var{terminal} is a terminal number to check ## ## @subsubheading Outputs ## @var{ret} return 1 if terminal is a digital pin, 0 otherwise ## @end deftypefn function retvalue = isTerminalDigital (obj, terminal) if nargin != 2 error ('@arduino.isTerminalDigital: expected single terminal value'); endif pininfo = obj.get_pin (terminal); idx = find (cellfun(@(x) strcmpi (x, "digital"), pininfo.modes), 1); if isempty (idx) retvalue = false; else retvalue = true; endif endfunction %!shared ar %! ar = arduino(); %!assert(isTerminalDigital(ar,"d0"), true); %!assert(isTerminalDigital(ar,getTerminalsFromPins(ar, "d0")), true); %!assert(isTerminalDigital(ar,"a0"), true); %!error isTerminalDigital() %!error isTerminalDigital(ar) # octave 7 returns: # function called with too many inputs # octave 6 returns: expected single terminal value %!error isTerminalDigital(ar, "d1", 1) %!error isTerminalDigital(ar, -1) arduino-0.12.1/inst/@arduino/playTone.m0000644000000000000000000000555114545566645014703 0ustar00## Copyright (C) 2018-2021 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} playTone (@var{ar}, @var{pin}, @var{freq}, @var{duration}) ## Play a tone of a given frequency on a specified pin. ## ## @subsubheading Inputs ## @var{ar} - connected arduino object ## ## @var{pin} - digital pin to play tone on ## ## @var{freq} - frequency in hertz to play between 0 and 32767Hz. ## ## @var{duration} duration in seconds to play tone between 0 and 30 seconds ## ## If duration is 0 or not specified, tone will continue to play until next tone is commanded. ## If frequency is 0, tone will stop playing ## ## @strong{NOTE:} use of playTone can interfere with PWM output. ## @end deftypefn function playTone (obj, pin, freq, duration) ARDUINO_PLAYTONE = 6; if nargin < 3 error ("@arduino.playTone: expected pin name and frequency"); endif if nargin < 4 duration = 0; endif if !ischar(pin) && !isnumeric(pin) error ("@arduino.playTone: expected pin name as string"); endif if (!isnumeric(freq) || freq < 0 || freq > 32767) error ("@arduino.playTone: expected freq between 0 .. 32767"); endif if (!isnumeric(duration) || duration < 0 || duration > 30) error ("@arduino.playTone: expected duration between 0 .. 30"); endif pininfo = obj.get_pin(pin); # first use ? if strcmp(pininfo.mode, "unset") configurePin(obj, pin, "digitaloutput") else [pinstate, pinmode] = pinStateMode(pininfo.mode); if !strcmp(pinmode, "digital") error ("@arduino.playTone: pin is in an incompatable mode"); endif endif freq = uint16(freq); freqh = bitshift (freq, -8); freql = bitand(freq, hex2dec('FF')); duration = uint16(duration*10); durh = bitshift (duration, -8); durl = bitand(duration, hex2dec('FF')); datain = uint8([pininfo.id freqh freql durh durl]); [dataout, status] = __sendCommand__ (obj, 0, ARDUINO_PLAYTONE, datain); if status != 0 error ("@arduino.playTone: failed to set tone err=%d - %s", status, char(dataout)); endif endfunction %!shared ar %! ar = arduino(); %!test %! if !strcmp(ar.Board, "due") %! playTone(ar,"d2", 0, 0); %! playTone(ar,"d2", 220, 1); %! playTone(ar, "d2", 0); %! else %! # due doesnt have playTone %! endif %!error playTone() %!error playTone(ar) %!error playTone(ar, "nopin", 220) arduino-0.12.1/inst/@arduino/private/0000755000000000000000000000000014545566645014376 5ustar00arduino-0.12.1/inst/@arduino/private/__digitalPin__.m0000644000000000000000000000332014545566645017432 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. see ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} __digitalPin__ (@var{obj}) ## Private function ## @end deftypefn function retval = __digitalPin__(obj, pin, value) ARDUINO_DIGITAL = 3; retval = 0; if !ischar(pin) && !isnumeric(pin) error ("@arduino.digitalPin: expected pin name as string"); endif pininfo = obj.get_pin(pin); if nargin == 2 mode = "digitalinput"; datain = uint8([pininfo.id]); elseif nargin == 3 mode = "digitaloutput"; if value val = 1; else val = 0; endif datain = uint8([pininfo.id val]); endif # first use ? if strcmp(pininfo.mode, "unset") configurePin(obj, pin, mode) else [pinstate, pinmode] = pinStateMode(pininfo.mode); if !strcmp(pinmode, "digital") error ("digitalPin: pin is in incompatable mode"); endif endif [dataout, status] = __sendCommand__ (obj, 0, ARDUINO_DIGITAL, datain); if status != 0 error ("digitalPin: failed to set/get pin state err=%d", status); endif if nargin == 2 if dataout(2) != 0 retval = 1; else retval = 0; endif endif endfunction arduino-0.12.1/inst/@arduino/private/__recvResponse__.m0000644000000000000000000000567314545566645020041 0ustar00## Copyright (C) 2021-2022 John Donoghue ## ## 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. see ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} __recvResponse__ (@var{obj}, @var{lib}, @var{cmd}, @var{timeout}) ## Private function ## @end deftypefn function [dataOut, errcode] = __recvResponse__ (dev, libid, cmd, timeout, debug) dataOut = []; errcode = 0; set(dev, "timeout", timeout); # TODO: current serial doesnt have a way to know if any data is awaiting # so try read what we need first without waiting ? # read in initial part [tmpdataOut, tmpdataSize] = fread (dev, 4); if (debug) printf("<< "); printf("%d ", tmpdataOut); printf("\n"); endif if tmpdataSize < 4 errcode = 1; dataOut = "Undersized packet header"; elseif tmpdataOut(1) != hex2dec("A5") || tmpdataOut(2) != libid || (tmpdataOut(3) != cmd && tmpdataOut(3) < 253) errcode = 2; dataOut = "Malformed packet header"; elseif (tmpdataOut(3) == 254) # got a wait for response value - length is expected to be 0 if (debug) printf("* wait for response\n"); endif set(dev, "timeout", -1); [tmpdataOut, tmpdataSize] = fread (dev, 4); if (debug) printf("<< "); printf("%d ", tmpdataOut); printf("\n"); endif if tmpdataSize < 4 errcode = 1; dataOut = "Undersized packet header"; elseif tmpdataOut(1) != hex2dec("A5") || tmpdataOut(2) != libid || (tmpdataOut(3) != cmd && tmpdataOut(3) != 255) errcode = 2; dataOut = "Malformed packet header"; endif endif if(errcode == 0) expectlen = tmpdataOut(4); if expectlen > 0 [dataOut, tmpdataSize] = fread (dev, expectlen); if (debug) printf("<< "); printf("%d ", dataOut); printf("\n"); endif else tmpdataSize = 0; endif if tmpdataSize != expectlen errcode = 3; dataOut = "Malformed packet body"; elseif tmpdataOut(3) == 255 # valid packet, but was coz we got an error errcode = 10; if expectlen == 0 dataOut = "Recieved error status";; else dataOut = char(dataOut); endif elseif tmpdataOut(3) == 253 # valid but was a debug message if debug s = char(dataOut); printf("DEBUG: %s\n", s); endif [dataOut, errcode] = __recvResponse__ (dev, libid, cmd, timeout, debug); else errcode = 0; # all is good endif endif endfunction arduino-0.12.1/inst/@arduino/private/__sendCommand__.m0000644000000000000000000000367514545566645017613 0ustar00## Copyright (C) 2018-2022 John Donoghue ## ## 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. see ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} __sendCommand__ (@var{obj}, @var{cmd}, @var{data}, @var{timeout}) ## Private function ## @end deftypefn ## Author: jdonoghue ## Created: 2018-05-15 function [dataOut, errcode] = __sendCommand__ (obj, libid, cmd, data, timeout) if nargin < 3 error ("@arduino.__sendCommand__: expected command"); endif % send command and get back reponse if !isa(obj.connected, "octave_serialport") && !isa(obj.connected, "octave_tcp") error ("@arduino.__sendCommand__: not connected to a arduino"); endif % connected yet ? % simple procol here, each field is a byte % sends A5 EXT CMD datasize [data,,,] % currently ext is 0 - may use later to identify module to send to ? % A5 00 00 00 = reset % A5 00 01 00 = req board info dataOut = []; errcode = 0; if (nargin < 4) data = []; endif if (nargin < 5) timeout = 0.5; endif if iscell(data) data = cell2mat(data); endif hdr = uint8([ hex2dec("A5") libid cmd numel(data)]); set(obj.connected, "timeout", timeout); len = fwrite(obj.connected, [hdr data]); if (obj.debug) printf(">> "); printf("%d ", [hdr data]); printf("\n"); endif [dataOut, errcode] = __recvResponse__ (obj.connected, libid, cmd, timeout, obj.debug); endfunction arduino-0.12.1/inst/@arduino/private/getTypeTerminals.m0000644000000000000000000000217514545566645020061 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. see ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} getTypeTerminals (@var{ar}, @var{ar}) # Private function ## @end deftypefn function retval = getTypeTerminals(obj, type) if nargin != 2 print_usage() endif retval = {}; for i=1:numel(obj.config.pins) pininfo = obj.config.pins{i}; # strncmp do can patch spi from spiX_XX etc idx = find( cellfun(@(x) strncmpi(x, type, length(type)), pininfo.modes), 1); if !isempty(idx) retval{end+1}=pininfo.id; endif endfor endfunction arduino-0.12.1/inst/@arduino/private/pinStateMode.m0000644000000000000000000000442714545566645017157 0ustar00## Copyright (C) 2018-2019 John Donoghue ## ## 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. see ## . ## -*- texinfo -*- ## @deftypefn {} {@var{value} =} pinStateMode (@var{pinStateVal}) ## Private function ## @end deftypefn function [pstate, pmode] = pinStateMode (pinStateVal) if ischar(pinStateVal) switch (tolower(pinStateVal)) case "unset" pstate = 0; pmode="none"; case "analoginput" pstate = 1; pmode = "analog"; case "digitalinput" pstate = 2; pmode="digital"; case "digitaloutput" pstate = 3; pmode="digital"; case "pullup" pstate = 4; pmode = "digital"; case "i2c" pstate = 5; pmode = "i2c"; case "pwm" pstate = 6; pmode="pwm"; case "servo" pstate = 7; pmode="pwm"; case "spi" pstate = 3; pmode="spi"; % for now just setting as output case "interrupt" pstate = 2; pmode="interrupt"; % for now just setting as input case "reserved" pstate = 10; pmode="reserved"; otherwise error ("unknown pin state %s", pinStateVal); endswitch else switch (pinStateVal) case 1 pstate = "analoginput"; pmode="analog"; case 2 pstate = "digitalinput"; pmode="digital"; case 3 pstate = "digitaloutput"; pmode="digital"; case 4 pstate = "pullup"; pmode="digital"; case 5 pstate = "i2c"; pmode="i2c"; case 6 pstate = "pwm"; pmode="pwm"; case 7 pstate = "servo"; pmode="pwm"; case 8 pstate = "spi"; pmode="spi"; case 9 pstate = "interrupt"; pmode="interrupt"; case 10 pstate = "reserved"; pmode="reserved"; otherwise pstate = "unset"; pmode=""; endswitch endif endfunction arduino-0.12.1/inst/@arduino/readAnalogPin.m0000644000000000000000000000462214545566645015612 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{value} =} readAnalogPin (@var{ar}, @var{pin}) ## Read analog voltage of @var{pin}. ## ## @subsubheading Inputs ## @var{ar} - connected arduino object. ## ## @var{pin} - string name of the pin to read. ## ## @subsubheading Outputs ## @var{value} - analog value of the pin ## ## @subsubheading Example ## @example ## @code{ ## ar = arduino (); ## readAnalogPin(ar, "A4"); ## ans = ## 87 ## } ## @end example ## @seealso{arduino, readVoltage} ## @end deftypefn function value = readAnalogPin (obj, pin) ARDUINO_ANALOG = 4; if nargin != 2 error ("@arduino.readAnalogPin: expected pin name and value"); endif if !ischar(pin) error ("@arduino.readAnalogPin: expected pin name as string"); endif pininfo = obj.get_pin(pin); # first use ? if strcmp(pininfo.mode, "unset") configurePin(obj, pin, "analoginput") else [pinstate, pinmode] = pinStateMode(pininfo.mode); if !strcmp(pinmode, "analog") error ("readAnalogPin: pin is in incompatable mode"); endif endif datain = uint8([pininfo.id]); [dataout, status] = __sendCommand__ (obj, 0, ARDUINO_ANALOG, datain); if status != 0 error ("readVoltage: failed to set pin state err=%d - %s", status, char(dataout)); endif value = (uint16(dataout(2))*256 + uint16(dataout(3))); endfunction %!shared ar %! ar = arduino(); %!test %! readAnalogPin(ar,"a0"); %! readAnalogPin(ar,"a1"); %! readAnalogPin(ar,"a2"); %! readAnalogPin(ar,"a3"); %! readAnalogPin(ar,"a4"); %! readAnalogPin(ar,"a5"); %!error readAnalogPin(ar,"d2"); %!error readAnalogPin() %!error readAnalogPin(ar) # octave 7 returns: # function called with too many inputs # octave 6 returns: expected pin name %!error readAnalogPin(ar, "a0", 2) %!error readAnalogPin(ar, "nopin") arduino-0.12.1/inst/@arduino/readDigitalPin.m0000644000000000000000000000343114545566645015763 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{value} =} readDigitalPin (@var{obj}, @var{pin}) ## Read digital value from a digital I/O pin. ## ## @subsubheading Inputs ## @var{ar} - connected arduino object. ## ## @var{pin} - string name of the pin to read. ## ## @subsubheading Outputs ## @var{value} - the logical value (0, 1, true false) of the current pin state. ## ## @subsubheading Example ## @example ## @code{ ## a = arduino (); ## pinvalue = readDigitalPin (a, 'D5'); ## } ## @end example ## ## @seealso{arduino, writeDigitalPin} ## @end deftypefn function retval = readDigitalPin (obj, pin) if nargin != 2 error ("@arduino.readDigitalPin: expected pin name"); endif if !ischar(pin) && !isnumeric(pin) error ("@arduino.readDigitalPin: expected pin name as string"); endif retval = __digitalPin__(obj, pin); endfunction %!shared ar %! ar = arduino(); %!test %! readDigitalPin(ar,"d2"); %! assert(readDigitalPin(ar,"d2"), readDigitalPin(ar,2)); %!error readDigitalPin() %!error readDigitalPin(ar) # octave 7 returns: # function called with too many inputs # octave 6 returns: expected pin name %!error readDigitalPin(ar, "d2", 2) %!error readDigitalPin(ar, "nopin") arduino-0.12.1/inst/@arduino/readVoltage.m0000644000000000000000000000371614545566645015346 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{voltage} =} readVoltage (@var{ar}, @var{pin}) ## Read analog voltage of a pin. ## ## @subsubheading Inputs ## @var{ar} - connected arduino. ## ## @var{pin} - pin name or number to query for voltage ## ## @subsubheading Outputs ## @var{voltage} - scaled pin value as a voltage ## ## @subsubheading Example ## @example ## @code{ ## ar = arduino (); ## readVoltage(ar, "A4"); ## ans = ## 1.401 ## } ## @end example ## @seealso{arduino, readAnalogPin} ## @end deftypefn function voltage = readVoltage (ar, pin) if nargin != 2 error ("@arduino.readVoltage: expected pin name and value"); endif if !ischar(pin) error ("@arduino.readVoltage: expected pin name as string"); endif voltage = double(readAnalogPin(ar,pin)) * (ar.board_voltage() / 1023.0); endfunction %!shared ar %! ar = arduino(); %!test %! readVoltage(ar,"a0"); %! readVoltage(ar,"a1"); %! readVoltage(ar,"a2"); %! readVoltage(ar,"a3"); %! readVoltage(ar,"a4"); %! readVoltage(ar,"a5"); %! val = readVoltage(ar,"a0"); %! assert(isnumeric(val)); %! assert(val <= 5.0); %! assert(val >= 0); %!error readVoltage(ar,"d2"); %!error readVoltage() %!error readVoltage(ar) # octave 7 returns: # function called with too many inputs # octave 6 returns: expected pin name %!error readVoltage(ar, "a0", 2) %!error readVoltage(ar, "nopin") arduino-0.12.1/inst/@arduino/reset.m0000644000000000000000000000235214545566645014226 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {} reset (@var{ar}) ## Send reset command to arduino hardware to force a hardware reset. ## ## @subsubheading Inputs ## @var{ar} - connected arduino object. ## ## @seealso{arduino} ## @end deftypefn function reset (ar) ARDUINO_RESET = 0; if nargin != 1 error ("@arduino.reset: expected arduiono object only"); endif [dataout, status] = __sendCommand__ (ar, 0, ARDUINO_RESET, [], 0); endfunction %!test %! ar = arduino(); %! assert(!isempty(ar)); %! reset(ar); %! pause(1); arduino-0.12.1/inst/@arduino/sendCommand.m0000644000000000000000000000575314545566645015344 0ustar00## Copyright (C) 2018-2020 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{outdata, outsize} =} sendCommand (@var{ar}, @var{libname}, @var{commandid}) ## @deftypefnx {} {@var{outdata, outsize} =} sendCommand (@var{ar}, @var{libname}, @var{commandid}, @var{data}) ## @deftypefnx {} {@var{outdata, outsize} =} sendCommand (@var{ar}, @var{libname}, @var{commandid}, @var{data}, @var{timeout}) ## Send a command with option data to the connected arduino, waiting up to a specified number of seconds ## for a response. ## ## @subsubheading Inputs ## @var{ar} - connected arduino object. ## ## @var{libname} - library sending the command. The name should match a programmed ## library of the arduino, or an error will be displayed. ## ## @var{commandid} - integer value for the command being sent to the arduino. ## ## @var{data} - optional data sent with the command. ## ## @var{timeout} - optional timeout to wait for data ## ## @subsubheading Outputs ## @var{outdata} - data returned back from the arduino in response to command ## ## @var{outsize} - size of data received ## ## If the arduino fails to respond with a valid reply, sendCommand will error. ## ## @seealso{arduino} ## @end deftypefn function [dataOut,payloadSize] = sendCommand (obj, libname, commandid, data, timeout) if nargin < 3 error ('sendCommand: missing expected arguments of libname, commandid'); endif if (isempty(libname)) libid = 0; else libid = obj.get_lib(libname); if libid == -1 error ("sendCommand: unknown or unprogrammed library '%s'.", libname); endif endif if ! isnumeric (commandid) error ('sendCommand: command id should be a number'); endif if (nargin < 4) data = []; endif if (nargin < 5) timeout = 5; endif [dataOut, status] = __sendCommand__ (obj, libid, commandid, data, timeout); if status != 0 error ("sendCommand: failed err=%d: msg=%s", status, char(dataOut)); endif payloadSize = numel(dataOut); endfunction %!shared ar %! ar = arduino(); %!error sendCommand(); %!error sendCommand(ar); %!error sendCommand(ar, ""); %!error sendCommand(ar, "", "str"); %!test %! % valid config pin msg %! assert(numel(sendCommand(ar, "", 2, [2])) > 0); # valid packet, but unknown id %!error sendCommand(ar, "", 255, [2 2]); # query config pin without the data %!error sendCommand(ar, "", 2); arduino-0.12.1/inst/@arduino/setSharedResourceProperty.m0000644000000000000000000000474114545566645020307 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} setSharedResourceProperty (@var{ar}, @var{resource}, @var{propname}, @var{propvalue}) ## @deftypefnx {} {} setSharedResourceProperty (@var{ar}, @var{resource}, @var{propname}, @var{propvalue}, ___) ## Set property values for a given resource. ## ## @subsubheading Inputs ## @var{ar} - connected arduino object ## ## @var{resource} - name of resource to get property for. ## ## @var{propname} - name of property from the resource. ## ## @var{propvalue} - value of property from the resource. ## ## Multiple @var{propname}, @var{propvalue} pairs can be given. ## ## @subsubheading Outputs ## None ## ## @subsubheading Example ## @example ## @code{ ## ar = arduino(); ## setSharedResourceProperty(ar, "myresource", "myproperty", [1 2 3]) ## } ## @end example ## ## @seealso{getSharedResourceProperty} ## @end deftypefn function setSharedResourceProperty (varargin) if nargin < 4 print_usage (); endif if mod(nargin, 2) != 0 error ("{getSharedResourceProperty: expected property name, value pairs"); endif if !iscellstr (varargin(3:2:nargin)) error ("{getSharedResourceProperty: expected property names to be strings"); endif ar = varargin{1}; resource = varargin{2}; if !ischar(resource) error ("getSharedResourceProperty: expects resource name"); endif resinfo = ar.get_resource(resource); for i = 3:2:nargin propname = tolower(varargin{i}); propvalue = varargin{i+1}; resinfo.props.(propname) = propvalue; endfor ar.set_resource(resource, resinfo); endfunction %!test %! ar = arduino(); %! assert(!isempty(ar)); %! setSharedResourceProperty(ar, "notusedname", "propname1", 16); %! setSharedResourceProperty(ar, "notusedname", "propname2", 32); %! assert(getSharedResourceProperty(ar,"notusedname", "propname1"), 16); %! setSharedResourceProperty(ar, "notusedname", "propname1", []); %! assert(getSharedResourceProperty(ar,"notusedname", "propname1"), []); arduino-0.12.1/inst/@arduino/uptime.m0000644000000000000000000000340314545566645014405 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{sec} =} uptime (@var{ar}) ## Get the number of seconds the arduino board has been running concurrently. ## ## ## @subsubheading Inputs ## @var{ar} - the arduino object of the connection to an arduino board. ## ## @subsubheading Outputs ## @var{sec} - the number seconds the board has been running. Note that the count will wrap around after ## approximately 50 days. ## ## @seealso{arduino} ## ## @end deftypefn function retval = uptime (obj) persistent ARDUINO_UPTIME = 21; if nargin != 1 error ("@arduino.version expects no arguments"); endif [dataout, status] = __sendCommand__ (obj, 0, ARDUINO_UPTIME, []); if status != 0 error ("@arduino.uptime: failed err=%d - %s", status, char(dataout)); else value = uint32(dataout(1))*256*256*256 + uint32(dataout(2))*256*256 + uint32(dataout(3))*256 + uint32(dataout(4)); retval = double(value)/1000.0; endif endfunction %!test %! ar = arduino(); %! assert(!isempty(ar)); %! t1 = uptime(ar); %! pause (1); %! t2 = uptime(ar); %! assert(t1 < t2); arduino-0.12.1/inst/@arduino/validatePin.m0000644000000000000000000000411314545566645015341 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} validatePin (@var{ar}, @var{pin}, @var{type}) ## Validate that the mode is allowed for specified pin ## ## If the mode is not valid, and error will be thrown. ## ## @subsubheading Inputs ## @var{ar} - connected arduino object ## ## @var{pin} - name of pin to query mode validity of ## ## @var{mode} - mode to query ## ## Known modes are: ## @itemize @bullet ## @item 'I2C' ## @item 'SPI' ## @item 'PWM' ## @item 'Servo' ## @item 'analog' ## @item 'digital' ## ## @end itemize ## ## @seealso{arduino, configurePin} ## @end deftypefn function validatePin (obj, pin, type) if nargin < 3 error ("@arduino.validatePin: expected pin name and type"); endif if !ischar(pin) || !ischar(type) error ("@arduino.validatePin: expected pin name and type as string"); endif pininfo = obj.get_pin(pin); # use type length, so can find spiX_XXXX etc when looking for SPI idx = find( cellfun(@(x) strncmpi(x, type, length(type)), pininfo.modes), 1); # check with mode allowed to that pin # if isnt, error if isempty(idx) error ("@arduino.validatePin: invalid mode for this pin"); endif endfunction %!shared ar %! ar = arduino(); %!test %! validatePin(ar, "d1", "digital"); %! validatePin(ar, "a0", "digital"); %! validatePin(ar, "a0", "analog"); %!error validatePin(ar,"d1", "analog"); %!error validatePin() %!error validatePin(ar) %!error validatePin(ar, "d1") %!error validatePin(ar, "xd1", "digital") arduino-0.12.1/inst/@arduino/version.m0000644000000000000000000000304314545566645014567 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{ver} =} version (@var{ar}) ## Get version of library code installed on arduino board ## ## @subsubheading Inputs ## @var{ar} - the arduino object of the connection to an arduino board. ## ## @subsubheading Outputs ## @var{ver} - version string in format of X.Y.Z. ## ## @seealso{arduino} ## ## @end deftypefn function retval = version (obj) persistent ARDUINO_VERSION = 20; if nargin != 1 error ("@arduino.version expects no arguments"); endif [dataout, status] = __sendCommand__ (obj, 0, ARDUINO_VERSION, []); if status != 0 error ("@arduino.version: failed err=%d - %s", status, char(dataout)); else retval = sprintf("%d.%d.%d", dataout(1), dataout(2), dataout(3)); endif endfunction %!test %! ar = arduino(); %! assert(!isempty(ar)); %! assert(~isempty(version(ar))); arduino-0.12.1/inst/@arduino/writeDigitalPin.m0000644000000000000000000000413114545566645016200 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} writeDigitalPin (@var{ar}, @var{pin}, @var{value}) ## Write digital value to a digital I/O pin. ## ## @subsubheading Inputs ## @var{ar} - connected arduino object. ## ## @var{pin} - string name of the pin to write to. ## ## @var{value} - the logical value (0, 1, true false) to write to the pin. ## ## If pin was unconfigured before using, pin is set into digital mode. ## ## @subsubheading Example ## @example ## @code{ ## a = arduino(); ## writeDigitalPin(a,'D5',1); ## } ## @end example ## ## @seealso{arduino, readDigitalPin} ## ## @end deftypefn function writeDigitalPin (obj, pin, value) if nargin != 3 error ("@arduino.writeDigitalPin: expected pin name and value"); endif if !ischar(pin) && !isnumeric(pin) error ("@arduino.writeDigitalPin: expected pin name as string"); endif if (!isnumeric(value) && !islogical(value)) || (value != 1 && value != 0) error ("@arduino.writeDigitalPin: expected value as logical or 0 or 1"); endif __digitalPin__(obj,pin,value); endfunction %!shared ar %! ar = arduino(); %!test %! writeDigitalPin(ar,"d2", 1); %! writeDigitalPin(ar,"d2", 0); %! writeDigitalPin(ar,"d2", false); %! writeDigitalPin(ar,"d2", true); %! writeDigitalPin(ar,2, true); %!error writeDigitalPin() %!error writeDigitalPin(ar) # octave 7 returns: # function called with too many inputs # octave 6 returns: expected pin name and value %!error writeDigitalPin(ar, "d2", 1, 1) %!error writeDigitalPin(ar, "nopin", 1) arduino-0.12.1/inst/@arduino/writePWMDutyCycle.m0000644000000000000000000000505414545566645016452 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} writePWMDutyCyle (@var{ar}, @var{pin}, @var{value}) ## Set pin to output a square wave with a specified duty cycle. ## ## @subsubheading Inputs ## @var{ar} - connected arduino object ## ## @var{pin} - pin to write to. ## ## @var{value} - duty cycle value where 0 = off, 0.5 = 50% on, 1 = always on. ## ## @subsubheading Example ## @example ## @code{ ## a = arduino(); ## writePWMDutyCycle(a,'D5',0.5); ## } ## @end example ## ## @seealso{arduino, writePWMVoltage} ## ## @end deftypefn function writePWMDutyCycle (obj, pin, value) ARDUINO_PWM = 5; if nargin < 3 error ("@arduino.writePWMDutyCycle: expected pin name and value"); endif if !ischar(pin) && !isnumeric(pin) error ("@arduino.writePWMDutyCycle: expected pin name as string"); endif if (!isnumeric(value) || value > 1.0 || value < 0) error ("@arduino.writePWMDutyCycle: expected value between 0 .. 1"); endif pininfo = obj.get_pin(pin); # first use ? if strcmp(pininfo.mode, "unset") configurePin(obj, pin, "pwm") else [pinstate, pinmode] = pinStateMode(pininfo.mode); if !strcmp(pinmode, "pwm") error ("@arduino.PWMDutyCycle: pin is in incompatable mode"); endif endif val = 255*value; datain = uint8([pininfo.id val]); [dataout, status] = __sendCommand__ (obj, 0, ARDUINO_PWM, datain); if status != 0 error ("@arduino.writePWMDutyCycle: failed to set pin state err=%d - %s", status, char(dataout)); endif endfunction %!shared ar, pwmpin %! ar = arduino(); %! pwmpin = getPinsFromTerminals(ar, getPWMTerminals(ar)){1}; %!test %! writePWMDutyCycle(ar, pwmpin, 0.5); %!error writePWMDutyCycle(); %!error writePWMDutyCycle(ar) %!error writePWMDutyCycle(ar, pwmpin) %!error writePWMDutyCycle(ar, "xd1", 1) %!error writePWMDutyCycle(ar, pwmpin, -1) %!error writePWMDutyCycle(ar, pwmpin, 1.1) %!test %! writePWMDutyCycle(ar, pwmpin, 0.0); arduino-0.12.1/inst/@arduino/writePWMVoltage.m0000644000000000000000000000411214545566645016140 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} writePWMVoltage (@var{ar}, @var{pin}, @var{voltage}) ## Emulate an approximate voltage out of a pin using PWM. ## ## @subsubheading Inputs ## @var{ar} - connected arduino object ## ## @var{pin} - pin to write to. ## ## @var{voltage} - voltage to emulate with PWM, between 0 - 5.0 ## ## @subsubheading Example ## @example ## @code{ ## a = arduino(); ## writePWMVoltage(a,'D5',1.0); ## } ## @end example ## ## @seealso{arduino, writePWMDutyCycle} ## @end deftypefn function writePWMVoltage (obj, pin, value) if nargin < 3 error ("@arduino.writePWMVoltage: expected pin name and value"); endif # TODO: need look at board type for what voltage range is allowed # and convert maxvolts = obj.board_voltage(); if !isnumeric(value) || value < 0 || value > maxvolts error('writePWMVoltage: value must be between 0 and %f', maxvolts); endif # assuming here for now 0 .. 5V is linear to 0 - 100% pwm val = value/maxvolts; writePWMDutyCycle(obj, pin, val); endfunction %!shared ar, pwmpin %! ar = arduino(); %! pwmpin = getPinsFromTerminals(ar, getPWMTerminals(ar)){1}; %!test %! writePWMVoltage(ar, pwmpin, ar.AnalogReference); %!error writePWMVoltage(); %!error writePWMVoltage(ar) %!error writePWMVoltage(ar, pwmpin) %!error writePWMVoltage(ar, "xd1", 1) %!error writePWMVoltage(ar, pwmpin, -1) %!error writePWMVoltage(ar, pwmpin, 5.1) %!test %! writePWMVoltage(ar, pwmpin, 0.0); arduino-0.12.1/inst/@device/0000755000000000000000000000000014545566645012522 5ustar00arduino-0.12.1/inst/@device/delete.m0000644000000000000000000000434414545566645014147 0ustar00## Copyright (C) 2020 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} delete (@var{dev}) ## Free resources of a device object. ## ## @subsubheading Inputs ## @var{dev} - object to free ## ## @seealso{device} ## @end deftypefn function delete(this) try ar = this.parent; resource = this.resourceowner; pins = this.pins; if !isempty(ar) if strcmp(resource, "i2c") cleanupI2Cdevice(ar, resource, pins) elseif strcmp(resource, "spi") cleanupSPIdevice(ar, resource, pins) elseif strcmp(resource, "serial") cleanupSerialdevice(ar, resource, pins) endif this.parent = []; endif catch # do nothing end_try_catch endfunction # private clean up allocated pins function cleanupI2Cdevice(ar, resource, pins) # currently doing nothing x = resource; endfunction function cleanupSerialdevice(ar, resource, pins) # currently doing nothing x = resource; endfunction # private clean up allocated pins function cleanupSPIdevice(ar, resource, pins) for i=1:numel(pins) pin = pins{i}; if strcmp(tolower(pin.func), "cs") configurePinResource(ar, pin.name, pin.owner, pin.mode, true); configurePin(ar, pin.name, pin.mode); endif endfor # clean up the spi port if not used? count = getResourceCount(ar, resource); if count > 0 count = decrementResourceCount(ar, resource); if count == 0 # last user, so free pins (except ss that we already did) pins = getSharedResourceProperty(ar, resource, "pins"); for i=1:numel(pins) pin = pins{i}; configurePinResource(ar, pin.name, pin.owner, pin.mode, true); configurePin(ar, pin.name, pin.mode); endfor endif endif endfunction arduino-0.12.1/inst/@device/device.m0000644000000000000000000004344414545566645014150 0ustar00## Copyright (C) 2019-2020 John Donoghue ## ## 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. classdef device < handle ## -*- texinfo -*- ## @deftypefn {} {@var{dev} =} device (@var{ar}, 'I2CAddress', @var{address}) ## @deftypefnx {} {@var{dev} =} device (@var{ar}, 'SPIChipSelectPin', @var{pin}) ## @deftypefnx {} {@var{dev} =} device (@var{ar}, 'Serial', @var{serialid}) ## @deftypefnx {} {@var{dev} =} device (..., @var{propname}, @var{propvalue}) ## Create an i2c, spi or serial object to communicate on a connected arduino. ## ## @subsubheading Inputs ## @var{ar} - connected arduino object ## ## @var{propname}, @var{propvalue} - property name/value pair for values to pass to devices. ## ## A property of 'i2caddress', 'spichipselectpin' or 'serial' must be specified to denote the device type to create. ## ## @var{i2caddress} - address to use for device on I2C bus. ## ## @var{pin} - pin to use for device SPI chip select. ## ## @var{serialid} - Serial port id to use ## ## Additional properties can also be specified for the device object ## ## Currently known input I2C properties values: ## @table @asis ## @item bus ## bus number (when arduino board supports multiple I2C buses) ## with value of 0 or 1. ## @item noprobe ## Do not probe the existence of device on creation if set to 1 (default 0) ## @item bitrate ## bit rate speed in Mbs - default 100000 ## @end table ## ## ## ## Currently known input SPI properties values: ## @table @asis ## @item bitrate ## bit rate speed in Mbs ## @item bitorder ## 'msbfirst' or 'lsbfirst' ## @item spimode ## SPI mode 0 - 3. ## @end table ## ## ## ## Currently known input Serial properties values: ## @table @asis ## @item baudrate ## baudrate value (default 9600) ## @item databits ## number of databits (5,6,7,8) (default 8) ## @item stopbits ## number of stopbits (1,2) (default 1) ## @item parity ## parity of device ('odd','even','none') (default 'none') ## @end table ## ## ## @subsubheading Outputs ## @var{dev} - new created device object. ## ## @subsubheading Properties ## The object has the following public properties: ## @table @asis ## @item parent ## The parent (arduino) for this device ## @item interface ## The interface type for this device ("SPI" or "I2C" or "Serial") ## @end table ## ## In addition, depending on type, the object will have these properties: ## ## @subsubheading I2C Properties ## The object has the following public properties: ## @table @asis ## @item bus ## bus used for created object ## @item i2caddress ## I2C address set for object ## @item sclpin ## the SCL pin of the device ## @item sdapin ## the SDA pin of the device ## @item bitrate ## bit rate for the i2c clock ## @end table ## ## @subsubheading SPI Properties ## The object has the following public properties: ## @table @asis ## @item spimode ## mode used for created object ## @item bitrate ## Bitrate set for object ## @item bitorder ## Bitorder set for object ## @item spichipselectpin ## Pin used for chipselect ## @item mosipin ## Pin used for mosi ## @item misopin ## Pin used for miso ## @item sckpin ## Pin used for sckpin ## @end table ## ## @subsubheading Serial Properties ## The object has the following public properties: ## @table @asis ## @item id ## serial port id ## @item baudrate ## baudrate ## @item databits ## number of databits (5,6,7,8) ## @item stopbits ## number of stopbits (1,2) ## @item parity ## parity of device ('odd','even','none') ## @end table ## ## @seealso{arduino, i2cdev, spidev} ## @end deftypefn properties (Access = private) parent = []; id = []; devinfo = {}; pins = {}; interface = ""; resourceowner = ""; endproperties methods (Access = public) function this = device(varargin) persistent ARDUINO_I2C_CONFIG = 1; persistent ARDUINO_SPI_CONFIG = 1; persistent ARDUINO_SERIAL_CONFIG = 1; if nargin < 3 error("expects arduino object and properties"); endif #this.parent = varargin{1}; has_add_param = true; try p = inputParser(); p.addParameter("test", 1); catch has_add_param = false; end_try_catch # parse args p = inputParser(); p.CaseSensitive = false; p.FunctionName = 'device'; p.KeepUnmatched = true; p.addRequired('ar', @isarduino); if has_add_param p.addParameter('I2CAddress', -1, @isnumeric); p.addParameter('SPIChipSelectPin', ""); p.addParameter('Serial', ""); else p.addParamValue('I2CAddress', -1, @isnumeric); p.addParamValue('SPIChipSelectPin', ""); p.addParamValue('Serial', ""); endif p.parse(varargin{:}); this.parent = p.Results.ar; # NOTE: dont use fields of our object in the function handle or we will # never be unreferenced # pin_type = @(x) !isempty(getPinInfo(p.Results.ar, x)); pin_type = @(x) (isnumeric(x) || (ischar(x) && !isempty(regexp(x, "[aAdD]\\d+")))); if p.Results.I2CAddress != -1 && isempty(p.Results.SPIChipSelectPin) && isempty(p.Results.Serial) this.interface = "I2C"; bus_type = @(x) (isnumeric(x) && x >= 0 && x <= 1); bool_type = @(x) ((isnumeric(x) && (x ==0 || x == 1)) || islogical(x)); i2caddr = p.Results.I2CAddress; p = inputParser(); p.FunctionName = 'device'; p.CaseSensitive = false; p.addRequired('ar', @isarduino); if has_add_param p.addParameter('I2CAddress', "", @isnumeric); p.addParameter('Bus', 0, bus_type); p.addParameter('BitRate', 100000, @isnumeric); p.addParameter('NoProbe', 0, bool_type); else p.addParamValue('I2CAddress', i2caddr, @isnumeric); p.addParamValue('Bus', 0, bus_type); p.addParamValue('BitRate', 100000, @isnumeric); p.addParamValue('NoProbe', 0, bool_type); endif p.parse(varargin{:}); this.id = p.Results.Bus; this.devinfo.address = p.Results.I2CAddress; this.devinfo.bus = p.Results.Bus; this.devinfo.bitrate = p.Results.BitRate; this.resourceowner = "i2c"; this.pins = this.parent.get_group(["i2c" num2str(this.devinfo.bus) "_"]); if isempty(this.pins) && this.devinfo.bus == 0 this.pins = this.parent.get_group("i2c_"); endif if numel(this.pins) != 2 error("expected 2 I2C pins but only have %d", numel(this.pins) ) endif # check a device is attached if p.Results.NoProbe == false && !checkI2CAddress(this.parent, this.devinfo.address, this.devinfo.bus) error ("I2c address did not respond to probe of address"); endif # set pins try for i=1:2 configurePin(this.parent, this.pins{i}.name, "i2c") endfor bitrate = uint16(this.devinfo.bitrate/1000); bitrate = [ bitand(bitshift(bitrate,-8), 255), bitand(bitrate, 255)]; # 0 = master mode, which all we currently support in our arduino toolkit [tmp, sz] = sendCommand(this.parent, "i2c", ARDUINO_I2C_CONFIG, [this.devinfo.bus 1 0 bitrate]); catch for i=1:2 configurePinResource(this.parent, this.pins{i}.name, this.pins{i}.owner, this.pins{i}.mode, true) configurePin(this.parent, this.pins{i}.name, this.pins{i}.mode) endfor rethrow (lasterror) end_try_catch # this.cleanup = onCleanup (@() cleanupI2Cdevice (this.parent, this.resourceowner, this.pins)); elseif p.Results.I2CAddress == -1 && !isempty(p.Results.SPIChipSelectPin) && isempty(p.Results.Serial) this.interface = "SPI"; bitorder_type = @(x) (ischar(x) && any(strcmp(lower(x), {"msbfirst", "lsbfirst"}))); mode_type = @(x) (isnumeric(x) && x >= 0 && x <= 3); cspin = p.Results.SPIChipSelectPin; p = inputParser(); p.FunctionName = 'device'; p.CaseSensitive = false; p.addRequired('ar', @isarduino); if has_add_param p.addParameter('SPIChipSelectPin', "", pin_type); p.addParameter('SPIMode', 0, mode_type); p.addParameter('BitRate', 4000000, @isnumeric); p.addParameter('BitOrder', "msbfirst", bitorder_type); else p.addParamValue('SPIChipSelectPin', cspin, pin_type); p.addParamValue('SPIMode', 0, mode_type); p.addParamValue('BitRate', 4000000, @isnumeric); p.addParamValue('BitOrder', "msbfirst", bitorder_type); endif p.parse(varargin{:}); this.devinfo.chipselectpin = p.Results.SPIChipSelectPin; this.devinfo.mode = p.Results.SPIMode; this.devinfo.bitrate = p.Results.BitRate; this.devinfo.bitorder = tolower(p.Results.BitOrder); this.resourceowner = "spi"; isfirst = getResourceCount(this.parent,"spi") == 0; # check if is valid CS pin that can use as output validatePin(this.parent, this.devinfo.chipselectpin, 'digital') if strcmp(getResourceOwner(this.parent, this.devinfo.chipselectpin), this.resourceowner) error ("pin %s is already in use by SPI", this.devinfo.chipselectpin) endif if isfirst terms = getSPITerminals(this.parent); tmp_pins = this.parent.get_pingroup(terms{1}, "SPI"); if numel(tmp_pins) != 4 error ("expected 4 SPI pins but only have %d", numel(tmp_pins)) endif setSharedResourceProperty(this.parent, this.resourceowner, "pins", tmp_pins); endif tmp_pins = getSharedResourceProperty(this.parent, this.resourceowner, "pins"); cs_is_ss = false; cspin = getPinInfo(this.parent, this.devinfo.chipselectpin); cspin.func = "cs"; for i=1:4 # verify cs pin is either SS pin, or a not a spi pin if strcmp(tolower(tmp_pins{i}.func), "ss") if strcmpi(tmp_pins{i}.name, cspin.name) cs_is_ss = true; endif else # check not trying to set CS to a spi pin if strcmpi(tmp_pins{i}.name, cspin.name) error ("can not set cspin to a SPI function pin"); endif endif endfor if !cs_is_ss tmp_pins{end+1} = cspin; endif this.pins = tmp_pins; this.id = cspin.terminal; try for i=1:numel(tmp_pins) if isfirst if strcmp(tolower(tmp_pins{i}.func), "ss") || strcmp(tolower(tmp_pins{i}.func), "cs") configurePin(this.parent, tmp_pins{i}.name, "digitaloutput") configurePinResource (this.parent, tmp_pins{i}.name, "spi", "digitaloutput", true); else configurePin(this.parent, tmp_pins{i}.name, "spi") endif else # only allocate cs pin if not first device if strcmp(tolower(tmp_pins{i}.func), "cs") configurePin(this.parent, tmp_pins{i}.name, "digitaloutput") configurePinResource (this.parent, tmp_pins{i}.name, "spi", "digitaloutput", true); endif endif endfor bitorder = 0; if strcmp(this.devinfo.bitorder, 'lsbfirst') bitorder = 1; endif [tmp, sz] = sendCommand(this.parent, this.resourceowner, ARDUINO_SPI_CONFIG, [this.id 1 this.devinfo.mode bitorder]); incrementResourceCount(this.parent, this.resourceowner); catch for i=1:numel(tmp_pins) if strcmp(tolower(tmp_pins{i}.func), "cs") || isfirst configurePinResource(this.parent, tmp_pins{i}.name, tmp_pins{i}.owner, tmp_pins{i}.mode, true) configurePin(this.parent, tmp_pins{i}.name, tmp_pins{i}.mode) endif endfor rethrow (lasterror); end_try_catch # set clean up function # this.cleanup = onCleanup (@() cleanupSPIdevice (this.parent, this.resourceowner, cspin)); elseif p.Results.I2CAddress == -1 && isempty(p.Results.SPIChipSelectPin) && !isempty(p.Results.Serial) this.interface = "Serial"; this.resourceowner = "serial"; parity_type = @(x) (ischar(x) && any(strcmp(lower(x), {"none", "odd", "even"}))); databits_type = @(x) (isnumeric(x) && x >= 5 && x <= 8); stopbits_type = @(x) (isnumeric(x) && x >= 1 && x <= 2); baudrate_type = @(x) (isnumeric(x) && x >= 300 && x <= 115200); p = inputParser(); p.FunctionName = 'device'; p.CaseSensitive = false; p.addRequired('ar', @isarduino); if has_add_param p.addParameter('Serial', -1, @isnumeric); p.addParameter('BaudRate', 9600, baudrate_type); p.addParameter('DataBits', 8, databits_type); p.addParameter('StopBits', 1, stopbits_type); p.addParameter('Parity', "none", parity_type); else p.addParamValue('Serial', -1, @isnumeric); p.addParamValue('BaudRate', 9600, baudrate_type); p.addParamValue('DataBits', 8, databits_type); p.addParamValue('StopBits', 1, stopbits_type); p.addParamValue('Parity', "none", parity_type); endif p.parse(varargin{:}); this.devinfo.id = p.Results.Serial; this.devinfo.baudrate = p.Results.BaudRate; this.devinfo.databits = p.Results.DataBits; this.devinfo.stopbits = p.Results.StopBits; this.devinfo.parity = p.Results.Parity; this.devinfo.timeout = 1.0; this.id = p.Results.Serial; name = ["uart" num2str(this.id) "_"]; this.pins = this.parent.get_group(name); if numel(this.pins) == 0 error("Not a known serial number '%d'", this.id) endif if numel(this.pins) != 2 error("expected 2 Serial pins but only have %d", numel(this.pins) ) endif # set pins try for i=1:2 configurePin(this.parent, this.pins{i}.name, "reserved") endfor baudrate = uint32(this.devinfo.baudrate); baudin = [ bitand(bitshift(baudrate,-24), 255) bitand(bitshift(baudrate,-16), 255), bitand(bitshift(baudrate,-8), 255), bitand(baudrate, 255)]; parity = 0; if strcmpi(this.devinfo.parity, "odd") parity = 1; elseif strcmpi(this.devinfo.parity, "even") parity = 2; endif [tmp, sz] = sendCommand(this.parent, "serial", ARDUINO_SERIAL_CONFIG, [this.id 1 baudin this.devinfo.databits this.devinfo.stopbits parity]); catch for i=1:2 configurePinResource(this.parent, this.pins{i}.name, this.pins{i}.owner, this.pins{i}.mode, true) configurePin(this.parent, this.pins{i}.name, this.pins{i}.mode) endfor rethrow (lasterror) end_try_catch # set clean up function # this.cleanup = onCleanup (@() cleanupSerialdevice (this.parent, this.resourceowner, {})); else error ('device expected I2CAddress, SPIChipSelectPin or Serial property'); endif endfunction endmethods endclassdef %!shared arduinos %! arduinos = scanForArduinos(1); %!assert(numel(arduinos), 1); %!test %! ar = arduino(); %! assert(!isempty(ar)); %! pins = getI2CTerminals(ar); %! # check pins not allocated %! for i=1:numel(pins) %! p = pins{i}; %! assert(configurePin(ar, p), "unset") %! endfor %! i2c = device(ar, 'i2caddress', 10, "noprobe", 1); %! assert(!isempty(i2c)); %! assert(i2c.interface, "I2C"); %! assert(i2c.i2caddress, 10); %! # check pins allocated %! for i=1:numel(pins) %! p = pins{i}; %! assert(!strcmpi(configurePin(ar, p), "unset")) %! endfor %! delete(i2c); %! # TODO check pins unallocated when we have implemented a free of shared spi bus %! # for i=1:numel(pins) %! # p = pins{i}; %! # assert(configurePin(ar, p), "unset") %! # endfor %! delete(ar) %!test %! ar = arduino(); %! assert(!isempty(ar)); %! %! spipins = getSPITerminals(ar); %! assert (numel(spipins), 4); %! %! # validate SPI pins not allocated %! assert(configurePin(ar, "d10"), "unset") %! assert(configurePin(ar, spipins{1}), "unset") %! assert(configurePin(ar, spipins{2}), "unset") %! assert(configurePin(ar, spipins{3}), "unset") %! assert(configurePin(ar, spipins{4}), "unset") %! %! spi = device(ar, "spichipselectpin", "d10"); %! assert(!isempty(spi)); %! assert(spi.spichipselectpin, "d10"); %! assert(spi.interface, "SPI"); %! %! # validate SPI pins allocated %! assert(configurePin(ar, "d10"), "digitaloutput") %! #assert(configurePin(ar, spipins{1}), 'digitaloutput') ## ss %! #assert(configurePin(ar, spipins{2}), 'digitaloutput') ## mosi %! #assert(configurePin(ar, spipins{3}), 'digitalinput') ## miso %! #assert(configurePin(ar, spipins{4}), 'digitaloutput') ## sck %! %! delete(spi); %! %! # check now pins unset %! assert(configurePin(ar, "d10"), "unset") %! assert(configurePin(ar, spipins{1}), "unset") %! assert(configurePin(ar, spipins{2}), "unset") %! assert(configurePin(ar, spipins{3}), "unset") %! assert(configurePin(ar, spipins{4}), "unset") %! delete(ar) %!test %! ar = arduino(); %! spi = device(ar, "spichipselectpin", "d10"); %! fail ('device(ar, "spichipselectpin", "d10");', 'pin d10 is already in use') %! spi2 = device(ar, "spichipselectpin", "d5"); %! delete(spi); %! delete(spi2); %! delete(ar) arduino-0.12.1/inst/@device/disp.m0000644000000000000000000000403114545566645013635 0ustar00## Copyright (C) 2019 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} disp (@var{dev}) ## Display device object. ## ## @subsubheading Inputs ## @var{dev} - device object to display ## ## @seealso{device} ## @end deftypefn function disp (this) printf (" device object with fields of: \n\n"); printf (" interface = %s\n", this.interface); if strcmp(this.interface, "SPI") printf ("spichipselectpin = %s\n", this.devinfo.chipselectpin); for i=1:numel(this.pins) if ! any(strcmp(this.pins{i}.func,{"ss", "cs"})) printf("%16s = %s\n", [ this.pins{i}.func "pin"], this.pins{i}.name) endif endfor printf (" spimode = %d\n", this.devinfo.mode); printf (" bitorder = %s\n", this.devinfo.bitorder); printf (" bitrate = %d\n", this.devinfo.bitrate); elseif strcmp(this.interface, "Serial") printf (" serialport = %d\n", this.devinfo.id); printf (" baudrate = %d\n", this.devinfo.baudrate); for i=1:2 printf("%16s = %s\n", [ this.pins{i}.func "pin"], this.pins{i}.name) endfor elseif strcmp(this.interface, "I2C") printf (" i2caddress = %d (0x%02X)\n", this.devinfo.address, this.devinfo.address); printf (" bus = %d\n", this.devinfo.bus); printf (" bitrate = %d\n", this.devinfo.bitrate); for i=1:2 printf("%16s = %s\n", [ this.pins{i}.func "pin"], this.pins{i}.name) endfor % Mode, Bitrate, Bitorder else % should never happen endif printf("\n"); endfunction arduino-0.12.1/inst/@device/flush.m0000644000000000000000000000332014545566645014017 0ustar00## Copyright (C) 2019 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{data} =} flush (@var{dev}) ## @deftypefnx {} {@var{data} =} flush (@var{dev}, "input") ## @deftypefnx {} {@var{data} =} flush (@var{dev}, "output") ## Flush the serial port buffers ## ## @subsubheading Inputs ## @var{dev} - connected serial device opened using device ## ## If an additional parameter is provided of "input" or "output", ## then only the input or output buffer will be flushed ## ## @subsubheading Outputs ## None ## ## @seealso{arduino, device, read} ## @end deftypefn function flush (dev, buffer) if nargin < 2 buffer = "all"; endif if !strcmp(dev.interface, "Serial") error("@device.flush: not a Serial device"); endif if !ischar (buffer) error("@device.flush: expected flushtype to be a string"); endif if strcmp(buffer, "all") || strcmp(buffer, "input") # flush input by reading all pending data sz = 32; while sz >= 32 tmp = read(dev, 32); sz = length(tmp); endwhile elseif strcmp(buffer, "output") # nothing to do as we dont have any pending output buffer else error("@device.flush: invalid flushbyte '%s'", buffer); endif endfunction arduino-0.12.1/inst/@device/private/0000755000000000000000000000000014545566645014174 5ustar00arduino-0.12.1/inst/@device/private/__getBytesAvailable__.m0000644000000000000000000000176014545566645020541 0ustar00## Copyright (C) 2019 John Donoghue ## ## 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. see ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} __getBytesAvailable__ (@var{obj}) ## Private function to get bytes available from serial port ## @end deftypefn function out = __getBytesAvailable__ (obj) persistent ARDUINO_SERIAL_STAT = 4; out = 0; ar = obj.parent; [tmp, sz] = sendCommand (ar, "serial", ARDUINO_SERIAL_STAT, [obj.devinfo.id]); out = uint16(tmp(2)); endfunction arduino-0.12.1/inst/@device/read.m0000644000000000000000000000566514545566645013627 0ustar00## Copyright (C) 2019-2021 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{data} =} read (@var{dev}, @var{numbytes}) ## @deftypefnx {} {@var{data} =} read (@var{dev}, @var{numbytes}, @var{precision}) ## Read a specified number of bytes from a i2c or serial device object ## using optional precision for bytesize. ## ## @subsubheading Inputs ## @var{dev} - connected i2c or serial device opened using device ## ## @var{numbytes} - number of bytes to read. ## ## @var{precision} - Optional precision for the output data read data. ## Currently known precision values are uint8 (default), int8, uint16, int16 ## ## @subsubheading Outputs ## @var{data} - data read from the device ## ## @seealso{arduino, device} ## @end deftypefn function out = read (dev, numbytes, precision) persistent ARDUINO_I2C_READ = 7; persistent ARDUINO_SERIAL_READ = 3; persistent endian; if isempty(endian) [~, ~, endian] = computer (); endif if nargin < 2 || nargin > 3 print_usage (); endif if ~isnumeric (numbytes) error("@i2c.read: expected numbytes to be a number"); endif if !strcmp(dev.interface, "I2C") && !strcmp(dev.interface, "Serial") error("@device.read: not a I2C or Serial device"); endif if nargin == 3 if !ischar (precision) error("@device.read: expected presision to be a string"); endif precision = tolower (precision); if !strcmp (precision, "uint8") && !strcmp (precision, "int8") && !strcmp (precision, "uint16") && !strcmp(precision, "int16") error ("@device.read: expected pression to be (u)int8 or (u)int16 string"); endif else precision = 'uint8'; endif datasize = 1; if (strcmp (precision,'uint16') || strcmp (precision,'int16')) datasize = 2; endif % read request if strcmp(dev.interface, "I2C") [tmp, sz] = sendCommand (dev.parent, "i2c", ARDUINO_I2C_READ, [dev.devinfo.bus dev.devinfo.address numbytes*datasize]); else [tmp, sz] = sendCommand (dev.parent, "serial", ARDUINO_SERIAL_READ, [dev.devinfo.id numbytes*datasize dev.devinfo.timeout*10]); endif # skip address and return the data out = typecast (uint8(tmp(2:end)), precision); if (strcmp (precision,'uint16') || strcmp (precision,'int16')) sz = sz/2; if (endian != getEndian(dev.parent)) out = swapbytes (out); endif else if (strcmp (precision, 'int8')) out = int8(tmp(2:end)) else out = tmp(2:end); endif endif endfunction arduino-0.12.1/inst/@device/readRegister.m0000644000000000000000000000654314545566645015330 0ustar00## Copyright (C) 2019 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{data} =} readRegister (@var{dev}, @var{reg}, @var{numbytes}) ## @deftypefnx {} {@var{data} =} readRegister (@var{dev}, @var{reg}, @var{numbytes}, @var{precision}) ## Read a specified number of bytes from a register of an i2cdev object ## using optional precision for bytesize. ## ## @subsubheading Inputs ## @var{dev} - connected i2c device opened using device ## ## @var{reg} - registry value number ## ## @var{numbytes} - number of bytes to read. ## ## @var{precision} - Optional precision for the output data read data. ## Currently known precision values are uint8 (default), int8, uint16, int16 ## ## @subsubheading Output ## @var{data} - data read from device. ## ## @seealso{arduino, device} ## @end deftypefn function out = readRegister(dev, reg, numbytes, precision) persistent endian; if isempty(endian) [~, ~, endian] = computer (); endif persistent ARDUINO_I2C_READREG = 9; if nargin < 3 || nargin > 4 print_usage (); endif if !strcmp(dev.interface, "I2C") error("@device.readRegister: not a I2C device"); endif if ~isnumeric (reg) error ("@device.readRegister: expected reg to be a number"); endif if ~isnumeric (numbytes) error ("@device.readRegister: expected numbytes to be a number"); endif if nargin == 4 if !ischar (precision) error ("@device.readRegister: expected presision to be a string"); endif precision = tolower (precision); if !strcmp (precision, "uint8") && !strcmp (precision, "int8") && !strcmp (precision, "uint16") && !strcmp(precision, "int16") error ("@device.readRegister: expected pression to be (u)int8 or (u)int16 string"); endif else precision = 'uint8'; endif if (strcmp (precision,'uint16')) reg = uint16(reg); if (endian != getEndian(dev.parent)) reg = swapbytes (reg); endif reg = typecast (reg, 'uint8'); regsz = 2; elseif (strcmp (precision,'int16')) reg = int16(reg); if (endian != getEndian(dev.parent)) reg = swabytes (reg); endif reg = typecast (reg, 'uint8'); regsz = 2; else if (strcmp (precision, 'int8')) reg = typecast (int8(reg), 'uint8'); else reg = typecast (uint8(reg), 'uint8'); endif regsz = 1; endif % read reg [tmp, sz] = sendCommand (dev.parent, "i2c", ARDUINO_I2C_READREG, [dev.devinfo.bus dev.devinfo.address regsz reg numbytes*regsz]); # skip address and and regsz and return the data out = tmp(3:end); % convert the outputs if (strcmp (precision,'uint16') || strcmp (precision,'int16')) sz = sz/2; out = typecast (out, precision); if (endian != getEndian(dev.parent)) out = swapbytes (out); endif else if (strcmp (precision, 'int8')) out = int8(out); else out = uint8(out); endif endif endfunction arduino-0.12.1/inst/@device/subsasgn.m0000644000000000000000000000254314545566645014531 0ustar00## Copyright (C) 2019 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{val} = } subsasgn (@var{dev}, @var{sub}) ## subsasgn for device ## ## @seealso{device} ## @end deftypefn function this = subsasgn (this, s, val) if isempty(s) error ("device.subsasgn missing index"); endif if strcmp(this.interface, "Serial") if s(1).type == "." fld = tolower(s(1).subs); switch (fld) case "timeout" if !isnumeric(val) || val < 0 || val > 8 error ("expected numeric time out between 0 to 8 seconds", fld); endif this.devinfo.timeout = val; otherwise error ("device.subsasgn invalid or readonly property '%s'", fld); endswitch else error("unimplemented device.subsasgn type"); endif else error("unimplemented device.subsasgn device"); endif endfunction arduino-0.12.1/inst/@device/subsref.m0000644000000000000000000000760714545566645014363 0ustar00## Copyright (C) 2019 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{val} = } subsref (@var{dev}, @var{sub}) ## subref for device ## ## @seealso{device} ## @end deftypefn function val = subsref (this, s) if isempty(s) error ("device.subsref missing index"); endif if strcmp(this.interface, "SPI") if s(1).type == "." fld = tolower(s(1).subs); switch (fld) case "pins" val = {}; for i = 1:numel(this.pins) val{end+1} = this.pins{i}.name; endfor case "interface" val = this.interface; case "parent" val = this.parent; case "spimode" val = this.devinfo.mode; case "bitrate" val = this.devinfo.bitrate; case "bitorder" val = this.devinfo.bitorder; case "spichipselectpin" val = this.devinfo.chipselectpin; case "misopin" val = get_func_pin(this.pins, "miso"); case "mosipin" val = get_func_pin(this.pins, "mosi"); case "sckpin" val = get_func_pin(this.pins, "sck"); otherwise error ("device.subsref invalid property '%s'", fld); endswitch else error("unimplemented device.subsref type"); endif elseif strcmp(this.interface, "Serial") if s(1).type == "." fld = tolower(s(1).subs); switch (fld) case "pins" val = {}; for i = 1:numel(this.pins) val{end+1} = this.pins{i}.name; endfor case "interface" val = this.interface; case "parent" val = this.parent; case "baudrate" val = this.devinfo.baudrate; case "databits" val = this.devinfo.databits; case "stopbits" val = this.devinfo.stopbits; case "parity" val = this.devinfo.parity; case "timeout" val = this.devinfo.timeout; case "numbytesavailable" val = __getBytesAvailable__(this); case "serialport" val = this.devinfo.id; otherwise error ("device.subsref invalid property '%s'", fld); endswitch else error("unimplemented device.subsref type"); endif else # I2C if s(1).type == "." fld = tolower(s(1).subs); switch (fld) case "pins" val = {}; for i = 1:numel(this.pins) val{end+1} = this.pins{i}.name; endfor case "interface" val = this.interface; case "parent" val = this.parent; case "bus" val = this.devinfo.bus; case "i2caddress" val = this.devinfo.address; case "bitrate" val = this.devinfo.bitrate; case "sdapin" val = get_func_pin(this.pins, "sda"); case "sclpin" val = get_func_pin(this.pins, "scl"); otherwise error ("device.subsref invalid property '%s'", fld); endswitch else error("unimplemented device.subsref type"); endif endif if (numel (s) > 1) val = subsref (val, s(2:end)); endif endfunction function val = get_func_pin(pins, func) val = []; for i=1:numel(pins) pin = pins{i}; if strcmp(pin.func, func) val = pin.name; endif endfor endfunction %!test %! ar = arduino(); %! spi = device (ar, "spichipselectpin", "d10"); %! assert (spi.spichipselectpin, "d10") %! assert (isarduino(spi.parent)) %! assert (ar.port, spi.parent.port) %! assert (spi.spimode, 0) %! assert (spi.bitorder, "msbfirst") %! assert (spi.interface, "SPI") %! assert (numel(spi.pins) >= 4) %! fail ("spi.invalid") %! delete(spi) arduino-0.12.1/inst/@device/write.m0000644000000000000000000000556314545566645014043 0ustar00## Copyright (C) 2019-2021 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} write (@var{dev}, @var{datain}) ## @deftypefnx {} {} write (@var{dev}, @var{datain}, @var{precision}) ## Write data to a I2C or serial device object ## using optional precision for the data byte used for the data. ## ## @subsubheading Inputs ## @var{dev} - connected i2c or serial device opened using device ## ## @var{datain} - data to write to device. Datasize should not exceed the constraints ## of the data type specified for the precision. ## ## @var{precision} - Optional precision for the input write data. ## Currently known precision values are uint8 (default), int8, uint16, int16 ## ## @seealso{arduino, device, read} ## @end deftypefn function write (dev, datain, precision) persistent endian; if isempty(endian) [~, ~, endian] = computer (); endif persistent ARDUINO_I2C_WRITE = 6; persistent ARDUINO_SERIAL_WRITE = 2; if nargin < 2 || nargin > 3 print_usage (); endif if !strcmp(dev.interface, "I2C") && !strcmp(dev.interface, "Serial") error("@device.write: not a I2C or Serial device"); endif if nargin == 3 if !ischar (precision) error ("@device.write: expected presision to be a atring"); endif precision = tolower (precision); if !strcmp (precision, "uint8") && !strcmp (precision, "int8") && !strcmp (precision, "uint16") && !strcmp(precision, "int16") error ("@device.write: expected pression to be (u)int8 or (u)int16 string"); endif else precision = 'uint8'; endif if (strcmp (precision,'uint16')) datain = uint16(datain); if (endian != getEndian(dev.parent)) datain = swapbytes (datain); endif datain = typecast (datain, 'uint8'); elseif (strcmp (precision,'int16')) datain = int16(datain); if (endian != getEndian(dev.parent)) datain = swapbytes (datain); endif datain = typecast (datain, 'uint8'); else if (strcmp (precision, 'int8')) datain = typecast (int8(datain), 'uint8'); else datain = typecast (uint8(datain), 'uint8'); endif endif % write request if strcmp(dev.interface, "I2C") [tmp, sz] = sendCommand (dev.parent, "i2c", ARDUINO_I2C_WRITE, [dev.devinfo.bus dev.devinfo.address datain]); else [tmp, sz] = sendCommand (dev.parent, "serial", ARDUINO_SERIAL_WRITE, [dev.devinfo.id datain]); endif endfunction arduino-0.12.1/inst/@device/writeRead.m0000644000000000000000000000373414545566645014635 0ustar00## Copyright (C) 2019 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{dataOut} =} readWrite (@var{spi}, @var{dataIn}) ## Write uint8 data to spi device and return ## back clocked out response data of same size. ## ## @subsubheading Inputs ## @var{spi} - connected spi device on arduino ## ## @var{dataIn} - uint8 sized data to send to spi device framed between SS frame. ## ## @subsubheading Outputs ## @var{dataOut} - uint8 data clocked out during send to dataIn. ## ## @seealso{arduino, device} ## @end deftypefn function dataOut = writeRead (this, dataIn) dataOut = []; persistent ARDUINO_SPI_READ_WRITE = 2; if nargin < 2 error ("@device.writeRead: expected dataIn"); endif if !strcmp(this.interface, "SPI") error("@device.writeRead: not a SPI device"); endif [tmp, sz] = sendCommand (this.parent, this.resourceowner, ARDUINO_SPI_READ_WRITE, [this.id uint8(dataIn)]); if sz > 0 dataOut = tmp(2:end); endif endfunction %!shared arduinos %! arduinos = scanForArduinos(1); %!assert(numel(arduinos), 1); %!test %! ar = arduino(); %! assert(!isempty(ar)); %! spi = device(ar, "SPIChipSelectPin", "d10"); %! assert(!isempty(spi)); %! data = writeRead(spi, 1); %! assert(numel(data), 1); %! delete(spi) %! delete(ar) %!test %! ar = arduino(); %! assert(!isempty(ar)); %! spi = device(ar, "SPIChipSelectPin", "d10"); %! assert(!isempty(spi)); %! data = writeRead(spi, [1 1 1]); %! assert(numel(data), 3); %! delete(spi) %! delete(ar) arduino-0.12.1/inst/@device/writeRegister.m0000644000000000000000000000621414545566645015542 0ustar00## Copyright (C) 2019 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} writeRegister (@var{dev}, @var{reg}, @var{datain}) ## @deftypefnx {} {} writeRegister (@var{dev}, @var{dev}, @var{datain}, @var{precision}) ## Write data to i2c device object at a given registry position ## using optional precision for the data byte used for the data. ## ## @subsubheading Inputs ## @var{dev} - connected i2c device opened using device ## ## @var{reg} - registry position to write to. ## ## @var{datain} - data to write to device. Datasize should not exceed the constraints ## of the data type specified for the precision. ## ## @var{precision} - Optional precision for the input write data. ## Currently known precision values are uint8 (default), int8, uint16, int16 ## ## @seealso{arduino, device, read} ## @end deftypefn function writeRegister (dev, reg, datain, precision) persistent endian; if isempty (endian) [~, ~, endian] = computer (); endif persistent ARDUINO_I2C_WRITEREG = 8; if nargin < 3 || nargin > 4 print_usage (); endif if !strcmp(dev.interface, "I2C") error("@device.writeRegister: not a I2C device"); endif if ~isnumeric (reg) error("@device.writeRegister: expected reg to be a number"); endif if nargin == 4 if !ischar (precision) error ("@device.writeRegister: expected precision to be a string"); endif precision = tolower (precision); if !strcmp (precision, "uint8") && !strcmp (precision, "int8") && !strcmp (precision, "uint16") && !strcmp(precision, "int16") error("@device.writeRegister: expected pression to be (u)int8 or (u)int16 string"); endif else precision = 'uint8'; endif % todo convert reg, data in to correct format if (strcmp (precision,'uint16')) reg = uint16 (reg); datain = uint16 (datain); if (endian != getEndian(dev.parent)) reg = swapbytes (reg); datain = swapbytes (datain); endif reg = typecast (reg, 'uint8'); datain = typecast (datain, 'uint8'); elseif (strcmp (precision,'int16')) reg = uint16 (reg); datain = int16 (datain); if (endian != getEndian(dev.parent)) reg = swabytes (reg); datain = swapbytes (datain); endif reg = typecast (reg, 'uint8'); datain = typecast (datain, 'uint8'); else if (strcmp (precision, 'int8')) reg = typecast (int8(reg), 'uint8'); datain = typecast (int8(datain), 'uint8'); else reg = typecast (uint8(reg), 'uint8'); datain = typecast (uint8(datain), 'uint8'); endif endif sendCommand (dev.parent, "i2c", ARDUINO_I2C_WRITEREG, [dev.devinfo.bus dev.devinfo.address reg datain]); endfunction arduino-0.12.1/inst/@i2cdev/0000755000000000000000000000000014545566645012437 5ustar00arduino-0.12.1/inst/@i2cdev/delete.m0000644000000000000000000000147214545566645014063 0ustar00## Copyright (C) 2020 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} delete (@var{dev}) ## Free resources of a i2cdev object. ## ## @subsubheading Inputs ## @var{dev} - object to free ## ## @seealso{i2cdev} ## @end deftypefn function delete(this) # currently does nothing endfunction arduino-0.12.1/inst/@i2cdev/disp.m0000644000000000000000000000222514545566645013555 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} disp (@var{dev}) ## Display i2cdev object. ## ## @subsubheading Inputs ## @var{dev} - i2cdev object ## ## @seealso{i2cdev} ## @end deftypefn function disp (p) printf (" arduino i2cdev object with fields of: \n\n"); printf (" address = %d (0x%02X)\n", p.address, p.address); printf (" bus = %d\n", p.bus); printf (" bitorder = %s\n", p.bitorder); printf (" pins = "); for i=1:2 printf("%s(%s) ", p.pins{i}.name, p.pins{i}.func) endfor printf("\n"); % Mode, Bitrate, Bitorder printf ("\n"); endfunction arduino-0.12.1/inst/@i2cdev/i2cdev.m0000644000000000000000000001277714545566645014007 0ustar00## Copyright (C) 2018-2020 John Donoghue ## ## 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. classdef i2cdev < handle ## -*- texinfo -*- ## @deftypefn {} {@var{dev} =} i2cdev (@var{ar}, @var{address}) ## @deftypefnx {} {@var{dev} =} i2cdev (@var{ar}, @var{address}, @var{propname}, @var{propvalue}) ## ## @code{i2cdev} is depreciated and will be removed in a future version. ## Use @code{device} instead. ## ## Create an i2cdev object to communicate to the i2c port on a connected arduino. ## ## @subsubheading Inputs ## @var{ar} - connected arduino object ## ## @var{address} - address to use for device on I2C bus. ## ## @var{propname}, @var{propvalue} - property name/value pair for values to pass to devices. ## ## Currently known properties: ## @table @asis ## @item bus ## bus number (when arduino board supports multiple I2C buses) ## with value of 0 or 1. ## @end table ## ## @subsubheading Outputs ## @var{dev} - new created i2cdev object. ## ## @subsubheading Properties ## The i2cdev object has the following public properties: ## @table @asis ## @item parent ## The parent (arduino) for this device ## @item pins ## pins used by this object ## @item bus ## bus used for created object ## @item address ## I2C address set for object ## @end table ## ## @seealso{arduino} ## @end deftypefn properties (Access = private) address = 0; arduinoobj = []; bus = 0; bitorder = ""; pins = {}; endproperties methods (Access = public) function p = i2cdev(varargin) ARDUINO_I2C_CONFIG = 1; persistent warned = false; if (! warned) warned = true; warning ("Octave:deprecated-function", "spidev is obsolete and will be removed from a future version of arduino, please use 'device' instead"); endif if nargin < 2 error("expects arduino object and address"); endif ar = varargin{1}; address = varargin{2}; bus = 0; bitorder = 'msbfirst'; if !isnumeric(address) || address < 0 || address > 255 error("expected address between 0 .. 255"); endif if mod(nargin, 2) != 0 error ("i2cdev: expected property name, value pairs"); endif if !iscellstr (varargin(3:2:nargin)) error ("i2cdev: expected property names to be strings"); endif for i = 3:2:nargin propname = tolower(varargin{i}); propvalue = varargin{i+1}; # printf("%s = %s\n", propname, propvalue); if strcmp (propname, "bus") if !isnumeric(propvalue) || propvalue < 0 error("bus should be a positive number") endif bus = propvalue; elseif strcmp (propname, "bitorder") if !ischar(propvalue) error("bitorder should be a 'lsbfirst' or 'msbfirst'"); endif propvalue = tolower(propvalue); if propvalue != 'lsbfirst' && propvalue != 'msbfirst' error("bitorder should be a 'lsbfirst' or 'msbfirst'"); endif bitorder = propvalue; endif endfor if (!isa (ar, "arduino")) error("expects arduino object"); endif p.address = address; p.arduinoobj = ar; p.bus = bus; p.bitorder = bitorder; % TODO on calling setup with the CS pin, returns back the other pins that we then setup as used ? % sendCommand # there only ever one port ??? with CS able to be completely independant ?? p.pins = ar.get_group(["i2c" num2str(bus) "_"]); if isempty(p.pins) && bus == 0 p.pins = ar.get_group("i2c_"); endif if numel(p.pins) != 2 error("expected 2 I2C pins but only have %d", numel(p.pins) ) endif # set pins try for i=1:2 configurePin(ar, p.pins{i}.name, "i2c") endfor # TODO: bitrate, order etc bitorder = 0; [tmp, sz] = sendCommand(p.arduinoobj, "i2c", ARDUINO_I2C_CONFIG, [bus 1]); catch for i=1:2 configurePinResource(ar, p.pins{i}.name, p.pins{i}.owner, p.pins{i}.mode, true) configurePin(ar, p.pins{i}.name, p.pins{i}.mode) endfor rethrow (lasterror) end_try_catch endfunction endmethods endclassdef %!shared arduinos %! arduinos = scanForArduinos(1); %!assert(numel(arduinos), 1); %!test %! ar = arduino(); %! assert(!isempty(ar)); %! pins = getI2CTerminals(ar); %! # TODO check pins unallocated when we have implemented a free of shared spi bus %! # check pins not allocated %! #for i=1:numel(pins) %! # p = pins{i}; %! # assert(configurePin(ar, p), "unset") %! #endfor %! i2c = i2cdev(ar, 10); %! assert(!isempty(i2c)); %! assert(i2c.address, 10); %! assert(i2c.bitorder, 'msbfirst'); %! # check pins allocated %! for i=1:numel(pins) %! p = pins{i}; %! assert(strcmpi(configurePin(ar, p), "i2c")) %! endfor %! delete(i2c) %! # TODO check pins unallocated when we have implemented a free of shared spi bus %! #for i=1:numel(pins) %! # p = pins{i}; %! # assert(configurePin(ar, p), "unset") %! #endfor arduino-0.12.1/inst/@i2cdev/read.m0000644000000000000000000000515114545566645013532 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{data} =} read (@var{dev}, @var{numbytes}) ## @deftypefnx {} {@var{data} =} read (@var{dev}, @var{numbytes}, @var{precision}) ## Read a specified number of bytes from a i2cdev object ## using optional precision for bytesize. ## ## @subsubheading Inputs ## @var{dev} - connected i2c device opened using i2cdev ## ## @var{numbytes} - number of bytes to read. ## ## @var{precision} - Optional precision for the output data read data. ## Currently known precision values are uint8 (default), int8, uint16, int16 ## ## @subsubheading Outputs ## @var{data} - data read from i2cdevice ## ## @seealso{arduino, i2cdev} ## @end deftypefn function out = read (dev, numbytes, precision) persistent ARDUINO_I2C_READ = 7; persistent endian; if isempty(endian) [~, ~, endian] = computer (); endif if nargin < 2 || nargin > 3 print_usage (); endif if ~isnumeric (numbytes) error("@i2c.read: expected numbytes to be a number"); endif if nargin == 3 if !ischar (precision) error("@i2c.read: expected presision to be a string"); endif precision = tolower (precision); if !strcmp (precision, "uint8") && !strcmp (precision, "int8") && !strcmp (precision, "uint16") && !strcmp(precision, "int16") error ("@i2c.read: expected pression to be (u)int8 or (u)int16 string"); endif else precision = 'uint8'; endif datasize = 1; if (strcmp (precision,'uint16') || strcmp (precision,'int16')) datasize = 2; endif % read request [tmp, sz] = sendCommand (dev.arduinoobj, "i2c", ARDUINO_I2C_READ, [dev.bus dev.address numbytes*datasize]); # skip address and return the data out = typecast (uint8(tmp(2:end)), precision); if (strcmp (precision,'uint16') || strcmp (precision,'int16')) sz = sz/2; if (endian == 'L' && strcmp (dev.bitorder,'msbfirst')) || (endian == 'B' && strcmp (dev.bitorder, 'lsbfirst')) out = swapbytes (out); endif else if (strcmp (precision, 'int8')) out = int8(tmp(2:end)) else out = tmp(2:end); endif endif endfunction arduino-0.12.1/inst/@i2cdev/readRegister.m0000644000000000000000000000671014545566645015241 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{data} =} readRegister (@var{dev}, @var{reg}, @var{numbytes}) ## @deftypefnx {} {@var{data} =} readRegister (@var{dev}, @var{reg}, @var{numbytes}, @var{precision}) ## Read a specified number of bytes from a register of an i2cdev object ## using optional precision for bytesize. ## ## @subsubheading Inputs ## @var{dev} - connected i2c device opened using i2cdev ## ## @var{reg} - registry value number ## ## @var{numbytes} - number of bytes to read. ## ## @var{precision} - Optional precision for the output data read data. ## Currently known precision values are uint8 (default), int8, uint16, int16 ## ## @subsubheading Output ## @var{data} - data read from device. ## ## @seealso{arduino, i2cdev} ## @end deftypefn function out = readRegister(dev, reg, numbytes, precision) persistent endian; if isempty(endian) [~, ~, endian] = computer (); endif persistent ARDUINO_I2C_READREG = 9; if nargin < 3 || nargin > 4 print_usage (); endif if ~isnumeric (reg) error ("@i2c.readRegister: expected reg to be a number"); endif if ~isnumeric (numbytes) error ("@i2c.readRegister: expected numbytes to be a number"); endif if nargin == 4 if !ischar (precision) error ("@i2c.readRegister: expected presision to be a string"); endif precision = tolower (precision); if !strcmp (precision, "uint8") && !strcmp (precision, "int8") && !strcmp (precision, "uint16") && !strcmp(precision, "int16") error ("@i2c.readRegister: expected pression to be (u)int8 or (u)int16 string"); endif else precision = 'uint8'; endif if (strcmp (precision,'uint16')) reg = uint16(reg); if (endian == 'L' && strcmp (dev.bitorder,'msbfirst')) || (endian == 'B' && strcmp (dev.bitorder, 'lsbfirst')) reg = swapbytes (reg); endif reg = typecast (reg, 'uint8'); regsz = 2; elseif (strcmp (precision,'int16')) reg = int16(reg); if (endian == 'L' && strcmp (dev.bitorder,'msbfirst')) || (endian == 'B' && strcmp (dev.bitorder, 'lsbfirst')) reg = swabytes (reg); endif reg = typecast (reg, 'uint8'); regsz = 2; else if (strcmp (precision, 'int8')) reg = typecast (int8(reg), 'uint8'); else reg = typecast (uint8(reg), 'uint8'); endif regsz = 1; endif % read reg [tmp, sz] = sendCommand (dev.arduinoobj, "i2c", ARDUINO_I2C_READREG, [dev.bus dev.address regsz reg numbytes*regsz]); # skip address and and regsz and return the data out = tmp(3:end); % convert the outputs if (strcmp (precision,'uint16') || strcmp (precision,'int16')) sz = sz/2; out = typecast (out, precision); if (endian == 'L' && strcmp (dev.bitorder,'msbfirst')) || (endian == 'B' && strcmp (dev.bitorder, 'lsbfirst')) out = swapbytes (out); endif else if (strcmp (precision, 'int8')) out = int8(out); else out = uint8(out); endif endif endfunction arduino-0.12.1/inst/@i2cdev/subsref.m0000644000000000000000000000267114545566645014274 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{val} = } subsref (@var{dev}, @var{sub}) ## subref for i2cdev ## ## @seealso{i2cdev} ## @end deftypefn function val = subsref (p, s) if isempty(s) error ("i2cdev.subsref missing index"); endif if s(1).type == "." fld = tolower(s(1).subs); switch (fld) case "pins" val = {}; for i = 1:numel(p.pins) val{end+1} = p.pins{i}.name; endfor case "parent" val = p.arduinoobj; case "bus" val = p.bus; case "address" val = p.address; case "bitorder" val = p.bitorder; otherwise error ("i2cdev.subsref invalid property '%s'", fld); endswitch else error("unimplemented i2cdev.subsref type"); endif endfunction %!test %! ar = arduino(); %! i2c = i2cdev (ar, 0x22); %! assert (isarduino(i2c.parent)) %! assert (i2c.address, 0x22) %! assert (numel(i2c.pins) == 2) %! fail ("i2c.invalid") arduino-0.12.1/inst/@i2cdev/write.m0000644000000000000000000000522414545566645013752 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} write (@var{dev}, @var{datain}) ## @deftypefnx {} {} write (@var{dev}, @var{datain}, @var{precision}) ## Write data to a i2cdev object ## using optional precision for the data byte used for the data. ## ## @subsubheading Inputs ## @var{dev} - connected i2c device opened using i2cdev ## ## @var{datain} - data to write to device. Datasize should not exceed the constraints ## of the data type specified for the precision. ## ## @var{precision} - Optional precision for the input write data. ## Currently known precision values are uint8 (default), int8, uint16, int16 ## ## @seealso{arduino, i2cdev, read} ## @end deftypefn function write (dev, datain, precision) persistent endian; if isempty(endian) [~, ~, endian] = computer (); endif persistent ARDUINO_I2C_WRITE = 6; if nargin < 2 || nargin > 3 print_usage (); endif if nargin == 3 if !ischar (precision) error ("@i2c.write: expected presision to be a atring"); endif precision = tolower (precision); if !strcmp (precision, "uint8") && !strcmp (precision, "int8") && !strcmp (precision, "uint16") && !strcmp(precision, "int16") error ("@i2c.write: expected pression to be (u)int8 or (u)int16 string"); endif else precision = 'uint8'; endif if (strcmp (precision,'uint16')) datain = uint16(datain); if (endian == 'L' && strcmp (dev.bitorder,'msbfirst')) || (endian == 'B' && strcmp (dev.bitorder, 'lsbfirst')) datain = swapbytes (datain); endif datain = typecast (datain, 'uint8'); elseif (strcmp (precision,'int16')) datain = int16(datain); if (endian == 'L' && strcmp (dev.bitorder,'msbfirst')) || (endian == 'B' && strcmp (dev.bitorder, 'lsbfirst')) datain = swapbytes (datain); endif datain = typecast (datain, 'uint8'); else if (strcmp (precision, 'int8')) datain = typecast (int8(datain), 'uint8'); else datain = typecast (uint8(datain), 'uint8'); endif endif % write request [tmp, sz] = sendCommand (dev.arduinoobj, "i2c", ARDUINO_I2C_WRITE, [dev.bus dev.address datain]); endfunction arduino-0.12.1/inst/@i2cdev/writeRegister.m0000644000000000000000000000624414545566645015462 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} writeRegister (@var{dev}, @var{reg}, @var{datain}) ## @deftypefnx {} {} writeRegister (@var{dev}, @var{dev}, @var{datain}, @var{precision}) ## Write data to i2cdev object at a given registry position ## using optional precision for the data byte used for the data. ## ## @subsubheading Inputs ## @var{dev} - connected i2c device opened using i2cdev ## ## @var{reg} - registry position to write to. ## ## @var{datain} - data to write to device. Datasize should not exceed the constraints ## of the data type specified for the precision. ## ## @var{precision} - Optional precision for the input write data. ## Currently known precision values are uint8 (default), int8, uint16, int16 ## ## @seealso{arduino, i2cdev, read} ## @end deftypefn function writeRegister (dev, reg, datain, precision) persistent endian; if isempty (endian) [~, ~, endian] = computer (); endif persistent ARDUINO_I2C_WRITEREG = 8; if nargin < 3 || nargin > 4 print_usage (); endif if ~isnumeric (reg) error("@i2c.writeRegister: expected reg to be a number"); endif if nargin == 4 if !ischar (precision) error ("@i2c.writeRegister: expected precision to be a string"); endif precision = tolower (precision); if !strcmp (precision, "uint8") && !strcmp (precision, "int8") && !strcmp (precision, "uint16") && !strcmp(precision, "int16") error("@i2c.writeRegister: expected pression to be (u)int8 or (u)int16 string"); endif else precision = 'uint8'; endif % todo convert reg, data in to correct format if (strcmp (precision,'uint16')) reg = uint16 (reg); datain = uint16 (datain); if (endian == 'L' && strcmp (dev.bitorder,'msbfirst')) || (endian == 'B' && strcmp (dev.bitorder, 'lsbfirst')) reg = swapbytes (reg); datain = swapbytes (datain); endif reg = typecast (reg, 'uint8'); datain = typecast (datain, 'uint8'); elseif (strcmp (precision,'int16')) reg = uint16 (reg); datain = int16 (datain); if (endian == 'L' && strcmp (dev.bitorder,'msbfirst')) || (endian == 'B' && strcmp(dev.bitorder, 'lsbfirst')) reg = swabytes (reg); datain = swapbytes (datain); endif reg = typecast (reg, 'uint8'); datain = typecast (datain, 'uint8'); else if (strcmp (precision, 'int8')) reg = typecast (int8(reg), 'uint8'); datain = typecast (int8(datain), 'uint8'); else reg = typecast (uint8(reg), 'uint8'); datain = typecast (uint8(datain), 'uint8'); endif endif sendCommand (dev.arduinoobj, "i2c", ARDUINO_I2C_WRITEREG, [dev.bus dev.address reg datain]); endfunction arduino-0.12.1/inst/@rotaryEncoder/0000755000000000000000000000000014545566645014103 5ustar00arduino-0.12.1/inst/@rotaryEncoder/delete.m0000644000000000000000000000226414545566645015527 0ustar00## Copyright (C) 2020 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} delete (@var{dev}) ## Free resources of a encoder object. ## ## @subsubheading Inputs ## @var{dev} - object to free ## ## @seealso{rotartEncoder} ## @end deftypefn function delete(this) try ar = this.parent; name = this.resourceowner; pins = this.pins;; if !isempty(ar) decrementResourceCount(ar, name); for i=1:numel(pins) pin = pins{i}; configurePinResource(ar, pin.name, pin.owner, pin.mode, true) configurePin(ar, pin.name, pin.mode) endfor this.parent = []; endif catch # do nothing end_try_catch endfunction arduino-0.12.1/inst/@rotaryEncoder/disp.m0000644000000000000000000000212714545566645015222 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} disp (@var{obj}) ## Display the rotary encoder object in a verbose way, ## ## @subsubheading Inputs ## @var{obj} - the arduino rotary encoder object created with rotaryEncoder ## ## @seealso{rotaryEncoder} ## @end deftypefn function retval = disp (obj) printf (" arduino rotary object with fields of: \n"); printf (" pulsesperrevolution = ") disp(obj.ppr); for i=1:numel(obj.pins) pin = obj.pins{i}; printf (" %s = %s\n", pin.func, pin.name) endfor endfunction arduino-0.12.1/inst/@rotaryEncoder/readCount.m0000644000000000000000000000501314545566645016204 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {[@var{count}, @var{time}] =} readCount (@var{obj}) ## @deftypefnx {} {[@var{count}, @var{time}] =} readCount (@var{obj}, @var{name}, @var{value}) ## read count value from the rotary encoder. ## ## subsubheading Inputs ## @var{obj} - rotary encoder object created with rotaryEncoder call. ## ## @var{name}, @var{value} - optional name,value pairs ## ## Valid option name pairs currently are: ## @table @asis ## @item reset ## Reset the count after reading (if true) ## @end table ## ## @subsubheading Outputs ## @var{count} - returned count read from the encoder. ## ## @var{time} - seconds since arduino started ## ## @seealso{rotaryEncoder, resetCount} ## @end deftypefn function [value, time] = readCount(obj, reset, resetvalue) persistent ARDUINO_ROTARYENCODER_READCOUNT = 2; if nargin != 1 && nargin != 3 error ("arduino: expected rotaryencoder object and optional property name, value pairs"); endif if nargin != 3 reset = "reset"; resetvalue = false; endif if !strcmpi (reset, "reset") error ("arduino: expected property name of 'reset'"); endif if !(isnumeric(resetvalue) || islogical(resetvalue)) || (resetvalue != 0 && resetvalue != 1) error ("arduino: expected resetvalue of 0 or 1"); endif # attempt to clock out precision bits [tmp, sz] = sendCommand(obj.parent, "rotaryencoder", ARDUINO_ROTARYENCODER_READCOUNT, [obj.id resetvalue]); value = typecast(uint16(tmp(2))*256 + uint16(tmp(3)), 'int16'); time = uint32(tmp(4))*(256*256*256) + uint32(tmp(5))*(256*256) + uint32(tmp(6))*256 + uint32(tmp(7)); time = double(time)/1000.0; endfunction %!test %! ar = arduino (); %! e = rotaryEncoder(ar, "d2","d3"); %! readCount(e); %! readCount(e, "reset", 0); %! readCount(e, "reset", 1); %! readCount(e, "reset", true); %! delete(e) %!error readCount(); arduino-0.12.1/inst/@rotaryEncoder/readSpeed.m0000644000000000000000000000315514545566645016161 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{speed} =} readSpeed (@var{obj}) ## read rotational speed from the rotary encoder. ## ## @subsubheading Inputs ## @var{obj} - rotary encoder object created with rotaryEncoder call. ## ## @subsubheading Outputs ## @var{speed} - returned speed in revolutions per minute read from the encoder. ## ## @seealso{rotaryEncoder, resetCount} ## @end deftypefn function value = readSpeed(obj, varargin) persistent ARDUINO_ROTARYENCODER_READSPEED = 3; # attempt to clock out precision bits [tmp, sz] = sendCommand(obj.parent, "rotaryencoder", ARDUINO_ROTARYENCODER_READSPEED, [obj.id]); value = typecast(uint16(tmp(2))*256 + uint16(tmp(3)), 'int16'); value = (double(value)/1000.0)*60; # cnts per min if obj.ppr > 0 value = value / obj.ppr; else value = 0; endif endfunction %!test %! ar = arduino (); %! e = rotaryEncoder(ar, "d2","d3"); %! readSpeed(e); %! delete(e) arduino-0.12.1/inst/@rotaryEncoder/resetCount.m0000644000000000000000000000305214545566645016414 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} reset (@var{obj}) ## @deftypefnx {} reset (@var{obj}, @var{cnt}) ## reset the rotary encoder count values ## ## @subsubheading Inputs ## @var{obj} - the rotaryEncoder object ## ## @var{cnt} - optional count value to reset to ## ## @seealso{rotaryEncoder, readCount} ## @end deftypefn function resetCount(obj, cnt) persistent ARDUINO_ROTARYENCODER_RESETCOUNT = 0; if nargin < 2 cnt = 0; endif if cnt < -32000 || cnt > 32000 error ("@rotaryEncoder.resetCount: reset count out of supported range"); endif cnt = uint16(cnt); [tmp, sz] = sendCommand(obj.parent, "rotaryencoder", ARDUINO_ROTARYENCODER_RESETCOUNT, [obj.id bitand(bitshift(cnt, -8),255) bitand(cnt,255)]); endfunction %!test %! ar = arduino (); %! e = rotaryEncoder(ar, "d2","d3"); %! resetCount(e); %! resetCount(e, 10); %! delete(e); arduino-0.12.1/inst/@rotaryEncoder/rotaryEncoder.m0000644000000000000000000001114214545566645017100 0ustar00## Copyright (C) 2018-2020 John Donoghue ## ## 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 ## . classdef rotaryEncoder < handle ## -*- texinfo -*- ## @deftypefn {} {@var{obj} =} rotaryEncoder (@var{ar}, @var{chanApin}, @var{chanBpin}) ## @deftypefnx {} {@var{obj} =} rotaryEncoder (@var{ar}, @var{chanApin}, @var{chanBpin}, @var{ppr}) ## Create a rotaryEncoder object controlled by the input pins. ## ## @subsubheading Inputs ## @var{ar} - connected arduino object. ## ## @var{chanApin} - pin used for channel A ## ## @var{chanBpin} - pin used for channel B ## ## @var{ppr} - count of encoder pulsed required for a full revolution of the encoder. ## ## @subsubheading Outputs ## @var{obj} - created rotary encoder object ## ## @subsubheading Example ## @example ## a = arduino (); ## enc = rotaryEncoder(a, "d2", "d3", 180); ## @end example ## ## @subsubheading Properties ## The rotaryEncoder object has the following public properties: ## @table @asis ## @item parent ## The parent (arduino) for this device ## @item pins ## pins used by this object ## @item ppr ## Number of pulses used per rotation ## @end table ## ## @seealso{arduino} ## @end deftypefn properties (Access = private) parent = []; id = 0; pins = {}; ppr = []; resourceowner = []; endproperties methods (Access = public) function p = rotaryEncoder(ar, pinA, pinB, ppr) persistent ARDUINO_ROTARYENCODER_CONFIG = 1; if (nargin == 1 && isa (ar, "rotaryEncoder")) register = ar; # Copy constructor elseif nargin < 3 error ('rotaryEncoder: Expected pinA and pinB'); else p.parent = ar; pins = {}; pins{end+1} = ar.get_pin(pinA); pins{end}.func = "channela"; # pin used also to address this obj p.id = pins{1}.id; pins{end+1} = ar.get_pin(pinB); pins{end}.func = "channelb"; if nargin < 4 ppr = []; endif if isempty(ppr) ppr = 0; endif if ! isnumeric(ppr) || ppr < 0 error('rotaryEncoder: ppr should be a positive number') endif # verify pins support digital i/o for i = 1:numel(pins) pin = pins{i}.name; validatePin(ar, pin, "digital"); endfor p.pins = pins; p.ppr = ppr; name = sprintf("encoder-%d", p.id); p.resourceowner = name; count = getResourceCount(ar,name); if count > 0 error ("@rotaryEncoder.rotaryEncoder: already in use"); endif try for i=1:numel(pins) pin = pins{i}.name; configurePin(ar, pin, "pullup"); endfor [tmp, sz] = sendCommand(ar, "rotaryencoder", ARDUINO_ROTARYENCODER_CONFIG, [p.id 1 pins{2}.id]); incrementResourceCount(ar, name); catch # on error, restore pin state for i=1:numel(pins) pin = pins{i}; configurePinResource(ar, pin.name, pin.owner, pin.mode, true) configurePin(ar, pin.name, pin.mode) endfor rethrow (lasterror); end_try_catch # set clean up function # p.cleanup = onCleanup (@() cleanupEncoder (ar, name, pins)); endif endfunction endmethods endclassdef %!shared ar %! ar = arduino(); %!test %! assert (configurePin(ar, "d2"), "unset") %! assert (configurePin(ar, "d3"), "unset") %! enc = rotaryEncoder(ar, "d2", "d3"); %! assert (isa (enc, "rotaryEncoder")) %! assert (!strcmpi(configurePin(ar, "d2"), "unset")) %! assert (!strcmpi(configurePin(ar, "d3"), "unset")) %! delete (enc) %! assert (configurePin(ar, "d2"), "unset") %! assert (configurePin(ar, "d3"), "unset") %!test %! enc = rotaryEncoder(ar, "d2", "d3", 100); %! assert (isa (enc, "rotaryEncoder")) %! delete (enc) %!test %! enc = rotaryEncoder(ar, "d2", "d3"); %! fail ('rotaryEncoder(ar, "d2", "d3");', "already in use"); %! delete (enc) %!error rotaryEncoder(ar); %!error rotaryEncoder(ar, "d2"); arduino-0.12.1/inst/@rotaryEncoder/subsref.m0000644000000000000000000000277414545566645015744 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{val} = } subsref (@var{dev}, @var{sub}) ## subref for rotaryEncoder ## ## @seealso{rotaryEncoder} ## @end deftypefn function val = subsref (p, s) if isempty(s) error ("rotaryEncoder.subsref missing index"); endif if s(1).type == "." fld = tolower(s(1).subs); switch (fld) case "pins" val = {}; for i = 1:numel(p.pins) val{end+1} = p.pins{i}.name; endfor case "parent" val = p.parent; case "ppr" val = p.ppr; otherwise error ("rotaryEncoder.subsref invalid property '%s'", fld); endswitch else error("unimplemented rotaryEncoder.subsref type"); endif if (numel (s) > 1) val = subsref (val, s(2:end)); endif endfunction %!test %! ar = arduino(); %! r = rotaryEncoder (ar, "d2", "d3", 100); %! assert (isarduino(r.parent)) %! assert (ar.port, r.parent.port) %! assert (r.ppr, 100) %! assert (numel(r.pins) == 2) %! fail ("r.invalid") %! delete(r) arduino-0.12.1/inst/@servo/0000755000000000000000000000000014545566645012421 5ustar00arduino-0.12.1/inst/@servo/delete.m0000644000000000000000000000215114545566645014040 0ustar00## Copyright (C) 2020 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} delete (@var{dev}) ## Free resources of a servo object. ## ## @subsubheading Inputs ## @var{dev} - object to free ## ## @seealso{servo} ## @end deftypefn function delete(this) try ar = this.arduinoobj; pins = this.pins; if !isempty(ar) for i=1:numel(pins) pin = pins{i}; configurePinResource(ar, pin.name, pin.owner, pin.mode, true); configurePin(ar, pin.name, pin.mode); endfor this.arduinoobj = []; endif catch # do nothing end_try_catch endfunction arduino-0.12.1/inst/@servo/disp.m0000644000000000000000000000202114545566645013531 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} disp (@var{dev}) ## Display servo object. ## ## @subsubheading Inputs ## @var{dev} - servo device to display ## ## @seealso{servo} ## @end deftypefn function disp (this) printf (" arduino servo object with fields of: \n\n"); printf (" pins = %s\n", this.pins{1}.name ); printf (" minpulseduration = %f\n", this.minpulseduration); printf (" maxpulseduration = %f\n", this.maxpulseduration); endfunction arduino-0.12.1/inst/@servo/private/0000755000000000000000000000000014545566645014073 5ustar00arduino-0.12.1/inst/@servo/private/__servoPosition__.m0000644000000000000000000000321714545566645017733 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. see ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} __servoPosition__ (@var{obj}, @var{value}) ## Private function to get/set servo position ## @end deftypefn function out = __servoPosition__ (obj, value) persistent ARDUINO_SERVO_POSITION = 0; out = 0; ar = obj.arduinoobj; pininfo = obj.pins{1}; diff = obj.maxpulseduration - obj.minpulseduration; assert (diff >= 0); if nargin == 2 if !isnumeric (value) || value < 0 || value > 1.0 error("@servo.writePosition: value must be between 0 and 1"); endif # convert 0 - 1 to min - max pulse value = obj.minpulseduration + (diff*value); intval = uint16(value*1e6); datain = [ bitshift(intval,-8) bitand(intval, 255)]; [tmp, sz] = sendCommand (ar, "servo", ARDUINO_SERVO_POSITION, [pininfo.terminal datain]); else [tmp, sz] = sendCommand (ar, "servo", ARDUINO_SERVO_POSITION, [pininfo.terminal]); value = uint16(tmp(2))*256 + uint16(tmp(3)); value = double(value)/1e6; value = value - obj.minpulseduration; out = value/diff; endif endfunction arduino-0.12.1/inst/@servo/readPosition.m0000644000000000000000000000252414545566645015242 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{position} = } readPosition (@var{servo}) ## Read the position of a servo ## ## @subsubheading Inputs ## @var{servo} - servo object created from arduino.servo. ## ## @subsubheading Outputs ## @var{position} - value between 0 .. 1 for the current servo position, ## where 0 is the servo min position, 1 is the servo maximum position. ## ## @seealso{servo, writePosition} ## @end deftypefn function value = readPosition (obj) value = __servoPosition__(obj); endfunction %!shared ar %! ar = arduino(); %!test %! s = servo(ar, "d9", "minpulseduration", 1.0e-3, "maxpulseduration", 2e-3); %! writePosition(s, 1); %! assert(readPosition(s), 1); %! writePosition(s, 0); %! assert(readPosition(s), 0); %! delete(s); %!error readPosition(); arduino-0.12.1/inst/@servo/servo.m0000644000000000000000000001077214545566645013744 0ustar00## Copyright (C) 2018-2020 John Donoghue ## ## 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. classdef servo < handle ## -*- texinfo -*- ## @deftypefn {} {@var{obj} = } servo (@var{arduinoobj}, @var{pin}) ## @deftypefnx {} {@var{obj} = } servo (@var{arduinoobj}, @var{pin}, @var{propertyname}, @var{propertyvalue}) ## Create a servo object using a specified pin on a arduino board. ## ## @subsubheading Inputs ## @var{obj} - servo object ## ## @var{arduinoobj} - connected arduino object ## ## @var{propertyname}, @var{propertyvalue} - name value pairs for properties to pass ## to the created servo object. ## ## Current properties are: ## @table @asis ## @item minpulseduration ## min PWM pulse value in seconds. ## @item maxpulseduration ## max PWM pulse value in seconds. ## @end table ## ## @subsubheading Outputs ## @var{obj} - created servo object. ## ## @subsubheading Example ## @example ## # create arduino connection ## ar = arduino(); ## # create hobby servo (1 - 2 ms pulse range) ## servo = servo(ar, "d9", "minpulseduration", 1.0e-3, "maxpulseduration", 2e-3); ## # center the servo ## writePosition(servo, 0.5); ## @end example ## ## @subsubheading Properties ## The servo object has the following public properties: ## @table @asis ## @item parent ## The parent (arduino) for this device ## @item pins ## pins used by this object ## @item minpulseduration ## minpulseduration set for object ## @item maxpulseduration ## maxpulseduration set for object ## @end table ## ## @seealso{arduino, readPosition, writePosition} ## @end deftypefn properties (Access = private) arduinoobj = []; minpulseduration = 5.44e-04; maxpulseduration = 2.40e-03; pins = {}; endproperties methods (Access = public) function this = servo(varargin) persistent ARDUINO_SERVO_CONFIG = 1; if nargin < 2 error("expects arduino object and servo pin"); endif ar = varargin{1}; pin = varargin{2}; this.arduinoobj = []; this.minpulseduration = 5.44e-04; this.maxpulseduration = 2.40e-03; this.pins = {}; if mod (nargin, 2) != 0 error ("servo: expected property name, value pairs"); endif if !iscellstr (varargin(3:2:nargin)) error ("servo: expected property names to be strings"); endif for i = 3:2:nargin propname = tolower (varargin{i}); propvalue = varargin{i+1}; #printf("%s = %s\n", propname, propvalue); if strcmp(propname, "minpulseduration") if !isnumeric (propvalue) error ("servo: minpulseduration should be a number"); endif this.minpulseduration = propvalue; elseif strcmp(propname, "maxpulseduration") if !isnumeric (propvalue) error ("servo: maxpulseduration should be a number"); endif this.maxpulseduration = propvalue; endif endfor if (!isa (ar, "arduino")) error ("servo: expects arduino object"); endif pininfo = getPinInfo (ar, pin); this.arduinoobj = ar; validatePin (ar, pin, 'pwm'); configurePin (ar, pin, "pwm"); this.pins{end+1} = pininfo; sendCommand (ar, "servo", ARDUINO_SERVO_CONFIG, [pininfo.terminal]); # set clean up function # this.cleanup = onCleanup (@() cleanupServo (ar, pininfo)); endfunction endmethods endclassdef %!shared ar %! ar = arduino(); %!test %! assert(configurePin(ar, "d9"), "unset") %! s = servo(ar, "d9"); %! assert(!isempty(s)); %! assert(isa(s, "servo")); %! assert(configurePin(ar, "d9"), "pwm") %! delete(s) %! assert(configurePin(ar, "d9"), "unset") %!error servo(); %!error servo(ar); %! s = servo(ar, "d9", "minpulseduration", 1.0e-3, "maxpulseduration", 2e-3); %! assert(!isempty(s)); %! assert(s.minpulseduration, 1.0e-3); %! assert(s.maxpulseduration, 2.0e-3); %! delete(s) arduino-0.12.1/inst/@servo/subsref.m0000644000000000000000000000315414545566645014253 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{val} = } subsref (@var{dev}, @var{sub}) ## subref for servo ## ## @seealso{servo} ## @end deftypefn function val = subsref (p, s) if isempty(s) error ("servo.subsref missing index"); endif if s(1).type == "." fld = tolower(s(1).subs); switch (fld) case "pins" val = {}; for i = 1:numel(p.pins) val{end+1} = p.pins{i}; endfor case "parent" val = p.arduinoobj; case "minpulseduration" val = p.minpulseduration; case "maxpulseduration" val = p.maxpulseduration; case "parent" val = p.arduinoobj; otherwise error ("servo.subsref invalid property '%s'", fld); endswitch else error("unimplemented servo.subsref type"); endif if (numel (s) > 1) val = subsref (val, s(2:end)); endif endfunction %!test %! ar = arduino(); %! s = servo (ar, "d9"); %! assert (isarduino(s.parent)) %! assert (ar.port, s.parent.port) %! assert(s.minpulseduration > 0); %! assert(s.maxpulseduration > 0); %! assert (numel(s.pins) == 1) %! fail ("s.invalid") %! delete(s); arduino-0.12.1/inst/@servo/writePosition.m0000644000000000000000000000270014545566645015455 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} writePosition (@var{servo}, @var{position}) ## Write the position to a servo. ## ## @subsubheading Inputs ## @var{servo} - servo object created from arduino.servo. ## ## @var{position} - value between 0 .. 1 for the current servo position, ## where 0 is the servo min position, 1 is the servo maximum position. ## ## @seealso{servo, readPosition} ## @end deftypefn function writePosition (obj, value) if nargin != 2 error ("@servo.writePosition: expected value"); endif __servoPosition__(obj, value); endfunction %!shared ar, s %! ar = arduino(); %! s = servo(ar, "d9", "minpulseduration", 1.0e-3, "maxpulseduration", 2e-3); %!test %! writePosition(s, 1); %! assert(readPosition(s), 1); %! writePosition(s, 0); %! assert(readPosition(s), 0); %!error writePosition(); %! error writePosition(s); %!test %! delete(s); arduino-0.12.1/inst/@shiftRegister/0000755000000000000000000000000014545566645014105 5ustar00arduino-0.12.1/inst/@shiftRegister/delete.m0000644000000000000000000000227214545566645015530 0ustar00## Copyright (C) 2020 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} delete (@var{dev}) ## Free resources of a shiftRegister object. ## ## @subsubheading Inputs ## @var{dev} - object to free ## ## @seealso{shiftRegister} ## @end deftypefn function delete(this) try ar = this.parent; name = this.resourceowner; pins = this.pins; if ~isempty(ar) decrementResourceCount(ar, name); for i=1:numel(pins) pin = pins{i}; configurePinResource(ar, pin.name, pin.owner, pin.mode, true); configurePin(ar, pin.name, pin.mode); endfor this.parent = []; endif catch # do nothing end_try_catch endfunction arduino-0.12.1/inst/@shiftRegister/disp.m0000644000000000000000000000211714545566645015223 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} disp (@var{register}) ## Display the register object in a verbose way, ## ## @subsubheading Inputs ## @var{register} - the arduino register object created with shiftRegister. ## ## @seealso{shiftRegister} ## @end deftypefn function disp (register) printf (" arduino shift register object with fields of: \n"); printf (" model = ") disp(register.model); for i=1:numel(register.pins) pin = register.pins{i}; printf (" %s = %s\n", pin.func, pin.name) endfor endfunction arduino-0.12.1/inst/@shiftRegister/read.m0000644000000000000000000000461414545566645015203 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} read (@var{register}) ## @deftypefnx {} {@var{retval} =} read (@var{register}, @var{precision}) ## read a value from the shift register. ## ## @subsubheading Inputs ## @var{register} - shift register created from shiftRegister call. ## ## @var{precision} - optional precision of the data, where precision can be a ## number in a multiple of 8 (ie: 8,16,32) or can be a named integer type: 8 ## of 'uint8', 'uint16', 'uint32'. The default precision is 8. ## ## @subsubheading Outputs ## @var{retval} - returned data read from the register. ## ## @seealso{shiftRegister, write} ## @end deftypefn function out = read(register, precision) persistent ARDUINO_SHIFTREG_READ = 3; persistent endian; if isempty(endian) [~, ~, endian] = computer (); endif if nargin < 1 || nargin > 2 print_usage (); endif if nargin == 2 if ischar(precision) precision = tolower(precision); switch(precision) case "uint8" precision = 8; case "uint16" precision = 16; case "uint32" precision = 32; otherwise error ("unknown precsison value '%s'", precision) endswitch elseif isscalar(precision) if precision <= 0 || mod(precision, 8) != 0 error ("precision should be positive number that is a muiltiple of 8"); endif endif else precision = 8; endif # attempt to clock out precision bits [tmp, sz] = sendCommand(register.parent, "shiftregister", ARDUINO_SHIFTREG_READ, [register.id precision]); out = typecast(uint8(tmp(2:end)), ['uint' num2str(precision)]); if (endian == 'L') out = swapbytes (out); endif endfunction arduino-0.12.1/inst/@shiftRegister/reset.m0000644000000000000000000000224414545566645015407 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} reset (@var{register}) ## clear the shift register value. ## ## @subsubheading Inputs ## @var{register} - shift register created from shiftRegister call. ## ## @seealso{shiftRegister, read, write} ## @end deftypefn function reset(register) persistent ARDUINO_SHIFTREG_RESET = 0; # TODO: see if we have a reset pin ? [tmp, sz] = sendCommand(register.parent, "shiftregister", ARDUINO_SHIFTREG_RESET, [register.id]); endfunction arduino-0.12.1/inst/@shiftRegister/shiftRegister.m0000644000000000000000000001462014545566645017110 0ustar00## Copyright (C) 2018-2020 John Donoghue ## ## 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 ## . classdef shiftRegister < handle ## -*- texinfo -*- ## @deftypefn {} {@var{register} =} shiftRegister (@var{ar}, @var{shifttype}, @var{dataPin}, @var{clockPin} ...) ## @deftypefnx {} {@var{register} =} shiftRegister (@var{ar},'74hc164', @var{dataPin}, @var{clockPin}, @var{resetPin}) ## @deftypefnx {} {@var{register} =} shiftRegister (@var{ar},'74hc165', @var{dataPin}, @var{clockPin}, @var{loadPin}, @var{clockEnablePin}) ## @deftypefnx {} {@var{register} =} shiftRegister(@var{ar},'74hc595', @var{dataPin}, @var{clockPin}, @var{latchPin} , @var{resetPin}) ## Create shift register of a given type, controlled by the input pins. ## ## @subsubheading Inputs ## Common function parameter definition: ## ## @var{ar} - connected arduino object. ## ## @var{shifttype} - string name of the shift register type. ## ## @var{dataPin} - pin used for data in/out of the device. ## ## @var{clockPin} - pin used for clocking data on the shiftRegister. ## ## ## Other variables are dependent on the shift register type: ## @table @asis ## @item '74hc164' ## Additional inputs: ## ## @var{resetPin} - optional pin for resetting the shift register. ## ## @item '74hc165' ## Additional inputs: ## ## @var{loadPin} - load pin to the shift register. ## @var{clockEnablePin} - clock enable pin. ## ## @item '74hc595' ## Additional inputs: ## ## @var{latchPin} - latching data to the shift register. ## @var{resetPin} - optional pin for resetting the shift register. ## ## @end table ## ## @subsubheading Outputs ## @var{register} - register object ## ## @subsubheading Properties ## The shiftRegister object has the following public properties: ## @table @asis ## @item parent ## The parent (arduino) for this device ## @item pins ## pins used by this object ## @item model ## model set for object ## @end table ## ## @seealso{arduino} ## @end deftypefn properties (Access = private) parent = []; model = "none"; datapin = ""; clockpin = ""; id = 0; pins = {}; resourceowner = ""; endproperties methods (Access = public) function p = shiftRegister(ar,type,dataPin,clockPin, varargin) persistent ARDUINO_SHIFTREG_CONFIG = 1; if (nargin == 1 && isa (ar, "shiftRegister")) register = ar; # Copy constructor elseif nargin < 4 error ('Expected type, dataPin and clockPin'); else p.parent = ar; p.model = toupper(type); p.datapin = dataPin; p.clockpin = clockPin; p.id = 0; pins = {}; pins{end+1} = ar.get_pin(dataPin); pins{end}.func = "datapin"; # datapin used also to address this register p.id = pins{1}.id; name = ["shiftregister_" pins{1}.name]; p.resourceowner = name; count = getResourceCount(ar, name); if count > 0 error ("@shiftRegister.shiftRegister: already have a shift register using this pin"); endif pins{end+1} = ar.get_pin(clockPin); pins{end}.func = "clockpin"; init_data = []; switch (p.model) case '74HC164' init_data = [0 pins{2}.id]; case '74HC165' init_data = [1 pins{2}.id]; if nargin != 6 error('74HC165 expects loadPin and clockEnablePin'); endif pins{end+1} = ar.get_pin(varargin{1}); pins{end}.func = "loadpin"; pins{end+1} = ar.get_pin(varargin{2}); pins{end}.func = "clockenablepin"; init_data = [ init_data pins{3}.id pins{4}.id ]; case '74HC595' init_data = [2 pins{2}.id]; if nargin != 5 && nargin != 6 error('74HC595 expects latchPin and optional resetPin'); endif pins{end+1} = ar.get_pin(varargin{1}); pins{end}.func = "latchpin"; init_data = [ init_data pins{end}.id ]; # optional reset if nargin == 6 pins{end+1} = ar.get_pin(varargin{2}); pins{end}.func = "resetpin"; init_data = [ init_data pins{end}.id ]; endif otherwise error ("Unknown shiftRegister type '%s'", p.model); endswitch # verify pins support digital i/o for i = 1:numel(pins) pin = pins{i}.name; validatePin(ar, pin, "digital"); endfor p.pins = pins; # TODO: save old modes and set them via force if we fail trying to alloc the whole group try for i=1:numel(pins) pin = pins{i}.name; configurePin(ar, pin, "digitaloutput"); endfor [tmp, sz] = sendCommand(ar, "shiftregister", ARDUINO_SHIFTREG_CONFIG, [p.id 1 init_data]); incrementResourceCount(ar, name); catch # restore pin state for i=1:numel(pins) pin = pins{i}; configurePinResource(ar, pin.name, pin.owner, pin.mode, true) configurePin(ar, pin.name, pin.mode) endfor rethrow (lasterror); end_try_catch #p.cleanup = onCleanup (@() cleanupShiftRegister (ar, name, pins)); endif endfunction endmethods endclassdef %!shared ar %! ar = arduino(); %!test %! # validate pins not allocated %! assert(configurePin(ar, "d2"), "unset"); %! assert(configurePin(ar, "d3"), "unset"); %! %! register = shiftRegister(ar, '74hc164', "d2", "d3"); %! assert (isa (register, "shiftRegister")) %! %! #pins allocated ? %! assert(configurePin(ar, "d2"), "digitaloutput"); %! assert(configurePin(ar, "d3"), "digitaloutput"); %! %! #free %! delete(register) %! assert(configurePin(ar, "d2"), "unset"); %! assert(configurePin(ar, "d3"), "unset"); arduino-0.12.1/inst/@shiftRegister/subsref.m0000644000000000000000000000301614545566645015734 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{val} = } subsref (@var{dev}, @var{sub}) ## subref for shiftRegister ## ## @seealso{shiftRegister} ## @end deftypefn function val = subsref (p, s) if isempty(s) error ("shiftRegister.subsref missing index"); endif if s(1).type == "." fld = tolower(s(1).subs); switch (fld) case "pins" val = {}; for i = 1:numel(p.pins) val{end+1} = p.pins{i}.name; endfor case "parent" val = p.parent; case "model" val = p.model; otherwise error ("shiftRegister.subsref invalid property '%s'", fld); endswitch else error("unimplemented shiftRegister.subsref type"); endif if (numel (s) > 1) val = subsref (val, s(2:end)); endif endfunction %!test %! ar = arduino(); %! r = shiftRegister(ar, '74hc164', "d2", "d3"); %! assert (isarduino(r.parent)) %! assert (ar.port, r.parent.port) %! assert (r.model, "74HC164") %! assert (numel(r.pins) == 2) %! fail ("r.invalid") %! delete(r); arduino-0.12.1/inst/@shiftRegister/write.m0000644000000000000000000000512014545566645015413 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} write (@var{register}, @var{dataIn}) ## @deftypefnx {} write (@var{register}, @var{dataIn}, @var{precision}) ## Write a value to the shift register. ## ## @subsubheading Inputs ## @var{register} - shift register created from shiftRegister call. ## ## @var{dataIn} - data to clock into the shiftRegister. ## ## @var{precision} - optional precision of the data, where precision can be a ## number in a multiple of 8 (ie: 8,16,32) or can be a named integer type ## of 'uint8', 'uint16', 'uint32'. The default precision is 8. ## ## @seealso{shiftRegister, read} ## @end deftypefn function write(register, dataIn, precision) persistent ARDUINO_SHIFTREG_WRITE = 2; persistent endian; if isempty(endian) [~, ~, endian] = computer (); endif if nargin < 2 || nargin > 3 print_usage (); endif if nargin == 3 if ischar(precision) precision = tolower(precision); switch(precision) case "uint8" precision = 8; case "uint16" precision = 16; case "uint32" precision = 32; otherwise error ("unknown precsison value '%s'", precision) endswitch elseif isscalar(precision) if precision <= 0 || mod(precision, 8) != 0 error ("precision should be positive number that is a muiltiple of 8"); endif endif else precision = 8; endif switch (precision) case 8 dataIn = uint8(dataIn); case 16 dataIn = uint16(dataIn); if (endian == 'L') dataIn = swapbytes (dataIn); endif dataIn = typecast(dataIn, 'uint8'); case 32 dataIn = uint32(dataIn); if (endian == 'L') dataIn = swapbytes (dataIn); endif dataIn = typecast(dataIn, 'uint8'); endswitch [tmp, sz] = sendCommand(register.parent, "shiftregister", ARDUINO_SHIFTREG_WRITE, [register.id dataIn]); endfunction arduino-0.12.1/inst/@spidev/0000755000000000000000000000000014545566645012555 5ustar00arduino-0.12.1/inst/@spidev/delete.m0000644000000000000000000000335514545566645014203 0ustar00## Copyright (C) 2020 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} delete (@var{dev}) ## Free resources of a spidev object. ## ## @subsubheading Inputs ## @var{dev} - spidev object to free ## ## @seealso{spidev} ## @end deftypefn function delete(this) try ar = this.parent; resource = this.resourceowner; if !isempty(ar) pins = this.pins; for i=1:numel(pins) pin = pins{i}; if strcmp(tolower(pin.func), "cs") configurePinResource(ar, pin.name, pin.owner, pin.mode, true); configurePin(ar, pin.name, pin.mode); endif endfor # clean up the spi port if not used? count = getResourceCount(ar, resource); if count > 0 count = decrementResourceCount(ar, resource); if count == 0 # last user, so free pins (except ss that we already did) pins = getSharedResourceProperty(ar, resource, "pins"); for i=1:numel(pins) pin = pins{i}; configurePinResource(ar, pin.name, pin.owner, pin.mode, true); configurePin(ar, pin.name, pin.mode); endfor endif endif this.parent = []; endif catch # do nothing end_try_catch endfunction arduino-0.12.1/inst/@spidev/disp.m0000644000000000000000000000231314545566645013671 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} disp (@var{dev}) ## Display spidev object. ## ## @subsubheading Inputs ## @var{dev} - spidev object to display ## ## @seealso{spidev} ## @end deftypefn function disp (this) printf (" arduino spidev object with fields of: \n\n"); printf (" chipselectpin = %s\n", this.chipselectpin); printf (" mode = %d\n", this.mode); printf (" bitorder = %s\n", this.bitorder); printf (" bitrate = %d\n", this.bitrate); printf (" pins = "); for i=1:numel(this.pins) printf("%s(%s) ", this.pins{i}.name, this.pins{i}.func) endfor printf("\n"); printf("\n"); endfunction arduino-0.12.1/inst/@spidev/spidev.m0000644000000000000000000001777714545566645014250 0ustar00## Copyright (C) 2018-2020 John Donoghue ## ## 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. classdef spidev < handle ## -*- texinfo -*- ## @deftypefn {} {@var{dev} =} spidev (@var{ar}, @var{cspin}) ## @deftypefnx {} {@var{dev} =} spidev (@var{ar}, @var{cspin}, @var{propname}, @var{propvalue}) ## ## @code{spidev} is depreciated and will be removed in a future version. ## Use @code{device} instead. ## ## Create an spidev object to communicate to the SPI port on a connected arduino. ## ## @subsubheading Inputs ## @var{ar} - connected arduino object ## ## @var{cspin} - chip select pin for attached spi device. ## ## @var{propname}, @var{propvalue} - property name/value pair for values to pass to devices. ## ## Currently known properties: ## @table @asis ## @item bitrate ## bit rate speed in Mbs ## @item bitorder ## 'msbfirst' or 'lsbfirst' ## @item mode ## SPI mode 0 - 3. ## @end table ## ## @subsubheading Outputs ## @var{dev} - created spidev object ## ## @subsubheading Properties ## The spidev object has the following public properties: ## @table @asis ## @item parent ## The parent (arduino) for this device ## @item pins ## pins used by this object ## @item mode ## mode used for created object ## @item bitrate ## Bitrate set for object ## @item bitorder ## Bitorder set for object ## @item chipselectpin ## Pin used for chipselect ## @end table ## ## @seealso{arduino, readWrite} ## @end deftypefn properties (Access = private) id = []; chipselectpin = ""; mode = 0; bitrate = 4000000; bitorder = 'msbfirst'; parent = []; resourceowner = "spi"; pins = {}; endproperties methods (Access = public) function this = spidev (varargin) ARDUINO_SPI_CONFIG = 1; persistent warned = false; if (! warned) warned = true; warning ("Octave:deprecated-function", "spidev is obsolete and will be removed from a future version of arduino, please use 'device' instead"); endif if nargin < 2 error ("spidev: expects arduino object and chipselect pin"); endif ar = varargin{1}; cspin = varargin{2}; if mod(nargin, 2) != 0 error ("spidev: expected property name, value pairs"); endif if !iscellstr (varargin(3:2:nargin)) error ("spidev: expected property names to be strings"); endif isfirst = getResourceCount(ar,"spi") == 0; for i = 3:2:nargin propname = tolower(varargin{i}); propvalue = varargin{i+1}; % printf("%s = %s\n", propname, propvalue); if strcmp (propname, "bitrate") if !isnumeric (propvalue) error("bitrate should be a number") endif this.bitrate = propvalue; elseif strcmp (propname, "mode") if !isnumeric (propvalue) || propvalue < 0 || propvalue > 3 error("mode should be a number betwwen 0 - 3"); endif this.mode = propvalue; elseif strcmp (propname, "bitorder") if !ischar(propvalue) error("bitorder should be a string"); endif this.bitorder = tolower(propvalue); if this.bitorder != "msbfirst" && this.bitorder != "lsbfirst" error("bitorder should be 'msbfirst' or 'lsbfirst'"); endif endif endfor if (!isa (ar, "arduino")) error("expects arduino object"); endif this.chipselectpin = cspin; this.parent = ar; this.resourceowner = "spi"; # check if is valid CS pin that can use as output validatePin(ar, cspin, 'digital') if strcmp(getResourceOwner(ar, cspin), this.resourceowner) error ("pin %s is already in use by SPI", cspin) endif if isfirst terms = getSPITerminals(ar); tmp_pins = ar.get_pingroup(terms{1}, "SPI"); if numel(tmp_pins) != 4 error ("expected 4 SPI pins but only have %d", numel(tmp_pins)) endif setSharedResourceProperty(ar, this.resourceowner, "pins", tmp_pins); endif tmp_pins = getSharedResourceProperty(ar, this.resourceowner, "pins"); cs_is_ss = false; cspin = getPinInfo(ar, cspin); cspin.func = "cs"; for i=1:4 # verify cs pin is either SS pin, or a not a spi pin if strcmp(tolower(tmp_pins{i}.func), "ss") if strcmpi(tmp_pins{i}.name, cspin.name) cs_is_ss = true; endif else # check not trying to set CS to a spi pin if strcmpi(tmp_pins{i}.name, cspin.name) error ("can not set cspin to a SPI function pin"); endif endif endfor if !cs_is_ss tmp_pins{end+1} = cspin; endif this.pins = tmp_pins; this.id = cspin.terminal; try for i=1:numel(tmp_pins) if isfirst if strcmp(tolower(tmp_pins{i}.func), "ss") || strcmp(tolower(tmp_pins{i}.func), "cs") configurePin(ar, tmp_pins{i}.name, "digitaloutput") configurePinResource (ar, tmp_pins{i}.name, "spi", "digitaloutput", true); else configurePin(ar, tmp_pins{i}.name, "spi") endif else # only allocate cs pin if not first device if strcmp(tolower(tmp_pins{i}.func), "cs") configurePin(ar, tmp_pins{i}.name, "digitaloutput") configurePinResource (ar, tmp_pins{i}.name, "spi", "digitaloutput", true); endif endif endfor bitorder = 0; if strcmp(this.bitorder, 'lsbfirst') bitorder = 1; endif [tmp, sz] = sendCommand(this.parent, this.resourceowner, ARDUINO_SPI_CONFIG, [this.id 1 this.mode bitorder]); incrementResourceCount(ar, this.resourceowner); catch for i=1:numel(tmp_pins) if strcmp(tolower(tmp_pins{i}.func), "cs") || isfirst configurePinResource(ar, tmp_pins{i}.name, tmp_pins{i}.owner, tmp_pins{i}.mode, true) configurePin(ar, tmp_pins{i}.name, tmp_pins{i}.mode) endif endfor rethrow (lasterror); end_try_catch endfunction endmethods endclassdef %!shared arduinos %! arduinos = scanForArduinos(1); %!assert(numel(arduinos), 1); %!test %! ar = arduino(); %! assert(!isempty(ar)); %! %! spipins = getSPITerminals(ar); %! assert (numel(spipins), 4); %! %! # validate SPI pins not allocated %! assert(configurePin(ar, "d10"), "unset") %! assert(configurePin(ar, spipins{1}), "unset") %! assert(configurePin(ar, spipins{2}), "unset") %! assert(configurePin(ar, spipins{3}), "unset") %! assert(configurePin(ar, spipins{4}), "unset") %! %! spi = spidev(ar, "d10"); %! assert(!isempty(spi)); %! assert(spi.chipselectpin, "d10"); %! %! # validate SPI pins allocated %! assert(configurePin(ar, "d10"), "digitaloutput") %! #assert(configurePin(ar, spipins{1}), 'digitaloutput') ## ss %! #assert(configurePin(ar, spipins{2}), 'digitaloutput') ## mosi %! #assert(configurePin(ar, spipins{3}), 'digitalinput') ## miso %! #assert(configurePin(ar, spipins{4}), 'digitaloutput') ## sck %! %! delete(spi); %! %! # check now pins unset %! assert(configurePin(ar, "d10"), "unset") %! assert(configurePin(ar, spipins{1}), "unset") %! assert(configurePin(ar, spipins{2}), "unset") %! assert(configurePin(ar, spipins{3}), "unset") %! assert(configurePin(ar, spipins{4}), "unset") %!test %! ar = arduino(); %! spi = spidev(ar, "d10"); %! fail ('spidev(ar, "d10");', 'pin d10 is already in use') %! spi2 = spidev(ar, "d5"); %! delete(spi); %! delete(spi2); arduino-0.12.1/inst/@spidev/subsref.m0000644000000000000000000000325614545566645014412 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{val} = } subsref (@var{dev}, @var{sub}) ## subref for spidev ## ## @seealso{spidev} ## @end deftypefn function val = subsref (this, s) if isempty(s) error ("spidev.subsref missing index"); endif if s(1).type == "." fld = tolower(s(1).subs); switch (fld) case "pins" val = {}; for i = 1:numel(this.pins) val{end+1} = this.pins{i}.name; endfor case "parent" val = this.parent; case "mode" val = this.mode; case "bitrate" val = this.bitrate; case "bitorder" val = this.bitorder; case "chipselectpin" val = this.chipselectpin; otherwise error ("spidev.subsref invalid property '%s'", fld); endswitch else error("unimplemented spidev.subsref type"); endif if (numel (s) > 1) val = subsref (val, s(2:end)); endif endfunction %!test %! ar = arduino(); %! spi = spidev (ar, "d10"); %! assert (spi.chipselectpin, "d10") %! assert (isarduino(spi.parent)) %! assert (ar.port, spi.parent.port) %! assert (spi.mode, 0) %! assert (spi.bitorder, "msbfirst") %! assert (numel(spi.pins) >= 4) %! fail ("spi.invalid") arduino-0.12.1/inst/@spidev/writeRead.m0000644000000000000000000000343314545566645014664 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{dataOut} =} readWrite (@var{spi}, @var{dataIn}) ## Write uint8 data to spi device and return ## back clocked out response data of same size. ## ## @subsubheading Inputs ## @var{spi} - connected spi device on arduino ## ## @var{dataIn} - uint8 sized data to send to spi device framed between SS frame. ## ## @subsubheading Outputs ## @var{dataOut} - uint8 data clocked out during send to dataIn. ## ## @seealso{arduino, spidev} ## @end deftypefn function dataOut = writeRead (this, dataIn) dataOut = []; persistent ARDUINO_SPI_READ_WRITE = 2; if nargin < 2 error ("@spidev.writeRead: expected dataIn"); endif [tmp, sz] = sendCommand (this.parent, this.resourceowner, ARDUINO_SPI_READ_WRITE, [this.id uint8(dataIn)]); if sz > 0 dataOut = tmp(2:end); endif endfunction %!shared arduinos %! arduinos = scanForArduinos(1); %!assert(numel(arduinos), 1); %!test %! ar = arduino(); %! assert(!isempty(ar)); %! spi = spidev(ar, "d10"); %! assert(!isempty(spi)); %! data = writeRead(spi, 1); %! assert(numel(data), 1); %!test %! ar = arduino(); %! assert(!isempty(ar)); %! spi = spidev(ar, "d10"); %! assert(!isempty(spi)); %! data = writeRead(spi, [1 1 1]); %! assert(numel(data), 3); arduino-0.12.1/inst/@ultrasonic/0000755000000000000000000000000014545566645013446 5ustar00arduino-0.12.1/inst/@ultrasonic/delete.m0000644000000000000000000000223314545566645015066 0ustar00## Copyright (C) 2020 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} delete (@var{dev}) ## Free resources of a ultrasonic object. ## ## @subsubheading Inputs ## @var{dev} - ultrasonic object to free ## ## @seealso{ultrasonic} ## @end deftypefn function delete(this) try ar = this.parent; resource = this.resourceowner; pins = this.pins; if ! isempty(ar) for i=1:numel(pins) pin = pins{i}; configurePinResource(ar, pin.name, pin.owner, pin.mode, true); configurePin(ar, pin.name, pin.mode); endfor this.parent = []; endif catch # do nothing end_try_catch endfunction arduino-0.12.1/inst/@ultrasonic/disp.m0000644000000000000000000000200014545566645014553 0ustar00## Copyright (C) 2019 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {} disp (@var{dev}) ## Display ultrasonic object. ## ## @subsubheading Inputs ## @var{dev} - ultrasonic object to display ## ## @seealso{ultrasonic} ## @end deftypefn function disp (this) printf (" arduino ultrasonic object with fields of: \n\n"); printf (" triggerpin = %s\n", this.pins{1}.name); if numel(this.pins) > 1 printf (" echopin = %s\n", this.pins{2}.name); endif printf("\n"); endfunction arduino-0.12.1/inst/@ultrasonic/readDistance.m0000644000000000000000000000315014545566645016211 0ustar00## Copyright (C) 2019 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{distance} =} readDistance (@var{dev}) ## Read the distance from a ultrasonic device ## ## @subsubheading Inputs ## @var{dev} - connected ultrasonic device opened using ultrasonic ## ## @subsubheading Outputs ## @var{distance} - distance value in meters from the ultrasonic device, or Inf if out of sensor range ## ## @seealso{arduino, ultrasonic} ## @end deftypefn function out = readDistance (dev) persistent ARDUINO_ULTRASONIC_READ = 2; persistent endian; if isempty(endian) [~, ~, endian] = computer (); endif if nargin != 1 print_usage (); endif [tmp, sz] = sendCommand (dev.parent, "ultrasonic", ARDUINO_ULTRASONIC_READ, [dev.id]); value = uint32(tmp(2))*(256*256*256) + uint32(tmp(3))*(256*256) + uint32(tmp(4))*256 + uint32(tmp(5)); if value == 0 || value == 0xffffffff out = Inf; else out = double(value)*0.0344/2/100; % meters endif endfunction %!test %! ar = arduino(); %! x = ultrasonic(ar, "d9"); %! v = readDistance(x); %!error <'readDistance' undefined> readDistance() arduino-0.12.1/inst/@ultrasonic/readEchoTime.m0000644000000000000000000000317214545566645016160 0ustar00## Copyright (C) 2019 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{time} =} readEchoTime (@var{dev}) ## Measure the time for waves to reflect back to the ultrasonic device ## ## @subsubheading Inputs ## @var{dev} - connected ultrasonic device opened using ultrasonic() ## ## @subsubheading Outputs ## @var{time} - time in seconds, or Inf if out of sensor range ## ## @seealso{arduino, ultrasonic} ## @end deftypefn function out = readEchoTime (dev) persistent ARDUINO_ULTRASONIC_READ = 2; if nargin != 1 print_usage (); endif precision = dev.outputformat; [tmp, sz] = sendCommand (dev.parent, "ultrasonic", ARDUINO_ULTRASONIC_READ, [dev.id]); value = uint32(tmp(2))*(256*256*256) + uint32(tmp(3))*(256*256) + uint32(tmp(4))*256 + uint32(tmp(5)); if value == 0 || value == 0xffffffff out = Inf; else # seconds out = double(value)/1000000.0; endif # TODO precision can be double or duration - currently octave doesnt know duration endfunction %!test %! ar = arduino(); %! x = ultrasonic(ar, "d9"); %! v = readEchoTime(x); %!error <'readEchoTime' undefined> readEchoTime() arduino-0.12.1/inst/@ultrasonic/subsref.m0000644000000000000000000000317014545566645015276 0ustar00## Copyright (C) 2019 John Donoghue ## ## 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. ## -*- texinfo -*- ## @deftypefn {} {@var{val} = } subsref (@var{dev}, @var{sub}) ## subref for ultrasonic ## ## @seealso{ultrasonic} ## @end deftypefn function val = subsref (p, s) if isempty(s) error ("ultrasonic.subsref missing index"); endif if s(1).type == "." fld = tolower(s(1).subs); switch (fld) case "pins" val = {}; for i = 1:numel(p.pins) val{end+1} = p.pins{i}.name; endfor case "outputformat" val = p.outputformat; case "parent" val = p.parent; case "triggerpin" val = p.pins{1}.name; case "echopin" if numel(p.pins) > 1 val = p.pins{2}.name; else val = []; endif otherwise error ("ultrasonic.subsref invalid property '%s'", fld); endswitch else error("unimplemented ultrasonic.subsref type"); endif if (numel (s) > 1) val = subsref (val, s(2:end)); endif endfunction %!test %! ar = arduino(); %! x = ultrasonic (ar, "d2", "d3"); %! assert (isarduino(x.parent)) %! assert (x.triggerpin, "d2") %! assert (x.echopin, "d3") %! assert (numel(x.pins) == 2) %! fail ("x.invalid") arduino-0.12.1/inst/@ultrasonic/ultrasonic.m0000644000000000000000000001251314545566645016011 0ustar00## Copyright (C) 2019-2020 John Donoghue ## ## 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. classdef ultrasonic < handle ## -*- texinfo -*- ## @deftypefn {} {@var{dev} =} ultrasonic (@var{ar}, @var{triggerpin}) ## @deftypefnx {} {@var{dev} =} ultrasonic (@var{ar}, @var{triggerpin}, @var{echopin}) ## @deftypefnx {} {@var{dev} =} ultrasonic (@var{ar}, @var{triggerpin}, @var{echopin}, @var{propname}, @var{propvalue}) ## Create an ultrasonic object to communicate to a connected ultrasonic device ## ## @subsubheading Inputs ## @var{ar} - connected arduino object ## ## @var{triggerpin} - trigger pin for attached device. ## ## @var{echopin} - trigger pin for attached device. ## ## @var{propname}, @var{propvalue} - property name/value pair for values to pass to devices. ## ## Currently known properties: ## @table @asis ## @item outputformat ## string designating number format for output ('double') ## @end table ## ## @subsubheading Outputs ## @var{dev} - created ultrasonic object ## ## @subsubheading Properties ## The ultrasonic object has the following public properties: ## @table @asis ## @item parent ## The parent (arduino) for this device ## @item pins ## pins used by this object ## @item triggerpin ## trigger used for created object ## @item echopin ## Echo pin set for object ## @item outputformat ## Output format for the created object ## @end table ## ## @seealso{arduino, readDistance, readEchoTime} ## @end deftypefn properties (Access = private) id = []; pins = {}; outputformat = "double"; parent = []; resourceowner = "ultrasonic"; endproperties methods (Access = public) function this = ultrasonic (varargin) ARDUINO_ULTRASONIC_CONFIG = 1; if nargin < 2 error ("expects arduino object and triggerpin pin"); endif ar = varargin{1}; triggerpin = varargin{2}; echopin = []; if nargin > 2 echopin = varargin{3}; endif if nargin > 3 && mod(nargin-3, 2) != 0 error ("arduino: expected property name, value pairs"); endif if !iscellstr (varargin(4:2:nargin)) error ("arduino: expected property names to be strings"); endif this.id = []; this.pins = {}; this.outputformat = "double"; for i = 4:2:nargin propname = tolower(varargin{i}); propvalue = varargin{i+1}; % printf("%s = %s\n", propname, propvalue); if strcmp (propname, "outputformat") if !ischar(propvalue) error("outputformat should be a string"); endif this.outputformat = tolower(propvalue); # NOTE:currently outputformat is ignored endif endfor if (!isa (ar, "arduino")) error("expects arduino object"); endif this.parent = ar; this.resourceowner = "ultrasonic"; tmp_pins = {}; validatePin(ar, triggerpin, 'digital') tmp_pins{end+1} = getPinInfo(ar, triggerpin); if !isempty(echopin) validatePin(ar, echopin, 'digital') tmp_pins{end+1} = getPinInfo(ar, echopin); endif this.pins = tmp_pins; this.id = tmp_pins{1}.terminal; try configurePin(ar, tmp_pins{1}.name, "digitaloutput") configurePinResource (ar, tmp_pins{1}.name, this.resourceowner, "digitaloutput", true); if numel(tmp_pins) > 1 configurePin(ar, tmp_pins{2}.name, "digitaloutput") configurePinResource (ar, tmp_pins{2}.name, this.resourceowner, "digitalinput", true); endif if numel(tmp_pins) > 1 [tmp, sz] = sendCommand(this.parent, this.resourceowner, ARDUINO_ULTRASONIC_CONFIG, [this.id 1 tmp_pins{2}.terminal]); else [tmp, sz] = sendCommand(this.parent, this.resourceowner, ARDUINO_ULTRASONIC_CONFIG, [this.id 1]); endif catch for i=1:numel(tmp_pins) configurePinResource(ar, tmp_pins{i}.name, tmp_pins{i}.owner, tmp_pins{i}.mode, true) configurePin(ar, tmp_pins{i}.name, tmp_pins{i}.mode) endfor rethrow (lasterror); end_try_catch # # set clean up function # this.cleanup = onCleanup (@() cleanupUltrasonic (ar, this.resourceowner, tmp_pins)); endfunction endmethods endclassdef %!shared arduinos %! arduinos = scanForArduinos(1); %!assert(numel(arduinos), 1); %!test %! ar = arduino(); %! assert(!isempty(ar)); %! %! x = ultrasonic(ar, "d9"); %! assert(!isempty(x)); %! assert(isa(x, "ultrasonic")) %!test %! ar = arduino(); %! x = ultrasonic(ar, "d9", "d10"); %! assert(!isempty(x)); %!test %! ar = arduino(); %! fail ('ultrasonic();', 'expects arduino object and triggerpin pin') %! fail ('ultrasonic(ar);', 'expects arduino object and triggerpin pin') %! fail ('ultrasonic(ar, "hello");', 'arduino: unknown pin hello') arduino-0.12.1/inst/__load_arduino__.m0000644000000000000000000000343114545566645014576 0ustar00## Copyright (C) 2023 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {} __load_arduino__ () ## Undocumented internal function of arduino package. ## @end deftypefn ## PKG_ADD: __load_arduino__ () function __load_arduino__ () if exist ("isfolder") == 0 if (isdir (fullfile (fileparts (mfilename ("fullpath")), "sensors"))) addpath (fullfile (fileparts (mfilename ("fullpath")), "sensors")); endif else if (isfolder (fullfile (fileparts (mfilename ("fullpath")), "sensors"))) addpath (fullfile (fileparts (mfilename ("fullpath")), "sensors")); endif endif # on package load, attempt to load docs try pkg_dir = fileparts (fullfile (mfilename ("fullpath"))); doc_file = fullfile (pkg_dir, "doc", "arduino.qch"); doc_file = strrep (doc_file, '\', '/'); if exist(doc_file, "file") if exist("__event_manager_register_documentation__") __event_manager_register_documentation__ (doc_file); elseif exist("__event_manager_register_doc__") __event_manager_register_doc__ (doc_file); endif endif catch # do nothing end_try_catch endfunction arduino-0.12.1/inst/__unload_arduino__.m0000644000000000000000000000345114545566645015143 0ustar00## Copyright (C) 2023 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {} __unload_arduino__ () ## Undocumented internal function of arduino package. ## @end deftypefn ## PKG_DEL: __unload_arduino__ () function __unload_arduino__ () if exist ("isfolder") == 0 if (isdir (fullfile (fileparts (mfilename ("fullpath")), "sensors"))) rmpath (fullfile (fileparts (mfilename ("fullpath")), "sensors")); endif else if (isfolder (fullfile (fileparts (mfilename ("fullpath")), "sensors"))) rmpath (fullfile (fileparts (mfilename ("fullpath")), "sensors")); endif endif # on package unload, attempt to unload docs try pkg_dir = fileparts (fullfile (mfilename ("fullpath"))); doc_file = fullfile (pkg_dir, "doc", "arduino.qch"); doc_file = strrep (doc_file, '\', '/'); if exist(doc_file, "file") if exist("__event_manager_unregister_documentation__") __event_manager_unregister_documentation__ (doc_file); elseif exist("__event_manager_unregister_doc__") __event_manager_unregister_doc__ (doc_file); endif endif catch # do nothing end_try_catch endfunction arduino-0.12.1/inst/addon.m0000644000000000000000000000605014545566645012427 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} addon (@var{ar}, @var{addonname}) ## @deftypefnx {} {@var{retval} =} addon (@var{ar}, @var{addonname}, varargs) ## Create an addon object using the addon named class. ## ## @subsubheading Inputs ## @var{ar} - connected arduino object ## ## @var{addonname} - the name of the addon to create. The addon name can be a user ## addon or an inbuilt addon, however must appear in the listArduinoLibraries ## output and have been programmed onto the arduino. ## ## @var{varargs} - optional values that will be provided verbatim to the ## the addon class constructor. ## ## @subsubheading Outputs ## @var{retval} - cell array of string library names. ## ## @seealso{arduino, arduinosetup, listArduinoLibraries} ## @end deftypefn function retval = addon (ar, addonname, varargin) if (! isa (ar, "arduino")) error("addon: expected first arguiment to be a arduino object"); endif # verify arduino has the plugin name p = ar.get_lib (addonname); if p == -1 error ("addon: arduino has not been programmed with a plugin named '%s'\n", addonname); endif availlibs = listArduinoLibraries (); addonlibs = __addons__ (); # get addonin for the requested library idx = find (cellfun(@(x) strcmpi(x.libraryname, addonname), addonlibs), 1); if isempty (idx) #if not found, was an inbuilt one ? # verify can find the lib and get/make constructor of it idx = find (cellfun(@(x) strcmpi(x, addonname), availlibs), 1); if isempty (idx) error ("addon: unknown library '%s'", addonname); endif # a known normal addon like spi if strcmpi (addonname, "spi") lib = "spidev"; elseif strcmpi (addonname, "i2c") lib = "i2cdev"; elseif strcmpi (addonname, "servo") lib = "servo"; elseif strcmpi (addonname, "shiftregister") lib = "shiftRegister"; elseif strcmpi (addonname, "rotaryencoder") lib = "rotaryEncoder"; else error ("addon: unknown builtin library '%s'", addonname); endif else # user addon constructor lib = addonlibs{idx}.classname; endif # get constructor function handle constructor = str2func (lib); # create object retval = constructor (ar, varargin{:}); endfunction %!test %! a = arduino(); %! # do equivalent of s = i2cdev(a, 10); %! s = addon(a, "i2c", 10); %! assert(class(s), "i2cdev"); arduino-0.12.1/inst/arduino_bistsetup.m0000644000000000000000000000704614545566645015113 0ustar00## Copyright (C) 2019-2020 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} arduino_bistsetup () ## @deftypefnx {} {@var{retval} =} arduino_bistsetup (@var{propertyname}, @var{propertyvalue}) ## Install on an arduino the required core libraries to run the BIST tests ## ## As part of the setup, the arduino IDE will be opened to allow programming ## the arduino board. ## ## @subsubheading Inputs ## ## @var{propertyname}, @var{propertyvalue} - A sequence of property name/value pairs can be given ## to set defaults while programming. ## ## Currently the following properties can be set: ## @table @asis ## @item arduinobinary ## The value should be the name/path of the arduino IDE binary for programming. If not specified, ## the function will attempt to find the binary itself. ## @item debug ## Set the debug flag when checking the arduino ## @end table ## ## @subsubheading Outputs ## @var{retval} - return 1 if everything installed ok ## ## @seealso{arduino, arduinosetup} ## @end deftypefn function retval = arduino_bistsetup (varargin) retval = 0; if mod (nargin, 2) != 0 error ("arduinosetup: expected property name, value pairs"); endif if !iscellstr (varargin(1:2:nargin)) error ("arduinosetup: expected property names to be strings"); endif arduinobinary = {}; debug = false; for i = 1:2:nargin propname = tolower (varargin{i}); propvalue = varargin{i+1}; if strcmp (propname, "arduinobinary") arduinobinary = propvalue; elseif strcmp (propname, "debug") debug = propvalue; elseif warning ("arduino_bistsetup: unknown property '%s', ignoring it", propname); endif endfor printf ("** Installing core libraries on arduino - please press upload in the IDE, and after completion, close the IDE\n"); fflush(stdout); libs = { "I2C", "servo", "SPI", "ShiftRegister", "RotaryEncoder", "Ultrasonic" }; if ! arduinosetup ('libraries', libs, varargin{:}) error ("Failed to program the arduino"); endif unwind_protect printf ("** Checking for any arduinos\n"); fflush(stdout); ars = scanForArduinos(); printf ("Found %d\n", numel(ars)); printf ("** Checking can open an UNO arduino\n"); fflush(stdout); ar = arduino ([], "uno", 'debug', debug); if ! isarduino(ar) error ('Couldnt load find an arduino UNO board') endif printf ("** Checking arduino version\n"); fflush(stdout); p = pkg('list', 'arduino'); if isempty(p) error ('No arduino package found'); endif ver = p{1}.version; if ! strcmp(ver, version(ar)) error ('Arduino version did not match %s : %s', ver, version(ar)); endif printf ('Arduino has been programmed and is ready for BIST testing\n'); printf ("run: __run_test_suite__({'%s'}, {})\n", p{1}.dir); fflush(stdout); ret = 1; unwind_protect_cleanup clear ar; end_unwind_protect endfunction arduino-0.12.1/inst/arduinosetup.m0000644000000000000000000002121414545566645014063 0ustar00## Copyright (C) 2018-2019 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} arduinosetup () ## @deftypefnx {} {@var{retval} =} arduinosetup (@var{propertyname}, @var{propertyvalue}) ## Open the arduino config / programming tool to program the arduino hardware for usage with ## the Octave arduino functions. ## ## arduinosetup will create a temporary project using the arduino IDE and allow ## compiling and programming of the code to an arduino. ## ## @subsubheading Inputs ## ## @var{propertyname}, @var{propertyvalue} - A sequence of property name/value pairs can be given ## to set defaults while programming. ## ## Currently the following properties can be set: ## @table @asis ## @item libraries ## The value should be the name of a library, or string array of libraries to program on the ## arduino board. ## @item arduinobinary ## The value should be the name/path of the arduino IDE binary for programming. If not specified, ## the function will use getpref preferences of arduino.arduino_binary, and if not found, the ## function will attempt to find the binary itself. ## ## If provided, the value will be saved to preferences for future calls. ## @end table ## ## @subsubheading Outputs ## @var{retval} - return 1 if arduino IDE returned without an error ## ## @seealso{arduino, __arduino_binary__} ## @end deftypefn function retval = arduinosetup (varargin) retval = 0; if mod (nargin, 2) != 0 error ("arduinosetup: expected property name, value pairs"); endif if !iscellstr (varargin(1:2:nargin)) error ("arduinosetup: expected property names to be strings"); endif libs = {}; arduinobinary = {}; debug = false; baudrate = []; def_baudrate = 9600; for i = 1:2:nargin propname = tolower (varargin{i}); propvalue = varargin{i+1}; if strcmp (propname, "libraries") if iscell (propvalue) libs = propvalue; elseif ischar (propvalue) libs{end+1} = propvalue; else error ("arduinosetup Expected libraries to be a cellarray or string"); endif elseif strcmp (propname, "arduinobinary") arduinobinary = propvalue; elseif strcmp (propname, "baudrate") baudrate = int32(propvalue); elseif strcmp (propname, "debug") debug = propvalue; elseif warning ("arduinosetup: unknown property '%s', ignoring it", propname); endif endfor if isempty(libs) # default libs if not are provided libs{end+1} = "SPI"; libs{end+1} = "I2C"; libs{end+1} = "Servo"; libs{end+1} = "ShiftRegister"; endif # we have the libs ? availlibs = listArduinoLibraries (); addonlibs = __addons__ (); # for any addons, check the dependancies and add it we need to for i = 1:numel(libs) idx = find (cellfun(@(x) strcmpi(x.libraryname, libs{i}), addonlibs), 1); if !isempty(idx) lib = addonlibs{idx}; for n = 1:numel(lib.dependentlibraries) addlib = lib.dependentlibraries{n}; idx = find (cellfun(@(x) strcmpi(x, addlib), libs), 1); if isempty(idx) libs{end+1} = addlib; if (debug) printf("arduinosetup: adding %s as a dependency\n", addlib); endif endif endfor endif endfor builtinlibs = {}; for i = 1:numel(libs) idx = find (cellfun(@(x) strcmpi(x.libraryname, libs{i}), addonlibs), 1); if isempty(idx) idx = find (cellfun(@(x) strcmpi(x, libs{i}), availlibs), 1); if isempty (idx) error ("arduinosetup: unknown library '%s'", libs{i}); elseif (debug) printf("arduinosetup: using builtin lib %s\n", libs{i}); endif builtinlibs{end+1} = libs{i}; libs{i} = []; else if (debug) printf("arduinosetup: using addon lib %s\n", libs{i}); endif libs{i} = addonlibs{idx}; endif endfor libfiles = arduinoio.LibFiles(); if isempty (libfiles) error ("arduinosetup: couldn't find library files"); endif # make a temp folder and create a arduino project in it tmpdir = tempname (); mkdir (tmpdir); unwind_protect mkdir (fullfile (tmpdir, "octave")); # copy all the libfiles copyfile (libfiles, fullfile (tmpdir, "octave")); fd = fopen (fullfile (tmpdir, "octave", "settings.h"), "w+t"); fprintf (fd, "// generated from arduinosetup for buildin library configuration\n"); fprintf (fd, "\n"); fprintf (fd, "// override target voltage (x10) by uncommenting and providing a value\n"); fprintf (fd, "//#define BOARD_VOLTAGE 50\n"); fprintf (fd, "\n"); fprintf (fd, "// override baudrate by providing a value\n"); if !isempty(baudrate) fprintf (fd, "#define ARDUINO_BAUDRATE %d\n", baudrate); else fprintf (fd, "//#define ARDUINO_BAUDRATE %d\n", def_baudrate); endif fprintf (fd, "\n"); fprintf (fd, "// builtin library support\n"); idx = find (cellfun(@(x) strcmpi(x, "SPI"), builtinlibs), 1); if !isempty(idx) fprintf (fd, "#define USE_SPI\n"); else fprintf (fd, "//#define USE_SPI\n"); endif idx = find (cellfun(@(x) strcmpi(x, "I2C"), builtinlibs), 1); if !isempty(idx) fprintf (fd, "#define USE_I2C\n"); else fprintf (fd, "//#define USE_I2C\n"); endif idx = find (cellfun(@(x) strcmpi(x, "Servo"), builtinlibs), 1); if !isempty(idx) fprintf (fd, "#define USE_SERVO\n"); else fprintf (fd, "//#define USE_SERVO\n"); endif idx = find (cellfun(@(x) strcmpi(x, "ShiftRegister"), builtinlibs), 1); if !isempty(idx) fprintf (fd, "#define USE_SHIFTREG\n"); else fprintf (fd, "//#define USE_SHIFTREG\n"); endif idx = find (cellfun(@(x) strcmpi(x, "RotaryEncoder"), builtinlibs), 1); if !isempty(idx) fprintf (fd, "#define USE_ROTARYENCODER\n"); else fprintf (fd, "//#define USE_ROTARYENCODER\n"); endif idx = find (cellfun(@(x) strcmpi(x, "Ultrasonic"), builtinlibs), 1); if !isempty(idx) fprintf (fd, "#define USE_ULTRASONIC\n"); else fprintf (fd, "//#define USE_ULTRASONIC\n"); endif idx = find (cellfun(@(x) strcmpi(x, "Serial"), builtinlibs), 1); if !isempty(idx) fprintf (fd, "#define USE_SERIAL\n"); else fprintf (fd, "//#define USE_SERIAL\n"); endif # if able to do network, add network settings here fprintf (fd, "//#define OCTAVE_USE_WIFI_COMMS\n"); fprintf (fd, "#ifdef OCTAVE_USE_WIFI_COMMS\n"); fprintf (fd, " // Provide these settings for network use\n"); fprintf (fd, "# define WIFI_SECRET_SSID \"\"\n"); fprintf (fd, "# define WIFI_SECRET_PASS \"\"\n"); fprintf (fd, "# define WIFI_PORT 9500\n"); fprintf (fd, " //uncomment and define if using static IP\n"); fprintf (fd, "//# define WIFI_STATIC_IP \"192.168.0.10\"\n"); fprintf (fd, "#endif"); fclose (fd); # requested additional libs fd = fopen (fullfile (tmpdir, "octave", "addons.h"), "w+t"); fprintf(fd, "// generated from arduinosetup for addon library addidtions\n"); for i = 1:numel (libs) l = libs{i}; if !isempty (l) if !isempty (l.cppheaderfile) copyfile (l.cppheaderfile, fullfile(tmpdir, "octave")); [d,f,e] = fileparts (l.cppheaderfile); fprintf (fd, '#include "%s%s"\n', f,e); if !isempty (l.cppclassname) fprintf (fd, "%s addon%d(octavearduino);\n", l.cppclassname, i); endif endif if !isempty (l.cppsourcefile) copyfile (l.cppsourcefile, fullfile(tmpdir, "octave")); endif endif endfor fclose(fd); # start the arduino ide if isempty (arduinobinary) arduinobinary = __arduino_binary__ (); else arduinobinary = __arduino_binary__ (arduinobinary); endif filename = fullfile (tmpdir, "octave", "octave.ino"); cmdline = sprintf ("\"%s\" \"%s\"", arduinobinary, filename); printf ("Running %s\n", cmdline); [status, ~] = system (cmdline); retval = (status == 0); unwind_protect_cleanup confirm_recursive_rmdir (false, "local"); rmdir(tmpdir, "s"); end_unwind_protect endfunction arduino-0.12.1/inst/examples/0000755000000000000000000000000014545566645013001 5ustar00arduino-0.12.1/inst/examples/example_blink.m0000644000000000000000000000206614545566645015775 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . % blink the LED on D13 pkg load instrument-control a = arduino(); leds = getLEDTerminals(a); led = getPinsFromTerminals(a, leds{1}); unwind_protect printf("starting to blink...\n"); while (true) writeDigitalPin(a, led, 0); pause(0.5); writeDigitalPin(a, led, 1); pause(0.5); endwhile unwind_protect_cleanup clear a end_unwind_protect arduino-0.12.1/inst/examples/example_i2c_eeprom.m0000644000000000000000000000536214545566645016724 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . % example using the arduino i2c % to communicate to a 24XX256 EEPROM chip connected to an uno % % Connection of arduino to EEPROM as follows: % Arduino 24XX256 eeprom (pin) % A4 - 5 % A5 - 6 % 5V - 8 % GND - 1,2,3,4 pkg load instrument-control eeprom_address = 0x50; data = "this is eeprom data"; # open the arduino a = arduino() unwind_protect [~, ~, endian] = computer (); printf("i2c terminals\n") getI2CTerminals(a) printf("i2c devices attached\n") devs = scanI2Cbus(a) idx = find(devs = eeprom_address); if isempty(idx) warning ('no EEPROM device found at address') endif printf("opening i2c...\n"); # oldstyle # i2c = i2cdev(a, eeprom_address) # new style i2c = device(a, "i2caddress", eeprom_address) printf("writing i2c...\n"); # write data to address 0x0000 write(i2c, [0 0 uint8(data)]); # read from address 0x0008, which should now be 'eeprom' write(i2c, uint8([0 8])); val = read(i2c, 6); printf("reading from 0x0008 = expecting 'eeprom', and got '%s'\n", char(val)) # demo read/write register val = readRegister(i2c, 0, 2, 'uint16'); expected = [typecast(data(1:2),'uint16'),typecast(data(3:4), 'uint16')]; # since default to msb, result will be swapped if we are low endian if endian == 'L' expected = swapbytes(expected); endif printf("reading as reg from 0x0000 = expecting %X %X, and got '%X %X'\n", expected(1), expected(2), val(1), val(2)) # 2nd page write(i2c, [1 0 0 1 0 2 0 3 0 4]); # read from address 0 of page # 0 1 0 2 write(i2c, uint8([1 0])); valu = read(i2c, 4); # read as register from address 0 of page 1 # 1 2 val = readRegister(i2c, 256, 2, 'uint16') # 2 3 valx = readRegister(i2c, 258, 2, 'uint16') # 0 2 0 3 write(i2c, uint8([1 2])); valux = read(i2c, 4) # write page 1, address 2 - 4 writeRegister(i2c, 258, [8 9], 'uint16') # 0 8 0 9 write(i2c, uint8([1 2])); valux = read(i2c, 4) # 8 9 valx = readRegister(i2c, 258, 2, 'uint16') clear i2c unwind_protect_cleanup clear a end_unwind_protect arduino-0.12.1/inst/examples/example_i2c_tempsensor.m0000644000000000000000000000636614545566645017641 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . % example using the arduino i2c to communicate to a Si7021 via a % sparkfun SparkFun Humidity and Temperature Sensor Breakout board % https://www.sparkfun.com/products/13763 % % Conection of arduino to breakout board as follows: % Arduino breakoutboard (pin) (name depending on rev of board) % A4 - 3 (DA or SDA) % A5 - 4 (CL or SCL) % 3V3 - 2 (+ or 3V3) % GND - 1 (- or GND) temp_address = 0x40; # open the arduino a = arduino () unwind_protect printf ("i2c terminals\n") getI2CTerminals (a) printf ("i2c devices attached\n") devs = scanI2Cbus (a) idx = find (devs = temp_address); if isempty (idx) warning ('no Si7021 device found at address') endif printf ("opening i2c...\n"); #old style #i2c = i2cdev (a, temp_address) # new style i2c = device (a, "i2caddress", temp_address) SENSOR_ID_1 = [ hex2dec("FA") hex2dec("F0") ]; SENSOR_ID_2 = [ hex2dec("FC") hex2dec("C9") ]; printf ("query device...\n"); write (i2c, SENSOR_ID_1); id1 = read(i2c, 1); write (i2c, SENSOR_ID_2); id2 = read(i2c, 1); printf ("Sensor ID: %02X%02X\n", id1, id2) printf ("Sensor Type: "); if id2 == hex2dec("15") printf ("Si7021\n"); elseif id2 == hex2dec("14") printf ("Si7020\n"); elseif id2 == hex2dec("0D") printf ("Si7013\n"); elseif id2 == hex2dec("32") printf ("HTU21D\n"); else error ("unknown sensor type of %d found", id2); endif SENSOR_VERSION = [ hex2dec("84") hex2dec("B8") ]; write (i2c, SENSOR_VERSION); ver = read(i2c, 1); printf ("F/W Version: "); if ver == hex2dec("FF") printf ("Version: 1.0\n"); elseif ver == hex2dec("20") printf ("Version: 2.0\n"); else printf ("Version: %f\n", double(ver)/10.0); endif TEMP_MEASURE_NOHOLD = hex2dec("F3"); HUMIDITY_MEASURE_NOHOLD = hex2dec("F5"); % write command to get temp write (i2c, uint8([TEMP_MEASURE_NOHOLD])); pause (0.02); data = read (i2c, 3); value = uint16(data(1))*256 + uint16(data(2)); value = bitand (value, hex2dec("FFFC")); temp_Code = double(value); C = (175.72*temp_Code/65536)-46.85; F = (C * 1.8) +32.0; printf ("temperature read %f C (%f F)\n", C, F); % write command to get rel humidity write (i2c, uint8([HUMIDITY_MEASURE_NOHOLD])); pause (0.02); data = read (i2c, 3); value = uint16(data(1))*256 + uint16(data(2)); value = bitand (value, hex2dec("FFFC")); humidity_Code = double(value); humidity = (125.0*humidity_Code/65536)-6; printf ("relative humidity read %f %%\n", humidity); clear i2c unwind_protect_cleanup clear a end_unwind_protect arduino-0.12.1/inst/examples/example_i2c_tempsensor_plot.m0000644000000000000000000001000114545566645020654 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . % example using the arduino i2c to communicate to a Si7021 via a % sparkfun SparkFun Humidity and Temperature Sensor Breakout board % https://www.sparkfun.com/products/13763 % % Connection of arduino to breakout board as follows: % Arduino breakoutboard (pin) (name depending on rev of board) % A4 - 3 (DA or SDA) % A5 - 4 (CL or SCL) % 3V3 - 2 (+ or 3V3) % GND - 1 (- or GND) pkg load instrument-control temp_address = 0x40; # open the arduino a = arduino(); unwind_protect % check if can find sensor devs = scanI2Cbus(a); idx = find(devs = temp_address); if isempty(idx) warning ('no Si7021 device found at address') endif # old style #i2c = i2cdev(a, temp_address); # new style i2c = device(a, "i2caddress", temp_address); SENSOR_ID_1 = [ hex2dec("FA") hex2dec("F0") ]; SENSOR_ID_2 = [ hex2dec("FC") hex2dec("C9") ]; write(i2c, SENSOR_ID_1); id1 = read(i2c, 1); write(i2c, SENSOR_ID_2); id2 = read(i2c, 1); printf("Device info ...\n"); printf (" Sensor ID: %02X%02X\n", id1, id2) printf (" Sensor Type: "); if id2 == hex2dec("15") printf("Si7021\n"); elseif id2 == hex2dec("14") printf("Si7020\n"); elseif id2 == hex2dec("0D") printf("Si7013\n"); elseif id2 == hex2dec("32") printf("HTU21D\n"); else error("unknown sensor type of %d found", id2); endif SENSOR_VERSION = [ hex2dec("84") hex2dec("B8") ]; write(i2c, SENSOR_VERSION); ver = read(i2c, 1); printf(" F/W Version: "); if ver == hex2dec("FF") printf("Version: 1.0\n"); elseif ver == hex2dec("20") printf("Version: 2.0\n"); else printf("Version: %f\n", double(ver)/10.0); endif sample_time = 1; history_size = 600; f = figure(); temp_data = zeros(1, history_size); hum_data = zeros(1, history_size); ax1 = subplot(2,1,1); tp = plot(ax1, temp_data); set(tp,'linewidth', 2, 'linestyle', '-', 'color', 'r'); title(ax1, "Temperature"); ylim(ax1, [0 40.0]); xlim(ax1, [1 history_size]); ylabel(ax1, "deg C"); xlabel(ax1, "history"); grid on; ax2 = subplot(2,1,2); hp = plot(ax2, hum_data); set(hp,'linewidth', 2, 'linestyle', '-', 'color', 'b'); title(ax2,"Relative Humidity"); ylim(ax2,[0 100.0]); xlim(ax2,[1 history_size]); ylabel(ax2,"%"); xlabel(ax2,"history"); grid on; TEMP_MEASURE_NOHOLD = hex2dec("F3"); HUMIDITY_MEASURE_NOHOLD = hex2dec("F5"); while(true) % write command to get temp write(i2c, uint8([TEMP_MEASURE_NOHOLD])); pause(0.02); data = read(i2c, 3); value = uint16(data(1))*256 + uint16(data(2)); value = bitand(value, hex2dec("FFFC")); temp_Code = double(value); C = (175.72*temp_Code/65536)-46.85; temp_data(2:history_size) = temp_data(1:history_size-1); temp_data(1) = C; set(tp,'ydata',temp_data); drawnow; % write command to get rel humidity write(i2c, uint8([HUMIDITY_MEASURE_NOHOLD])); pause(0.02); data = read(i2c, 3); value = uint16(data(1))*256 + uint16(data(2)); value = bitand(value, hex2dec("FFFC")); humidity_Code = double(value); humidity = (125.0*humidity_Code/65536)-6; hum_data(2:history_size) = hum_data(1:history_size-1); hum_data(1) = humidity; set(hp,'ydata',hum_data); drawnow; pause(sample_time); endwhile clear i2c unwind_protect_cleanup clear a end_unwind_protect arduino-0.12.1/inst/examples/example_lcd_plugin.m0000644000000000000000000000250014545566645017007 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . # test LCD plugin using the Arduini LinkSprite16x2 LCD LCD Keypad shield # get arduino a = arduino(); # check have the lcd addon programmed havelcd = sum(index(a.libraries, 'examplelcd/lcd')) > 0; if !havelcd error ('no LCD addon found - install it with arduinosetup'); endif # create lcd object lcd = addon(a, "examplelcd/lcd", "d8", "d9", "d4", "d5", "d6", "d7") # loop, displaying date and time on LCD while(true) gotoLCD(lcd, 0, 0); printLCD(lcd, datestr (date, "dd mmm yyyy")); t = localtime(time); gotoLCD(lcd, 0, 1); printLCD(lcd, sprintf("%02d:%02d:%02d", t.hour, t.min, t.sec)) pause(1); endwhile arduino-0.12.1/inst/examples/example_shiftreg_595.m0000644000000000000000000000251514545566645017112 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . # example using a 74HC595 shift register # breakout board https://www.sparkfun.com/products/10680 # arduino shiftRegister (sparkfun breakout) # d2 14 io (ser_in) # d3 11 clk (clock) # d4 12 latch (l_clk) # d5 10 reset (/reset) # 5V 16 vcc (Vcc) # gnd 8 gnd (Gnd) # gnd 13 oe (oe) a = arduino("","", 'Libraries', { "ShiftRegister" }) reg = shiftRegister(a, '74HC595', 'd2', 'd3', 'd4', 'd5'); reset(reg); val = uint8(1) while(true) write(reg, val); pause(1); val = val + uint8(1) endwhile arduino-0.12.1/inst/examples/example_spi_mcp3002.m0000644000000000000000000000412614545566645016634 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . ## test program for octave - arduino - mcp3002 10 bit ADC (spi) # Assuming connections of # Arduino MCP3002 # D10 - 1 (CS) # D11 - 5 (DI) # D12 - 6 (DO) # D13 - 7 (CLK) # VCC - 8 (VDD) # GND - 4 (VSS) # 2 (CH0) - chan 0 input # 3 (CH1) - chan 1 input unwind_protect ar = arduino(); # talk to the mpc3002 via spi - SS = D10 on uno # set msb mode #spi = spidev(ar, "d10") spi = device(ar, "spichipselectpin", "d10") # command (bits) in MSB mode to device # [START SGL ODN MSBF X X X X] [ X X X X X X X X ] # 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 # [chan 0 ] MSB # data back # X X X X X 0 D D D D D D D D D D printf("reading ADC @ 1 Hz...\n"); # skip first reading v = writeRead(spi, [ hex2dec("DF") hex2dec("FF") ]); while (true) pause(1); # chan 0 v = writeRead(spi, [ hex2dec("DF") hex2dec("FF") ]); adc = bitand (uint16(v(1))*256 + uint16(v(2)), hex2dec('3FF')); volts = double(adc) * 5.0 / 1023.0; printf("ch0 = 0x%04X (adc) %f (volts)\n", adc, volts) # chan 1 v = writeRead(spi, [ hex2dec("EF") hex2dec("FF") ]); adc = bitand (uint16(v(1))*256 + uint16(v(2)), hex2dec('3FF')); volts = double(adc) * 5.0 / 1023.0; printf("ch1 = 0x%04X (adc) %f (volts)\n", adc, volts) endwhile unwind_protect_cleanup clear ar end_unwind_protect arduino-0.12.1/inst/examples/example_sweep_servo.m0000644000000000000000000000257614545566645017245 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . % example control servo on D9 % scans servo between min - max position a = arduino(); unwind_protect # hobby servo with puslses between 1ms - 2 ms s = servo (a, 'd9', 'MinPulseDuration', 1e-3, 'MaxPulseDuration', 2e-3) # go mid position writePosition (s, .5); # loop, slowly going between min - max pos speed = 0.02; pauseval = .05; printf ("scanning ...\n"); while (true) pos = readPosition (s); pos = pos + speed; if(pos > 1) pos = 1; speed = -speed; endif if(pos < 0) pos = 0; speed = -speed; endif writePosition (s, pos); pause (pauseval); endwhile unwind_protect_cleanup clear a end_unwind_protect arduino-0.12.1/inst/isarduino.m0000644000000000000000000000264714545566645013347 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} isarduino (@var{obj}) ## Check if input value is an arduino object ## ## Function is essentially just a call of ## @code { ## retval = isa(obj, "arduino"); ## } ## ## @subsubheading Inputs ## @var{obj} - The object to check ## ## @subsubheading Outputs ## @var{retval} is true, if obj is an arduino object, false otherwise. ## ## @seealso{arduino} ## @end deftypefn function retval = isarduino (obj) retval = false; if nargin > 0 && isa(obj, "arduino") retval = true; endif endfunction %!test %! a = arduino(); %! assert(isarduino(a), true) %!assert(isarduino(0), false) %!assert(isarduino({}), false) %!assert(isarduino([]), false) %!assert(isarduino(), false) arduino-0.12.1/inst/listArduinoLibraries.m0000644000000000000000000000557314545566645015505 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} listArduinoLibraries () ## @deftypefnx {} {@var{retval} =} listArduinoLibraries (@var{libtypes}) ## Retrieve list of all known arduino library modules that are available. ## ## @subsubheading Inputs ## @var{libtypes} - optional specifier for type of libraries to list. ## ## Options are: ## @table @asis ## @item all ## List core and addons ## @item core ## List core only libraries ## @item addons ## List addons only ## @end table ## When no libtypes is specified, all libraries are shown. ## ## @subsubheading Outputs ## @var{retval} is an cell array of string library names that are ## available for programming to the arduino. ## ## @seealso{arduino, arduinosetup} ## @end deftypefn function retval = listArduinoLibraries (libtypes) retval = {}; if nargin == 0 libtypes = "all"; elseif ! ischar(libtypes) error ("Expected libtypes to be a string") endif if ! (strcmpi(libtypes, "all") || strcmpi(libtypes, "addons") || strcmpi(libtypes, "core")) error ("Invalid libtypes value '%s'", libtypes) endif # hardcoded libraries if strcmpi(libtypes, "all") || strcmpi(libtypes, "core") retval{end+1} = 'I2C'; retval{end+1} = 'Servo'; retval{end+1} = 'SPI'; retval{end+1} = 'ShiftRegister'; retval{end+1} = 'RotaryEncoder'; retval{end+1} = 'Ultrasonic'; retval{end+1} = 'Serial'; endif # add ons if strcmpi(libtypes, "all") || strcmpi(libtypes, "addons") addonfiles = __addons__ (); for i = 1:numel (addonfiles) retval{end+1} = addonfiles{i}.libraryname; endfor endif endfunction %!test %! libs = listArduinoLibraries (); %! assert (!isempty (libs)) %! assert (! isempty (find(strcmp(libs, 'SPI')))); %! assert (isempty (find(strcmp(libs, 'unknown')))); %!test %! deflibs = listArduinoLibraries (); %! alllibs = listArduinoLibraries ("all"); %! corelibs = listArduinoLibraries ("core"); %! addonlibs = listArduinoLibraries ("addons"); %! assert(numel(alllibs) == (numel(corelibs) + numel(addonlibs))) %! assert(numel(alllibs) == numel(deflibs)) %!error listArduinoLibraries(1) %!error listArduinoLibraries("invalid") arduino-0.12.1/inst/private/0000755000000000000000000000000014545566645012635 5ustar00arduino-0.12.1/inst/private/__addons__.m0000644000000000000000000000740114545566645015061 0ustar00## Copyright (C) 2018-2022 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} __addons__ () ## Private function to get information aabout all user ## plugins ## @end deftypefn function addonfiles = __addons__ () addonfiles = {}; addonpathfix = fileparts (mfilename ('fullpath')); # how can we look for +arduinioaddons in the load path # genpath and dir_in_loadpath wont do it, so have to do it the hard way loadpaths = strsplit (path (), pathsep); addondirs = {}; for i = 1:numel (loadpaths) checkpath = fullfile (loadpaths{i}, "+arduinoioaddons"); if exist (checkpath, "dir") addondirs{end+1} = checkpath; endif endfor # we expect <+arduinoioaddons>/+AddonFolderName/ for i=1:numel (addondirs) files = dir (addondirs{i}); for j = 1:numel (files) if files(j).isdir && files(j).name(1) != '.' searchname = fullfile (addondirs{i}, files(j).name, "*.m"); f1 = files (j).name; if f1(1) == "+" f1 = f1(2:end); endif files2 = dir (searchname); folder = fileparts(searchname); for k = 1:numel (files2) finfo = {}; [d2,f2,e2] = fileparts (files2(k).name); classname = sprintf ("arduinoioaddons.%s.%s", f1, f2); if is_arduino_addon_class(classname) z = eval(sprintf ("%s.AddonInfo('%s')", classname, classname)); z.scriptfile = fullfile (folder, files2(k).name); # set absolute filenames if not if !is_absolute_filename(z.cppheaderfile) z.cppheaderfile = fullfile(folder, z.cppheaderfile); endif if !is_absolute_filename(z.cppsourcefile) z.cppsourcefile = fullfile(folder, z.cppsourcefile); endif # paths are wrong in octave < 6.0 as mfilename isnt giving us a # correct path from within the class so for now, fixing here z.cppheaderfile = strrep (z.cppheaderfile, addonpathfix, folder); z.cppsourcefile = strrep (z.cppsourcefile, addonpathfix, folder); addonfiles{end+1} = z; endif endfor endif endfor endfor endfunction function retval = is_arduino_addon_class(classname) try classinfo = meta.class.fromName(classname); if !isempty(classinfo) # base class should have AddonInfo inhirected from arduinoio.LibraryBase idx = find( cellfun(@(x) strcmpi(x.Name, "AddonInfo"), classinfo.Methods), 1); if !isempty(idx) if size(classinfo.SuperClassList) > 0 idx = find( cellfun(@(x) strcmpi(x.Name, "arduinoio.LibraryBase"), classinfo.SuperClassList), 1); retval = !isempty(idx); if retval == false idx = cellfun(@(x) (is_arduino_addon_class(x.Name) == true), classinfo.SuperClassList); retval = !isempty(idx); endif else retval = false; endif else retval = false; endif else retval = false; endif catch retval = false; #warning ("addon: Ignoring %s", lasterror.message) end_try_catch endfunction arduino-0.12.1/inst/private/__arduino_binary__.m0000644000000000000000000001052314545566645016615 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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. see ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} __arduino__binary__ (}) ## @deftypefnx {} {@var{retval} =} __arduino__binary__ (@var{newpath}) ## Private function to set arduino path ## @seealso{arduinosetup} ## @end deftypefn function retval = __arduino_binary__ (newarduinopath) persistent arduino_binary = ""; if nargin == 0 if isempty(arduino_binary) arduino_binary = find_arduino_binary (); endif else % trying to set the path ? arduino_binary = newarduinopath; setpref('arduino', 'arduino_binary', arduino_binary); endif retval = arduino_binary; endfunction function arduino_binary = find_arduino_binary () # use arduino_debug.exe in windoze ? binary_name = "arduino"; arduino_binary = ""; have_prefs = false; binary = getpref("arduino", "arduino_binary", ""); if !isempty(binary) have_prefs = true; t = file_in_path (getenv ("PATH"), binary); if !isempty(t) arduino_binary = t; endif endif if (isunix ()) binaries = strcat (binary_name, {"", ".exe"}); else binaries = strcat (binary_name, {".exe"}); endif n = 0; while (n < numel (binaries) && isempty (arduino_binary)) arduino_binary = file_in_path (getenv ("PATH"), binaries{++n}); endwhile % if a pc, and have the winqueryreg function, try find the path if isempty(arduino_binary) && ispc () if exist('winqueryreg') == 5 try arduino_binary = winqueryreg("HKLM", 'SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\arduino.exe'); end_try_catch if isempty(arduino_binary) # try win32 registry try arduino_binary = fullfile(winqueryreg("HKLM", 'SOFTWARE\WOW6432Node\Arduino', 'install_dir'), 'arduino.exe'); end_try_catch endif endif if isempty(arduino_binary) trypath = "C:\\Program Files (x86)\\Arduino\\arduino.exe"; if exist (trypath, "file") arduino_binary = trypath; endif endif if isempty(arduino_binary) trypath = fullfile (getenv ("LOCALAPPDATA"), "Programs", "Arduino IDE", "Arduino IDE.exe"); if exist (trypath, "file") arduino_binary = trypath; endif endif if isempty(arduino_binary) trypath = fullfile (getenv ("PROGRAMFILES"), "Arduino IDE", "Arduino IDE.exe"); if exist (trypath, "file") arduino_binary = trypath; endif endif endif % look for arduino prefs file if isempty (arduino_binary) if ispc () prefsfile = fullfile (getenv ("LOCALAPPDATA"), "Arduino15", "preferences.txt"); else prefsfile = fullfile (getenv ("HOME"), ".arduino15", "preferences.txt"); endif fd = fopen (prefsfile, "rt"); if fd != -1 try trypaths = {}; while ! feof (fd) l = fgetl (fd); str = regexp (l, "last\.ide\.(?\\d.*)\.hardwarepath=(?.*)$", "names"); if ! isempty (str) trypaths{end+1} = str; endif endwhile if !isempty (trypaths) % sort so will try newest ver first [~, sortidx] = sort(arrayfun( @(x) x{1}.version, trypaths, 'uniformoutput', false), 'descend'); for idx = 1:length(sortidx) if isempty (arduino_binary) [trypath,~,~] = fileparts (trypaths{idx}.path); n = 0; while (n < numel (binaries) && isempty (arduino_binary)) arduino_binary = file_in_path (trypath, binaries{++n}); endwhile endif endfor endif end_try_catch fclose (fd); endif endif if isempty(arduino_binary) error ("__arduino_binary__: can not find the arduino binary"); elseif !have_prefs setpref('arduino', 'arduino_binary', arduino_binary); endif endfunction arduino-0.12.1/inst/scanForArduinos.m0000644000000000000000000001377014545566645014451 0ustar00## Copyright (C) 2018-2019 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} scanForArduinos () ## @deftypefnx {} {@var{retval} =} scanForArduinos (@var{maxCount}) ## @deftypefnx {} {@var{retval} =} scanForArduinos (@var{"debug"}) ## @deftypefnx {} {@var{retval} =} scanForArduinos (@var{maxCount}, @var{type}) ## @deftypefnx {} {@var{retval} =} scanForArduinos (@var{propertyname}, @var{propertvalue} ...) ## Scan system for programmed serial connected arduino boards. ## ## scanForArduinos will scan the system for programmed arduino boards ## and return at most @var{maxCount} of them as a cell array ## in @var{retval}. ## ## @subsubheading Inputs ## @var{maxCount} - max number of arduino boards to detect. ## if @var{maxCount} is not specified, or is a less than 1, the ## function will return as many arduino boards as it can detect. ## ## @var{type} - optional board type to match. If specified, the board ## type must match for the arduino to be added to the return list. ## ## @var{"debug"} - if single input parameter is "debug", the ## scanForArduinos will display debug information as it scans ## all available ports for arduinos. ## ## @var{propertyname}, @var{propertyvalue} - property name/value pairs to match search with. ## @table @asis ## @item 'BaudRate' ## Numeric BaudRate to use when trying to scan for arduinos. ## @item 'MaxCount' ## Max number of arduinos to scan for. ## @item 'BoardType' ## Boardtype to match. ## @item 'Debug' ## Logical flag for debug mode. ## @end table ## ## @subsubheading Outputs ## @var{retval} structure cell array of matching detected arduino boards. ## ## Each cell value of the cell array will contain a structure with values of: ## @table @asis ## @item port ## the serial port the arduino is connected to ## @item board ## the board type of the arduino ## @end table ## ## @seealso{arduino} ## @end deftypefn function arduinos = scanForArduinos (varargin) # maxCount, typestr arduinos = {}; debug_flag = false; maxCount = 0; typestr = ""; baudrate = []; if nargin == 1 typestr = ""; if ischar(varargin{1}) if strcmp(varargin{1}, "debug") debug_flag = 1; else error ("scanForArduinos: invalid argument"); endif elseif isnumeric(varargin{1}) maxCount = int32(varargin{1}); else error ("scanForArduinos: invalid argument"); endif elseif nargin == 2 && isnumeric(varargin{1}) && ischar(varargin{2}) # maxCount and boardtype maxCount = int32(varargin{1}); typestr = varargin{2}; elseif nargin >= 2 # properties if mod (nargin, 2) != 0 error ("scanForArduins: expected property name, value pairs"); endif if !iscellstr (varargin (1:2:nargin)) error ("scanForArduinos: expected property names to be strings"); endif for i = 1:2:nargin propname = tolower (varargin{i}); propvalue = varargin{i+1}; if strcmp (propname,"debug") if propvalue debug_flag = 1; else debug_flag = 0; endif endif if strcmp (propname,"boardtype") boardstr = propvalue; endif if strcmp (propname,"baudrate") baudrate = propvalue; endif if strcmp (propname,"maxcount") maxCount = propvalue; endif endfor endif if ! isnumeric (maxCount) || maxCount < 0 error ("scanForArduinos expected maxCount to be a number"); endif if ! ischar (typestr) && !isempty (typestr) error ("scanForArduinos expected typestr to be a board type"); elseif ischar (typestr) typestr = tolower (typestr); else typestr = ""; endif if isempty(baudrate) baudrate = 9600; if !isempty(typestr) # get default baudrate for baud try c = arduinoio.getBoardConfig(typestr); baudrate = c.baudrate; catch err error ("scanForArduinos: unknown board type"); end_try_catch endif endif if ! isnumeric (baudrate) || baudrate < 1200 error ("scanForArduinos expected baudrate to be a number >= 1200"); endif # get list of serial ports to try ports = serialportlist (); for i = 1:numel (ports) try s = {}; unwind_protect portname = ports{i}; if debug_flag printf("* trying comport %s\n", portname); endif s = arduino(portname, "", "Debug", debug_flag, "BaudRate", baudrate, "_scan_only", 1); if isempty (typestr) || strcmpi(s.board, typestr) info = {}; info.port = portname; info.board = s.board; arduinos{end+1} = info; if debug_flag printf(" ** found board %s\n", info.board); endif if numel (arduinos) == maxCount break; endif endif unwind_protect_cleanup if !isempty (s) delete(s); endif end_unwind_protect catch err % do nothing if debug_flag printf(" ** %s\n", err.message); endif end_try_catch endfor endfunction %!test %! # assuming that to test, we have at least one board available %! arduinos = scanForArduinos(1); %! assert(numel(arduinos), 1); %! assert(!isempty(arduinos{1}.port)) %! assert(!isempty(arduinos{1}.board)) %!test %! a = scanForArduinos("BaudRate", 115200, "BoardType", "Uno"); %!error scanForArduinos(1, "madeuparduinoname"); arduino-0.12.1/inst/scanI2Cbus.m0000644000000000000000000000432114545566645013275 0ustar00## Copyright (C) 2018-2019 John Donoghue ## ## 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 ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} scanI2Cbus (@var{ar}) ## @deftypefnx {} {@var{retval} =} scanI2Cbus (@var{ar}, @var{bus}) ## Scan arduino for devices on the I2C bus. ## ## @subsubheading Inputs ## @var{ar} - arduino object connected to a arduino board. ## ## @var{bus} - bus number to scan I2C devices, when multiple buses are available. ## If the bus is not specified, it will default to 0. ## ## @subsubheading Outputs ## @var{retval} - cell array of addresses as strings in format of "0xXX". ## ## @subsubheading Example ## @example ## @code { ## # create arduino connection. ## ar = arduino(); ## # scan for devices on the I2C bus ## scanI2Cbus (ar) ## # output is each detected i2c address as a string ## ans = ## @{ ## [1,1] = 0x50 ## @} ## } ## @end example ## ## @seealso{arduino, i2cdev, checkI2CAddress} ## @end deftypefn function addr = scanI2Cbus (ar, bus) addr = {}; if nargin < 1 || nargin > 2 print_usage (); endif if nargin == 1 bus = 0; elseif !isnumeric (bus) || bus < 0 || bus > 1 error ('scanI2Cbus: expected bus to be numeric and 0 or 1'); endif if (!isa (ar, "arduino")) error ("scanI2Cbus: expects arduino object as 1st argument"); endif # TODO: configure SPI pins if not already done?? # scan each address, and add any found to cell array for i = 3:126 if checkI2CAddress (ar, i, bus) addr{end+1} = [ "0x" dec2hex(i, 2) ]; endif endfor endfunction %!test %! ar = arduino(); %! assert(!isempty(ar)); %! scanI2Cbus(ar); arduino-0.12.1/inst/sensors/0000755000000000000000000000000014545566645012657 5ustar00arduino-0.12.1/inst/sensors/bme280.m0000644000000000000000000003666014545566645014045 0ustar00## Copyright (C) 2022 John Donoghue ## ## Conversion routines based on code from the BME280 datasheet ## revision 1.6, Document number BST-BME280-DS002-15. ## ## 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 ## . classdef bme280 < handle ## -*- texinfo -*- ## @deftypefn {} {} bme280 ## BME280 pressure, temperature and humidity sensor ## @end deftypefn ## ## @subheading Methods ## @deftypefn {} {@var{obj} =} bme280(@var{arObj}) ## @deftypefnx {} {@var{obj} =} bme280(@var{arObj}, @var{propertyname, propertyvalue} ....) ## Constructor to create BME280 sensor ## @subsubheading Inputs ## @var{arObj} - the arduino parent object ## ## @var{propertyname, propertyvalue} - optional property name, value pairs. ## Current known properties are: ## Current properties are: ## @table @asis ## @item I2CAddress ## I2C address of the sensor (default 0x40) ## @item Bus ## I2C bus - 0 or 1 (default 0) ## @end table ## ## @subsubheading Outputs ## @var{obj} - created object ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## sensor = bme280(a) ## } ## @end example ## @end deftypefn ## ## @deftypefn {} {[@var{C}, @var{timestamp}] =} readTemperature(@var{obj}) ## Read the temperature ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{C} - read temperature in deg C. ## ## @var{timestamp} - timestamp when read ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## s = bme280(a) ## # get temp ## temp = s.readTemperature ## } ## @end example ## @seealso{bme280} ## @end deftypefn ## ## @deftypefn {} {[@var{relH}, @var{timestamp}] =} readHumidity(@var{obj}) ## Read the relative humidity ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{relH} - relative humidity as a percentage (0 - 100.0) ## ## @var{timestamp} - timestamp when read ## @end deftypefn ## ## @deftypefn {} {[@var{P}, @var{timestamp}] =} readPressure(@var{obj}) ## Read the pressure ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{P} - pressure reading from sensor. ## ## @var{timestamp} - timestamp when read ## @end deftypefn ## ## @deftypefn {} {[@var{readings}, @var{overrun}] =} read(@var{obj}) ## @deftypefnx {} {[@var{P}, @var{H}, @var{C}, @var{timestamp}, @var{overrun}] =} read(@var{obj}) ## Read the sensor data ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{P} - pressure reading from sensor. ## ## @var{H} - humidity reading from sensor. ## ## @var{C} - temperature reading from sensor. ## ## @var{timestamp} - timestamp when read ## ## @var{overrun} - overrun flag. ## ## @var{readings} - table structure with fields for Timestamp, Pressure, Temperature and Humidity. ## @end deftypefn ## ## @deftypefn {} {@var{inf} =} info(@var{obj}) ## Read the sensor info ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{inf} - structure containing the sensor information. ## ## Structure fields are: ## @table @asis ## @item Version ## Chip firmware version ## @item SensorId ## sensor id value ## @item Type ## sensor type 'bme280' ## @item Status ## Status value read from sensor ## @end table ## ## @end deftypefn ## ## @deftypefn {} {} flush(@var{obj}) ## Flush sensor data ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## None ## @end deftypefn ## ## @deftypefn {} {} release(@var{obj}) ## Release the resources of the sensor ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## None ## @end deftypefn properties(Access = private, constant = true) BME280_REG_DIG_T1 = 0x88; BME280_REG_DIG_T2 = 0x8A; BME280_REG_DIG_T3 = 0x8C; BME280_REG_DIG_P1 = 0x8E; BME280_REG_DIG_P2 = 0x90; BME280_REG_DIG_P3 = 0x92; BME280_REG_DIG_P4 = 0x94; BME280_REG_DIG_P5 = 0x96; BME280_REG_DIG_P6 = 0x98; BME280_REG_DIG_P7 = 0x9A; BME280_REG_DIG_P8 = 0x9C; BME280_REG_DIG_P9 = 0x9E; BME280_REG_DIG_H1 = 0xA1; BME280_REG_DIG_H2 = 0xE1; BME280_REG_DIG_H3 = 0xE3; BME280_REG_DIG_H4 = 0xE4; BME280_REG_DIG_H5 = 0xE5; BME280_REG_DIG_H6 = 0xE7; BME280_REG_CHIPID = 0xD0; BME280_REG_VERSION = 0xD1; BME280_REG_SOFTRESET = 0xE0; BME280_REG_CAL26 = 0xE1; BME280_REG_CONTROLHUMID = 0xF2; BME280_REG_STATUS = 0XF3; BME280_REG_CONTROL = 0xF4; BME280_REG_CONFIG = 0xF5; BME280_REG_PRESSUREDATA = 0xF7; BME280_REG_TEMPDATA = 0xFA; BME280_REG_HUMIDDATA = 0xF; BME280_REG_DATA = 0xF7; endproperties properties(Access = private) i2c; caldata = {}; endproperties # matlab compatible properties properties (SetAccess = private) I2CAddress = ""; Bus = 0; endproperties methods # constructor function this = bme280(parentObj, varargin) if nargin < 1 || ! isarduino(parentObj) error('Expected arduino object as first parameter'); endif # parse args p = inputParser(CaseSensitive=false, FunctionName='arduinosensor.SI7021'); p.addParameter('I2CAddress', 0x77, @isnumeric); p.addParameter('Bus', 0, @isnumeric); p.parse(varargin{:}); # do we have the address ? address = p.Results.I2CAddress; bus = p.Results.Bus; #i2caddresses = scanI2Cbus(parentObj, bus); #idx = find(cellfun ( @(x) strcmp(x, sprintf("0x%02X", address)), i2caddresses)); #if isempty(idx) # error('No matching i2c address found on bus'); #endif this.i2c = device(parentObj, "i2caddress", p.Results.I2CAddress, 'Bus', bus); # init id = this.readRegisterU8(this.BME280_REG_CHIPID); if id < hex2dec("56") || id > hex2dec("60") error ("Invalid id '%X' read for sensor", id) endif # wait while chip is reading status = 1; while bitand(status, 1) == 1 pause(.1); status = this.readRegisterU8(this.BME280_REG_STATUS); endwhile this.caldata.t_fine = []; this.caldata.T1 = this.readRegisterU16(this.BME280_REG_DIG_T1); this.caldata.T2 = this.readRegisterS16(this.BME280_REG_DIG_T2); this.caldata.T3 = this.readRegisterS16(this.BME280_REG_DIG_T3); this.caldata.P1 = this.readRegisterU16(this.BME280_REG_DIG_P1); this.caldata.P2 = this.readRegisterS16(this.BME280_REG_DIG_P2); this.caldata.P3 = this.readRegisterS16(this.BME280_REG_DIG_P3); this.caldata.P4 = this.readRegisterS16(this.BME280_REG_DIG_P4); this.caldata.P5 = this.readRegisterS16(this.BME280_REG_DIG_P5); this.caldata.P6 = this.readRegisterS16(this.BME280_REG_DIG_P6); this.caldata.P7 = this.readRegisterS16(this.BME280_REG_DIG_P7); this.caldata.P8 = this.readRegisterS16(this.BME280_REG_DIG_P8); this.caldata.P9 = this.readRegisterS16(this.BME280_REG_DIG_P9); this.caldata.H1 = this.readRegisterU8(this.BME280_REG_DIG_H1); this.caldata.H2 = this.readRegisterU16(this.BME280_REG_DIG_H2); this.caldata.H3 = this.readRegisterU8(this.BME280_REG_DIG_H3); a = this.readRegisterU8(this.BME280_REG_DIG_H4); b = this.readRegisterU8(this.BME280_REG_DIG_H4+1); this.caldata.H4 = uint16(a)*16 + bitand(uint16(b), uint16(0x0f)); a = this.readRegisterU8(this.BME280_REG_DIG_H5); b = this.readRegisterU8(this.BME280_REG_DIG_H5+1); this.caldata.H5 = uint16(b*16) + bitshift(uint16(a), -4); this.caldata.H6 = this.readRegisterS8(this.BME280_REG_DIG_H6); # ensure in sleep mode this.writeRegister(this.BME280_REG_CONTROL, uint8([0])); # start sensors # sample rate 1 this.writeRegister(this.BME280_REG_CONTROLHUMID, uint8([0x01])); this.writeRegister(this.BME280_REG_CONFIG, uint8([0xE1])); # 101 101 11 this.writeRegister(this.BME280_REG_CONTROL, uint8([0xB7])); endfunction function inf = info (this) inf = {}; inf.Type = "bme280"; inf.SensorId = this.readRegisterU8(this.BME280_REG_CHIPID); inf.Version = this.readRegisterU8(this.BME280_REG_VERSION); inf.Status = this.readRegisterU8(this.BME280_REG_STATUS); endfunction function [C, timestamp] = readTemperature (this) data = readData(this); value = bitshift(int32(data(4)), 12) + bitshift(int32(data(5)), 4) + bitshift(int32(data(6)), -4); timestamp = time(); C = calcTemperature(this, value); endfunction function [H, timestamp] = readHumidity(this) data = readData(this); if isempty(this.caldata.t_fine) value = bitshift(int32(data(4)), 12) + bitshift(int32(data(5)), 4) + bitshift(int32(data(6)), -4); calcTemperature(this, value); endif value = bitshift(int32(data(7)), 8) + int32(data(8)); timestamp = time(); H = calcHumidity(this, value); endfunction function [P, timestamp] = readPressure(this) data = readData(this); if isempty(this.caldata.t_fine) value = bitshift(int32(data(4)), 12) + bitshift(int32(data(5)), 4) + bitshift(int32(data(6)), -4); calcTemperature(this, value); endif value = bitshift(int32(data(1)), 12) + bitshift(int32(data(2)), 4) + bitshift(int32(data(3)), -4); timestamp = time(); P = calcPressure(this, value); endfunction function varargout = read(this) data = readData(this); timestamp = time(); value = bitshift(int32(data(4)), 12) + bitshift(int32(data(5)), 4) + bitshift(int32(data(6)), -4); C = calcTemperature(this, value); value = bitshift(int32(data(7)), 8) + int32(data(8)); H = calcHumidity(this, value); value = bitshift(int32(data(1)), 12) + bitshift(int32(data(2)), 4) + bitshift(int32(data(3)), -4); P = calcPressure(this, value); if nargout <= 2 varargout{1} = struct('Time', timestamp, 'Temperature', C, 'Pressure', P, 'Humidity', H); if nargout > 1 varargout{2} = 0; # no overrun endif else if nargout > 0 varargout{1} = P; endif if nargout > 1 varargout{2} = H; endif if nargout > 2 varargout{3} = C; endif if nargout > 3 varargout{4} = timestamp; endif if nargout > 4 varargout{5} = 0; # overrun endif endif endfunction function flush(this) # flush currenly does nothing endfunction function disp(this) printf(" %s with properties\n", class(this)); if isobject(this.i2c) printf(" I2CAddress: %d ('0x%s')\n", this.i2c.i2caddress, num2hex(this.i2c.i2caddress)); printf(" Bus: %d\n", this.i2c.bus); else printf(" Not connected"); endif endfunction function release(this) if isobject(this.i2c) delete(this.i2c); this.i2c = []; endif endfunction function delete(this) try if isobject(this.i2c) delete(this.i2c); this.i2c = []; endif catch # do nothing end_try_catch endfunction endmethods methods (Hidden = true) function v = get.I2CAddress (this) v = sprintf("0x%02X", this.i2c.I2CAddress); endfunction function v = get.Bus (this) v = this.i2c.Bus; endfunction endmethods methods (Access = private) function C = calcTemperature(this, value) var1 = bitshift((bitshift(int32(value), -3) - bitshift(int32(this.caldata.T1), 1)) * int32(this.caldata.T2), -11); var2 = (bitshift(int32(value), -4) - int32(this.caldata.T1)); var2 = bitshift( (bitshift(var2*var2, -12) * int32(this.caldata.T3)), -14); this.caldata.t_fine = var1 + var2; T = bitshift(this.caldata.t_fine * 5 + 128, -8); C = single(T)/100.0; endfunction function H = calcHumidity(this, value) var1 = int32(this.caldata.t_fine) - 76800; a = bitshift(value, 14) - bitshift(int32(this.caldata.H4), 20) - (int32(this.caldata.H5) * var1); a = bitshift(a + 16384, -15); b = bitshift(var1 * int32(this.caldata.H6), -10) * (bitshift(var1 * int32(this.caldata.H3), -11) + 32768); b = bitshift(b, -10) + 2097152 * int32(this.caldata.H2) + 8192; b = bitshift(b, -14); var1 = a * b; a = bitshift(bitshift(var1, -15) * bitshift(var1, -15), -7); var1 = var1 - bitshift(a * int32(this.caldata.H1), -4); if var1 < 0 var1 = 0; elseif var1 > 419430400 var1 = 419430400; endif H = single(bitshift(var1, -12)) / 1024.0; endfunction function P = calcPressure(this, value) var1 = int64(this.caldata.t_fine) - 128000; var2 = var1 * var1 * int64(this.caldata.P6); var2 = int64(var2) + bitshift(var1 * int64(this.caldata.P5), 17); var2 = var2 + bitshift(int64(this.caldata.P4), 35); var1 = bitshift(var1 * var1 * int64(this.caldata.P3), -8) + bitshift(var1 * int64(this.caldata.P2), 12); var1 = bitshift((bitshift(int64(1), 47) +var1) * int64(this.caldata.P1), -33); if (var1 != 0) P = 1048576 - value; P = ((bitshift(int64(P), 31) - var2)*3125)/var1; var1 = bitshift(int64(this.caldata.P9) * bitshift(P, -13) * bitshift(P, -13), -25); var2 = bitshift(int64(this.caldata.P8) * P, -19); P = bitshift(P + var1 + var2, -8) + bitshift(int64(this.caldata.P7), 4); else P = 0; endif P = single(P) / 256.0; endfunction function data = readRegister(this, reg, sz) data = readRegister(this.i2c, reg, sz); endfunction function writeRegister(this, reg, data) writeRegister(this.i2c, reg, data); endfunction # read the data function data = readData(this) m = 1; while m == 1 status = this.readRegisterU8 (this.BME280_REG_STATUS); m = bitand(bitshift(status, -3), 1); if m == 1 pause(.1); endif endwhile data = readRegister(this, this.BME280_REG_DATA, 8); endfunction function value = readRegisterU16(this, reg) data = readRegister(this, reg, 2); value = uint16(data(2))*256 + uint16(data(1)); endfunction function value = readRegisterS16(this, reg) data = readRegister(this, reg, 2); value = uint16(data(2))*256 + uint16(data(1)); value = typecast(value, 'int16'); endfunction function value = readRegisterU8(this, reg) data = readRegister(this, reg, 1); value = uint8(data(1)); endfunction function value = readRegisterS8(this, reg) data = readRegister(this, reg, 1); value = uint8(data(1)); value = typecast(value, 'int8'); endfunction endmethods endclassdef %!error bme280(1); arduino-0.12.1/inst/sensors/bno055.m0000644000000000000000000005500014545566645014045 0ustar00## Copyright (C) 2022 John Donoghue ## ## 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 ## . classdef bno055 < handle ## -*- texinfo -*- ## @deftypefn {} {} bno055 ## BNO055 9 axis orientation sensor ## @end deftypefn ## ## @subheading Methods ## @deftypefn {} {@var{obj} =} bno055(@var{arObj}) ## @deftypefnx {} {@var{obj} =} bno055(@var{arObj}, @var{propertyname, propertyvalue} ....) ## Constructor to create BME280 sensor ## @subsubheading Inputs ## @var{arObj} - the arduino parent object ## ## @var{propertyname, propertyvalue} - optional property name, value pairs. ## Current known properties are: ## Current properties are: ## @table @asis ## @item I2CAddress ## I2C address of the sensor (default 0x40) ## @item Bus ## I2C bus - 0 or 1 (default 0) ## @item OperatingMode ## Operating mode 'ndof' or 'amg' ## @end table ## ## @subsubheading Outputs ## @var{obj} - created object ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## sensor = bno055(a) ## } ## @end example ## @end deftypefn ## ## @deftypefn {} {[@var{C}, @var{timestamp}] =} readTemperature(@var{obj}) ## Read the temperature ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{C} - read temperature in deg C. ## ## @var{timestamp} - timestamp when read ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## s = bno055(a) ## # get temp ## temp = s.readTemperature ## } ## @end example ## @seealso{bno055} ## @end deftypefn ## ## @deftypefn {} {[@var{readVal}, @var{timestamp}] =} readAcceleration(@var{obj}) ## Read the acceleration rate ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{readVal} - the 3 acceleration values ## ## @var{timestamp} - timestamp when read ## @end deftypefn ## ## @deftypefn {} {[@var{readVal}, @var{timestamp}] =} readAngularVelocity(@var{obj}) ## Read the angular velocity ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{readVal} - the 3 angular velocity values ## ## @var{timestamp} - timestamp when read ## @end deftypefn ## ## @deftypefn {} {[@var{readVal}, @var{timestamp}] =} readMagneticField(@var{obj}) ## Read the magnetic field components ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{readVal} - the 3 magnetic field values ## ## @var{timestamp} - timestamp when read ## @end deftypefn ## ## @deftypefn {} {[@var{readVal}, @var{timestamp}] =} readOrientation(@var{obj}) ## Read the oriientation components ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{readVal} - the 3 orientation values ## ## @var{timestamp} - timestamp when read ## @end deftypefn ## ## @deftypefn {} {[@var{readings}, @var{overrun}] =} read(@var{obj}) ## @deftypefnx {} {[@var{accel}, @var{gyro}, @var{mag}, @var{timestamp}, @var{overrun}] =} read(@var{obj}) ## @deftypefnx {} {[@var{accel}, @var{gyro}, @var{mag}, @var{orientation}, @var{timestamp}, @var{overrun}] =} read(@var{obj}) ## Read the sensor data ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{accel} - acceleration reading from sensor. ## ## @var{gyro} - angular acceleration reading from sensor. ## ## @var{mag} - magnetic field reading from sensor. ## ## @var{orientation} - orientation reading from sensor. ## ## @var{timestamp} - timestamp when read ## ## @var{overrun} - overrun flag. ## ## @var{readings} - table structure with fields for Timestamp, Acceleration, AngularVelocity, MagneticField, Orientation. ## @end deftypefn ## ## @deftypefn {} {@var{inf} =} readCalibrationStatus(@var{obj}) ## Read the sensor calibration status ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{status} - structure containing the calibration information. ## ## Structure fields are: ## @table @asis ## @item System ## System calibrarion ## @item Accelerometer ## Accelerometer calibration status ## @item Gyroscope ## Gyroscope calibration status ## @item Magnetometer ## Magnetometer calibration status ## @end table ## ## Values for each will be either 'uncalibrated', 'partial' or 'full'. ## ## @end deftypefn ## ## @deftypefn {} {@var{inf} =} info(@var{obj}) ## Read the sensor info ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{inf} - structure containing the sensor information. ## ## Structure fields are: ## @table @asis ## @item Version ## Software firmware version ## @item SensorId ## sensor id value ## @item Type ## sensor type 'bno055' ## @end table ## ## @end deftypefn ## ## @deftypefn {} {} flush(@var{obj}) ## Flush sensor data ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## None ## @end deftypefn ## ## @deftypefn {} {} release(@var{obj}) ## Release the resources of the sensor ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## None ## @end deftypefn properties(Access = private, constant = true) # page 0 BNO055_REG_CHIP_ID = 0x00; # 0xA0 BNO055 CHIP ID BNO055_REG_ACC_ID = 0x01; # 0xFB ACC chip ID BNO055_REG_MAG_ID = 0x02; # 0x32 MAG chip ID BNO055_REG_GYR_ID = 0x03; # 0x0F GYRO chip ID BNO055_REG_SW_REV_ID = 0x04; BNO055_REG_SW_REV_ID_L = 0x04; # SB 0x118 SW Revision ID <7:0> BNO055_REG_SW_REV_ID_M = 0x05; # SB 0x037 SW Revision ID <15:8> BNO055_REG_BL_REV_ID = 0x06; # 0x15 Bootloader Version BNO055_REG_PAGE_ID = 0x07; # 0x00 Page ID BNO055_REG_ACC_DATA_X = 0x08; BNO055_REG_ACC_DATA_X_LSB = 0x08; # 0x00 Acceleration Data X <7:0> BNO055_REG_ACC_DATA_X_MSB = 0x09; # 0x00 Acceleration Data X <15:8> BNO055_REG_ACC_DATA_Y = 0x0A; BNO055_REG_ACC_DATA_Y_LSB = 0x0A; # 0x00 Acceleration Data Y <7:0> BNO055_REG_ACC_DATA_Y_MSB = 0x0B; # 0x00 Acceleration Data Y <15:8> BNO055_REG_ACC_DATA_Z = 0x0C; BNO055_REG_ACC_DATA_Z_LSB = 0x0C; # 0x00 Acceleration Data Z <7:0> BNO055_REG_ACC_DATA_Z_MSB = 0x0D; # 0x00 Acceleration Data Z <15:8> BNO055_REG_MAG_DATA_X = 0x0E; BNO055_REG_MAG_DATA_X_LSB = 0x0E; # 0x00 Magnetometer Data X <7:0> BNO055_REG_MAG_DATA_X_MSB = 0x0F; # 0x00 Magnetometer Data X <15:8> BNO055_REG_MAG_DATA_Y = 0x10; BNO055_REG_MAG_DATA_Y_LSB = 0x10; # 0x00 Magnetometer Data Y <7:0> BNO055_REG_MAG_DATA_Y_MSB = 0x11; # 0x00 Magnetometer Data Y <15:8> BNO055_REG_MAG_DATA_Z = 0x12; BNO055_REG_MAG_DATA_Z_LSB = 0x12; # 0x00 Magnetometer Data Z <7:0> BNO055_REG_MAG_DATA_Z_MSB = 0x13; # 0x00 Magnetometer Data Z <15:8> BNO055_REG_GYR_DATA_X = 0x14; BNO055_REG_GYR_DATA_X_LSB = 0x14; # 0x00 Gyroscope Data X <7:0> BNO055_REG_GYR_DATA_X_MSB = 0x15; # 0x00 Gyroscope Data X <15:8> BNO055_REG_GYR_DATA_Y = 0x16; BNO055_REG_GYR_DATA_Y_LSB = 0x16; # 0x00 Gyroscope Data Y <7:0> BNO055_REG_GYR_DATA_Y_MSB = 0x17; # 0x00 Gyroscope Data Y <15:8> BNO055_REG_GYR_DATA_Z = 0x18; BNO055_REG_GYR_DATA_Z_LSB = 0x18; # 0x00 Gyroscope Data Z <7:0> BNO055_REG_GYR_DATA_Z_MSB = 0x19; # 0x00 Gyroscope Data Z <15:8> BNO055_REG_EUL_HEADING = 0x1A; BNO055_REG_EUL_HEADING_LSB = 0x1A; # 0x00 Heading Data <7:0> BNO055_REG_EUL_HEADING_MSB = 0x1B; # 0x00 Heading Data <15:8> BNO055_REG_EUL_ROLL = 0x1C; BNO055_REG_EUL_ROLL_LSB = 0x1C; # 0x00 Roll Data <7:0> BNO055_REG_EUL_ROLL_MSB = 0x1D; # 0x00 Roll Data <15:8> BNO055_REG_EUL_PITCH = 0x1E; BNO055_REG_EUL_PITCH_LSB = 0x1E; # 0x00 Pitch Data <7:0> BNO055_REG_EUL_PITCH_MSB = 0x1F; # 0x00 Pitch Data <15:8> BNO055_REG_QUA_DATA_W = 0x20; BNO055_REG_QUA_DATA_W_LSB = 0x20; # 0x00 Quaternion w Data <7:0> BNO055_REG_QUA_DATA_W_MSB = 0x21; # 0x00 Quaternion w Data <15:8> BNO055_REG_QUA_DATA_X = 0x22; BNO055_REG_QUA_DATA_X_LSB = 0x22; # 0x00 Quaternion x Data <7:0> BNO055_REG_QUA_DATA_X_MSB = 0x23; # 0x00 Quaternion x Data <15:8> BNO055_REG_QUA_DATA_Y = 0x24; BNO055_REG_QUA_DATA_Y_LSB = 0x24; # 0x00 Quaternion y Data <7:0> BNO055_REG_QUA_DATA_Y_MSB = 0x25; # 0x00 Quaternion y Data <15:8> BNO055_REG_QUA_DATA_Z = 0x26; BNO055_REG_QUA_DATA_Z_LSB = 0x26; # 0x00 Quaternion z Data <7:0> BNO055_REG_QUA_DATA_Z_MSB = 0x17; # 0x00 Quaternion z Data <15:8> BNO055_REG_LIA_DATA_X = 0x28; BNO055_REG_LIA_DATA_X_LSB = 0x28; # 0x00 Linear Acceleration Data X <7:0> BNO055_REG_LIA_DATA_X_MBS = 0x29; # 0x00 Linear Acceleration Data X <15:8> BNO055_REG_LIA_DATA_Y = 0x2A; BNO055_REG_LIA_DATA_Y_LSB = 0x2A; # 0x00 Linear Acceleration Data Y <7:0> BNO055_REG_LIA_DATA_Y_MBS = 0x2B; # 0x00 Linear Acceleration Data Y <15:8> BNO055_REG_LIA_DATA_Z = 0x2C; BNO055_REG_LIA_DATA_Z_LSB = 0x2C; # 0x00 Linear Acceleration Data Z <7:0> BNO055_REG_LIA_DATA_Z_MBS = 0x2D; # 0x00 Linear Acceleration Data Z <15:8> BNO055_REG_GRV_DATA_X = 0x2E; BNO055_REG_GRV_DATA_X_LSB = 0x2E; # 0x00 Gravity Vector Data X <7:0> BNO055_REG_GRV_DATA_X_MSB = 0x2F; # 0x00 Gravity Vector Data X <15:8> BNO055_REG_GRV_DATA_Y = 0x30; BNO055_REG_GRV_DATA_Y_LSB = 0x30; # 0x00 Gravity Vector Data Y <7:0> BNO055_REG_GRV_DATA_Y_MSB = 0x31; # 0x00 Gravity Vector Data Y <15:8> BNO055_REG_GRV_DATA_Z = 0x32; BNO055_REG_GRV_DATA_Z_LSB = 0x32; # 0x00 Gravity Vector Data Z <7:0> BNO055_REG_GRV_DATA_Z_MSB = 0x33; # 0x00 Gravity Vector Data Z <15:8> BNO055_REG_TEMP = 0x34; # 0x00 Temperature BNO055_REG_CALIB_STAT = 0x35; # 0x00 SYS Calib Status 0:3 GYR Calib Status 0:3 ACC Calib Status 0:3 MAG Calib Status 0:3 BNO055_REG_ST_RESULT = 0x36; # 0x0F ST_MCU ST_GYR ST_MAG ST_ACC BNO055_REG_INT_STA = 0x37; # 0x00 ACC_N M ACC_A M ACC_HI GH_G GYR_DR DY6 GYR_HIG H_RATE GYRO_A M MAG_DR DY6 ACC_BS X_DRDY6 BNO055_REG_SYS_CLK_STATUS = 0x38; # 0x00 ST_MAI N_CLK BNO055_REG_SYS_STATUS = 0x39; # 0x00 System Status Code BNO055_REG_SYS_ERR = 0x3A; # 0x00 System Error Code BNO055_REG_UNIT_SEL = 0x3B; # 0x80 ORI_Android_Windows TEMP_Unit EUL_Unit GYR_Unit ACC_Unit BNO055_REG_Reserved = 0x3C; BNO055_REG_OPR_MODE = 0x3D; # 0x10 Operation Mode <3:0> BNO055_REG_PWR_MODE = 0x3E; # 0x00 Power Mode <1:0> BNO055_REG_SYS_TRIGGER = 0x3F; # 0x00 CLK_S EL RST_IN T RST_S YS Self_Test BNO055_REG_TEMP_SOURCE = 0x40; # 0x00 TEMP_Source <1:0> BNO055_REG_AXIS_MAP_CONFIG = 0x41; # 0x24 Remapped Z axis value Remapped Y axis value Remapped X axis value BNO055_REG_AXIS_MAP_SIGN = 0x42; # 0x00 Remapped X axis sign Remapped Y axis sign Remapped Z axis sign BNO055_REG_SIC_MATRIX_LSB0 = 0x43; # 0x00 SIC_MATRIX_LSB0 BNO055_REG_SIC_MATRIX_MSB0 = 0x44; # 0x40 SIC_MATRIX_MSB0 BNO055_REG_SIC_MATRIX_LSB1 = 0x45; # 0x00 SIC_MATRIX_LSB1 BNO055_REG_SIC_MATRIX_MSB1 = 0x46; # 0x00 SIC_MATRIX_MSB1 BNO055_REG_SIC_MATRIX_LSB2 = 0x47; # 0x00 SIC_MATRIX_LSB2 BNO055_REG_SIC_MATRIX_MSB2 = 0x48; # 0x00 SIC_MATRIX_MSB2 BNO055_REG_SIC_MATRIX_LSB3 = 0x49; # 0x00 SIC_MATRIX_LSB3 BNO055_REG_SIC_MATRIX_MSB3 = 0x4A; # 0x00 SIC_MATRIX_MSB3 BNO055_REG_SIC_MATRIX_LSB4 = 0x4B; # 0x00 SIC_MATRIX_LSB4 BNO055_REG_SIC_MATRIX_MSB4 = 0x4C; # 0x40 SIC_MATRIX_MSB4 BNO055_REG_SIC_MATRIX_LSB5 = 0x4D; # 0x00 SIC_MATRIX_LSB5 BNO055_REG_SIC_MATRIX_MSB5 = 0x4E; # 0x00 SIC_MATRIX_MSB5 BNO055_REG_SIC_MATRIX_LSB6 = 0x4F; # 0x00 SIC_MATRIX_LSB6 BNO055_REG_SIC_MATRIX_MSB6 = 0x50; # 0x00 SIC_MATRIX_MSB6 BNO055_REG_SIC_MATRIX_LSB7 = 0x51; # 0x00 SIC_MATRIX_LSB7 BNO055_REG_SIC_MATRIX_MSB7 = 0x52; # 0x00 SIC_MATRIX_MSB7 BNO055_REG_SIC_MATRIX_LSB8 = 0x53; # 0x00 SIC_MATRIX_LSB8 BNO055_REG_SIC_MATRIX_MSB8 = 0x54; # 0x40 SIC_MATRIX_MSB8 BNO055_REG_ACC_OFFSET_X_LSB = 0x55; # 0x00 Accelerometer Offset X <7:0> BNO055_REG_ACC_OFFSET_X_MSB = 0x56; # 0x00 Accelerometer Offset X <15:8> BNO055_REG_ACC_OFFSET_Y_LSB = 0x57; # 0x00 Accelerometer Offset Y <7:0> BNO055_REG_ACC_OFFSET_Y_MSB = 0x58; # 0x00 Accelerometer Offset Y <15:8> BNO055_REG_ACC_OFFSET_Z_LSB = 0x59; # 0x00 Accelerometer Offset Z <7:0> BNO055_REG_ACC_OFFSET_Z_MSB = 0x5A; # 0x00 Accelerometer Offset Z <15:8> BNO055_REG_MAG_OFFSET_X_LSB = 0x5B; # 0x00 Magnetometer Offset X <7:0> BNO055_REG_MAG_OFFSET_X_MSB = 0x5C; # 0x00 Magnetometer Offset X <15:8> BNO055_REG_MAG_OFFSET_Y_LSB = 0x5D; # 0x00 Magnetometer Offset Y <7:0> BNO055_REG_MAG_OFFSET_Y_MSB = 0x5E; # 0x00 Magnetometer Offset Y <15:8> BNO055_REG_MAG_OFFSET_Z_LSB = 0x5F; # 0x00 Magnetometer Offset Z <7:0> BNO055_REG_MAG_OFFSET_Z_MSB = 0x60; # 0x00 Magnetometer Offset Z <15:8> BNO055_REG_GYR_OFFSET_X_LSB = 0x61; # 0x00 Gyroscope Offset X <7:0> BNO055_REG_GYR_OFFSET_X_MSB = 0x62; # 0x00 Gyroscope Offset X <15:8> BNO055_REG_GYR_OFFSET_Y_LSB = 0x63; # 0x00 Gyroscope Offset Y <7:0> BNO055_REG_GYR_OFFSET_Y_MSB = 0x64; # 0x00 Gyroscope Offset Y <15:8> BNO055_REG_GYR_OFFSET_Z_LSB = 0x65; # 0x00 Gyroscope Offset Z <7:0> BNO055_REG_GYR_OFFSET_Z_MSB = 0x66; # 0x00 Gyroscope Offset Z <15:8> BNO055_REG_ACC_RADIUS_LSB = 0x67; # 0x00 Accelerometer Radius BNO055_REG_ACC_RADIUS_MSB = 0x68; # 0x00 Accelerometer Radius BNO055_REG_MAG_RADIUS_LSB = 0x69; # 0xE0 Magnetometer Radius BNO055_REG_MAG_RADIUS_MSB = 0x6A; # 0x01 Magnetometer Radius endproperties properties(Access = private) i2c; caldata = {}; endproperties # matlab compatible properties properties (SetAccess = private) I2CAddress = ""; Bus = 0; endproperties properties (Access = public) OperatingMode = 'ndof'; endproperties methods # constructor function this = bno055(parentObj, varargin) if nargin < 1 || ! isarduino(parentObj) error('Expected arduino object as first parameter'); endif # parse args p = inputParser(CaseSensitive=false, FunctionName='arduinosensor.SI7021'); p.addParameter('I2CAddress', 0x29, @isnumeric); # matlab default is 0x28 p.addParameter('Bus', 0, @isnumeric); p.addParameter('OperatingMode', 'ndof', @ischar); # ndof or amg p.parse(varargin{:}); # do we have the address ? address = p.Results.I2CAddress; bus = p.Results.Bus; # Operating mode 'ndof' or 'amg' switch p.Results.OperatingMode case 'ndof' this.OperatingMode = p.Results.OperatingMode; case 'amg' this.OperatingMode = p.Results.OperatingMode; otherwise error ("Invalid operating mode"); endswitch this.i2c = device(parentObj, "i2caddress", p.Results.I2CAddress, 'Bus', bus); # verify what talking to id = this.readRegisterU8(this.BNO055_REG_CHIP_ID); if id != 0xA0 pause(1); id = this.readRegisterU8(this.BNO055_REG_CHIP_ID); endif if id != 0xA0 error ("Invalid id '%X' read for sensor", id) endif # init modes this.writeRegister(this.BNO055_REG_OPR_MODE, 0); # set into condig mode # reset this.writeRegister(this.BNO055_REG_SYS_TRIGGER, 0x20); pause(.5); id = this.readRegisterU8(this.BNO055_REG_CHIP_ID); while id != 0xA0 pause(.1); id = this.readRegisterU8(this.BNO055_REG_CHIP_ID); endwhile # normal power mode this.writeRegister(this.BNO055_REG_PWR_MODE, 0); # page 0 this.writeRegister(this.BNO055_REG_PAGE_ID, 0); this.writeRegister(this.BNO055_REG_SYS_TRIGGER, 0x00); pause(.1); if strcmp(this.OperatingMode, "ndof") # NDOF mode this.writeRegister(this.BNO055_REG_OPR_MODE, 0x0C); else # amg this.writeRegister(this.BNO055_REG_OPR_MODE, 0x07); endif pause(.2); endfunction function inf = info (this) inf = {}; inf.Type = "bno055"; inf.SensorId = this.readRegisterU8(this.BNO055_REG_CHIP_ID); inf.AccelId = this.readRegisterU8(this.BNO055_REG_ACC_ID); inf.MagId = this.readRegisterU8(this.BNO055_REG_MAG_ID); inf.GyroId = this.readRegisterU8(this.BNO055_REG_GYR_ID); inf.BootloaderRev = this.readRegisterU8(this.BNO055_REG_BL_REV_ID); inf.Version = this.readRegisterU16(this.BNO055_REG_SW_REV_ID); endfunction function [status, timestamp] = readCalibrationStatus (this) data = single(this.readRegisterU8(this.BNO055_REG_CALIB_STAT)); timestamp = time(); mcal = this.calStatusString (bitand(data, 3)); gcal = this.calStatusString (bitand(bitshift(data, -4), 3)); acal = this.calStatusString (bitand(bitshift(data, -2), 3)); scal = this.calStatusString (bitand(bitshift(data, -6), 3)); status = struct('System', scal, 'Accelerometer', acal, 'Gyroscope', gcal, 'Magnetometer', mcal); endfunction function [C, timestamp] = readTemperature (this) timestamp = time(); C = single(this.readRegisterS8(this.BNO055_REG_TEMP)); endfunction function [readVal, timestamp] = readOrientation (this) data = this.readRegister(this.BNO055_REG_EUL_HEADING, 6); timestamp = time(); azm = typecast(uint16(data(2))*256 + uint16(data(1)), 'int16'); pitch = typecast(uint16(data(4))*256 + uint16(data(3)), 'int16'); roll = typecast(uint16(data(6))*256 + uint16(data(5)), 'int16'); readVal = deg2rad(single([azm pitch, roll])/16.0); endfunction function [readVal, timestamp] = readMagneticField (this) data = this.readRegister(this.BNO055_REG_MAG_DATA_X, 6); timestamp = time(); x = typecast(uint16(data(2))*256 + uint16(data(1)), 'int16'); y = typecast(uint16(data(4))*256 + uint16(data(3)), 'int16'); z = typecast(uint16(data(6))*256 + uint16(data(5)), 'int16'); readVal = single([x y z])/16.0; endfunction function [readVal, timestamp] = readAcceleration (this) data = this.readRegister(this.BNO055_REG_ACC_DATA_X, 6); timestamp = time(); x = typecast(uint16(data(2))*256 + uint16(data(1)), 'int16'); y = typecast(uint16(data(4))*256 + uint16(data(3)), 'int16'); z = typecast(uint16(data(6))*256 + uint16(data(5)), 'int16'); readVal = single([x y z])/100.0; endfunction function [readVal, timestamp] = readAngularVelocity (this) data = this.readRegister(this.BNO055_REG_GYR_DATA_X, 6); timestamp = time(); x = typecast(uint16(data(2))*256 + uint16(data(1)), 'int16'); y = typecast(uint16(data(4))*256 + uint16(data(3)), 'int16'); z = typecast(uint16(data(6))*256 + uint16(data(5)), 'int16'); readVal = single([x y z])/16.0; endfunction function varargout = read(this) data = readData(this); timestamp = time(); accel = this.readAcceleration(); avel = this.readAngularVelocity(); mag = this.readMagneticField(); orien = this.readOrientation(); if nargout <= 2 varargout{1} = struct('Time', timestamp, 'Acceleration', accel, 'AngularVelocity', avel, 'MagneticField', mag, 'Orientation', orien); if nargout > 1 varargout{2} = 0; # no overrun endif else if nargout > 0 varargout{1} = accel; endif if nargout > 1 varargout{2} = avel; endif if nargout > 2 varargout{3} = mag; endif if nargout == 5 varargout{4} = timestamp; varargout{5} = 0; # overrun else if nargout > 3 varargout{4} = orien; endif if nargout > 4 varargout{5} = timestamp; endif if nargout > 5 varargout{6} = 0; # overrun endif endif endif endfunction function flush(this) # flush currenly does nothing endfunction function disp(this) printf(" %s with properties\n", class(this)); printf(" OperatingMode: %s\n", this.OperatingMode); if isobject(this.i2c) printf(" I2CAddress: %d ('0x%s')\n", this.i2c.i2caddress, num2hex(this.i2c.i2caddress)); printf(" Bus: %d\n", this.i2c.bus); else printf(" Not connected"); endif endfunction function release(this) if isobject(this.i2c) delete(this.i2c); this.i2c = []; endif endfunction function delete(this) try if isobject(this.i2c) delete(this.i2c); this.i2c = []; endif catch # do nothing end_try_catch endfunction endmethods methods (Hidden = true) function v = get.I2CAddress (this) v = sprintf("0x%02X", this.i2c.I2CAddress); endfunction function v = get.Bus (this) v = this.i2c.Bus; endfunction endmethods methods (Access = private) function status = calStatusString(this, val) switch val case {1, 2} status = "partial" ; case 3 status = "full" ; otherwise status = "uncalibrated" ; endswitch endfunction function data = readRegister(this, reg, sz) data = readRegister(this.i2c, reg, sz); endfunction function writeRegister(this, reg, data) writeRegister(this.i2c, reg, data); endfunction function value = readRegisterU16(this, reg) data = readRegister(this, reg, 2); value = uint16(data(2))*256 + uint16(data(1)); endfunction function value = readRegisterS16(this, reg) data = readRegister(this, reg, 2); value = uint16(data(2))*256 + uint16(data(1)); value = typecast(value, 'int16'); endfunction function value = readRegisterU8(this, reg) data = readRegister(this, reg, 1); value = uint8(data(1)); endfunction function value = readRegisterS8(this, reg) data = readRegister(this, reg, 1); value = uint8(data(1)); value = typecast(value, 'int8'); endfunction endmethods endclassdef %!error bno055(1); arduino-0.12.1/inst/sensors/lis3dh.m0000644000000000000000000002143014545566645014223 0ustar00## Copyright (C) 2022 John Donoghue ## ## 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 ## . classdef lis3dh < handle ## -*- texinfo -*- ## @deftypefn {} {} lis3dh ## LIS3DH 3 degrees sensor ## @end deftypefn ## ## @subheading Methods ## @deftypefn {} {@var{obj} =} lis3dh(@var{arObj}) ## @deftypefnx {} {@var{obj} =} lis3dh(@var{arObj}, @var{propertyname, propertyvalue} ....) ## Constructor to create LIS3DH sensor ## @subsubheading Inputs ## @var{arObj} - the arduino parent object ## ## @var{propertyname, propertyvalue} - optional property name, value pairs. ## Current known properties are: ## Current properties are: ## @table @asis ## @item I2CAddress ## I2C address of the sensor (default 0x40) ## @item Bus ## I2C bus - 0 or 1 (default 0) ## @end table ## ## @subsubheading Outputs ## @var{obj} - created object ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## sensor = lis3dh(a) ## } ## @end example ## @end deftypefn ## ## @deftypefn {} {[@var{readVal}, @var{timestamp}] =} readAcceleration(@var{obj}) ## Read the acceleration rate ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{readVal} - the 3 acceleration values ## ## @var{timestamp} - timestamp when read ## @end deftypefn ## ## @deftypefn {} {[@var{readings}, @var{overrun}] =} read(@var{obj}) ## @deftypefnx {} {[@var{accel}, @var{timestamp}, @var{overrun}] =} read(@var{obj}) ## Read the sensor data ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{accel} - acceleration reading from sensor. ## ## @var{timestamp} - timestamp when read ## ## @var{overrun} - overrun flag. ## ## @var{readings} - table structure with fields for Timestamp, Acceleration. ## @end deftypefn ## ## @deftypefn {} {@var{inf} =} info(@var{obj}) ## Read the sensor info ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{inf} - structure containing the sensor information. ## ## Structure fields are: ## @table @asis ## @item SensorId ## sensor id value ## @item Type ## sensor type 'lis3dh' ## @item Status ## sensor status value ## @end table ## ## @end deftypefn ## ## @deftypefn {} {} flush(@var{obj}) ## Flush sensor data ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## None ## @end deftypefn ## ## @deftypefn {} {} release(@var{obj}) ## Release the resources of the sensor ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## None ## @end deftypefn properties(Access = private, constant = true) # Reserved (do not modify) 00 - 06 Reserved LIS3DH_REG_STATUS_REG_AUX = 0x07; LIS3DH_REG_OUT_ADC1_L = 0x08; LIS3DH_REG_OUT_ADC1_H = 0x09; LIS3DH_REG_OUT_ADC2_L = 0x0A; LIS3DH_REG_OUT_ADC2_H = 0x0B; LIS3DH_REG_OUT_ADC3_L = 0x0C; LIS3DH_REG_OUT_ADC3_H = 0x0D; # Reserved (do not modify) 0E; LIS3DH_REG_WHO_AM_I = 0x0F; # Reserved (do not modify) 10; LIS3DH_REG_CTRL_REG0 = 0x1E; LIS3DH_REG_TEMP_CFG_REG = 0x1F; LIS3DH_REG_CTRL_REG1 = 0x20; LIS3DH_REG_CTRL_REG2 = 0x21; LIS3DH_REG_CTRL_REG3 = 0x22; LIS3DH_REG_CTRL_REG4 = 0x23; LIS3DH_REG_CTRL_REG5 = 0x24; LIS3DH_REG_CTRL_REG6 = 0x25; LIS3DH_REG_REFERENCE = 0x26; LIS3DH_REG_STATUS_REG = 0x27; LIS3DH_REG_OUT_X_L = 0x28; LIS3DH_REG_OUT_X_H = 0x29; LIS3DH_REG_OUT_Y_L = 0x2A; LIS3DH_REG_OUT_Y_H = 0x2B; LIS3DH_REG_OUT_Z_L = 0x2C; LIS3DH_REG_OUT_Z_H = 0x2D; LIS3DH_REG_FIFO_CTRL_REG = 0x2E; LIS3DH_REG_FIFO_SRC_REG = 0x2F; LIS3DH_REG_INT1_CFG = 0x30; LIS3DH_REG_INT1_SRC = 0x31; LIS3DH_REG_INT1_THS = 0x32; LIS3DH_REG_INT1_DURATION = 0x33; LIS3DH_REG_INT2_CFG = 0x34; LIS3DH_REG_INT2_SRC = 0x35; LIS3DH_REG_INT2_THS = 0x36; LIS3DH_REG_INT2_DURATION = 0x37; LIS3DH_REG_CLICK_CFG = 0x38; LIS3DH_REG_CLICK_SRC = 0x39; LIS3DH_REG_CLICK_THS = 0x3A; LIS3DH_REG_TIME_LIMIT = 0x3B; LIS3DH_REG_TIME_LATENCY = 0x3C; LIS3DH_REG_TIME_WINDOW = 0x3D; LIS3DH_REG_ACT_THS = 0x3E; LIS3DH_REG_ACT_DUR = 0x3F; endproperties properties(Access = private) i2c; endproperties # matlab compatible properties properties (SetAccess = private) I2CAddress = ""; Bus = 0; endproperties methods # constructor function this = lis3dh(parentObj, varargin) if nargin < 1 || ! isarduino(parentObj) error('Expected arduino object as first parameter'); endif # parse args p = inputParser(CaseSensitive=false, FunctionName='arduinosensor.SI7021'); p.addParameter('I2CAddress', 0x18, @isnumeric); p.addParameter('Bus', 0, @isnumeric); p.parse(varargin{:}); # do we have the address ? address = p.Results.I2CAddress; bus = p.Results.Bus; this.i2c = device(parentObj, "i2caddress", p.Results.I2CAddress, 'Bus', bus); # verify what talking to pause(.1); id = this.readRegisterU8(this.LIS3DH_REG_WHO_AM_I); if id != 0x33 pause(.1); id = this.readRegisterU8(this.LIS3DH_REG_WHO_AM_I); endif if id != 0x33 error ("Invalid id '%X' read for sensor", id) endif # set up device # 400 Mhz, normal mode, all axis enabled this.writeRegister(this.LIS3DH_REG_CTRL_REG1, 0x77); # bdu enabled, little endian, scale 2g, hires this.writeRegister(this.LIS3DH_REG_CTRL_REG4, 0x88); endfunction function inf = info (this) inf = {}; inf.Type = "lis3dh"; inf.SensorId = this.readRegisterU8(this.LIS3DH_REG_WHO_AM_I); inf.Status = this.readRegisterU8(this.LSM6DSO_REG_STATUS_REG); endfunction function [readVal, timestamp] = readAcceleration (this) data = this.readRegister(bitor(this.LIS3DH_REG_OUT_X_L, 0x80), 6); timestamp = time(); x = typecast(uint16(data(2))*256 + uint16(data(1)), 'int16'); y = typecast(uint16(data(4))*256 + uint16(data(3)), 'int16'); z = typecast(uint16(data(6))*256 + uint16(data(5)), 'int16'); readVal = single([x y z]) * 2.0 / 32768.0; endfunction function varargout = read(this) data = readData(this); timestamp = time(); accel = this.readAcceleration(); if nargout <= 2 varargout{1} = struct('Time', timestamp, 'Acceleration', accel); if nargout > 1 varargout{2} = 0; # no overrun endif else if nargout > 0 varargout{1} = accel; endif if nargout > 1 varargout{2} = timestamp; endif if nargout > 2 varargout{3} = 0; # overrun endif endif endfunction function flush(this) # flush currenly does nothing endfunction function disp(this) printf(" %s with properties\n", class(this)); if isobject(this.i2c) printf(" I2CAddress: %d ('0x%s')\n", this.i2c.i2caddress, num2hex(this.i2c.i2caddress)); printf(" Bus: %d\n", this.i2c.bus); else printf(" Not connected"); endif endfunction function release(this) if isobject(this.i2c) delete(this.i2c); this.i2c = []; endif endfunction function delete(this) try if isobject(this.i2c) delete(this.i2c); this.i2c = []; endif catch # do nothing end_try_catch endfunction endmethods methods (Hidden = true) function v = get.I2CAddress (this) v = sprintf("0x%02X", this.i2c.I2CAddress); endfunction function v = get.Bus (this) v = this.i2c.Bus; endfunction endmethods methods (Access = private) function data = readRegister(this, reg, sz) data = readRegister(this.i2c, reg, sz); endfunction function writeRegister(this, reg, data) writeRegister(this.i2c, reg, data); endfunction function value = readRegisterU8(this, reg) data = readRegister(this, reg, 1); value = uint8(data(1)); endfunction endmethods endclassdef %!error lis3dh(1); arduino-0.12.1/inst/sensors/lps22hb.m0000644000000000000000000002705214545566645014317 0ustar00## Copyright (C) 2022 John Donoghue ## ## Conversion routines based on code from LPS22HB datasheet ## DocID027083 Rev 6 ## ## 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 ## . classdef lps22hb < handle ## -*- texinfo -*- ## @deftypefn {} {} lps22hb ## LPS22HB absolute pressure and temperature sensor ## @end deftypefn ## ## @subheading Methods ## @deftypefn {} {@var{obj} =} lps22hb(@var{arObj}) ## @deftypefnx {} {@var{obj} =} lps22hb(@var{arObj}, @var{propertyname, propertyvalue} ....) ## Constructor to create LPS22HB sensor ## @subsubheading Inputs ## @var{arObj} - the arduino parent object ## ## @var{propertyname, propertyvalue} - optional property name, value pairs. ## Current known properties are: ## Current properties are: ## @table @asis ## @item I2CAddress ## I2C address of the sensor (default 0x5C) ## @item Bus ## I2C bus - 0 or 1 (default 0) ## @end table ## ## @subsubheading Outputs ## @var{obj} - created object ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## sensor = lps22hb(a) ## } ## @end example ## @end deftypefn ## ## @deftypefn {} {[@var{C}, @var{timestamp}] =} readTemperature(@var{obj}) ## Read the temperature ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{C} - read temperature in deg C. ## ## @var{timestamp} - timestamp when read ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## s = lps22hb(a) ## # get temp ## temp = s.readTemperature ## } ## @end example ## @seealso{lps22hb} ## @end deftypefn ## ## @deftypefn {} {[@var{P}, @var{timestamp}] =} readPressure(@var{obj}) ## Read the pressure ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{P} - pressure reading from sensor. ## ## @var{timestamp} - timestamp when read ## @end deftypefn ## ## @deftypefn {} {[@var{readings}, @var{overrun}] =} read(@var{obj}) ## @deftypefnx {} {[@var{P}, @var{C}, @var{timestamp}, @var{overrun}] =} read(@var{obj}) ## Read the sensor data ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{P} - pressure reading from sensor. ## ## @var{C} - temperature reading from sensor. ## ## @var{timestamp} - timestamp when read ## ## @var{overrun} - overrun flag. ## ## @var{readings} - table structure with fields for Timestamp, Pressure, Temperature and Humidity. ## @end deftypefn ## ## @deftypefn {} {@var{inf} =} info(@var{obj}) ## Read the sensor info ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{inf} - structure containing the sensor information. ## ## Structure fields are: ## @table @asis ## @item Version ## Chip firmware version ## @item SensorId ## sensor id value ## @item Type ## sensor type 'lps22hb' ## @item Status ## Status value read from sensor ## @end table ## ## @end deftypefn ## ## @deftypefn {} {} flush(@var{obj}) ## Flush sensor data ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## None ## @end deftypefn ## ## @deftypefn {} {} release(@var{obj}) ## Release the resources of the sensor ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## None ## @end deftypefn properties(Access = private, constant = true) LPS22_DEFAULT_ADDRESS = 0x5D; LPS22_CHIP_ID = 0xB1; LPS22_REG_INTERRUPT_CFG = 0; # Interrupt register LPS22_REG_THS_P_L = 0x0C; # Pressure threshold registers LPS22_REG_THS_P_H = 0x0D; #LPS22_REG_Reserved = 0E; # Reserved LPS22_REG_WHO_AM_I = 0x0F; # Who am I LPS22_REG_CTRL_REG1 = 0x10; # Control registers LPS22_REG_CTRL_REG2 = 0x11; LPS22_REG_CTRL_REG3 = 0x12; #LPS22_REG_Reserved = 0x13; # Reserved LPS22_REG_FIFO_CTRL = 0x14; # FIFO configuration register LPS22_REG_REF_P_XL = 0x15; # Reference pressure registers LPS22_REG_REF_P_L = 0x16; LPS22_REG_REF_P_H = 0x17; LPS22_REG_RPDS_L = 0x18; # Pressure offset registers LPS22_REG_RPDS_H = 0x19; LPS22_REG_RES_CONF = 0x1A; # Resolution register #LPS22_REG_Reserved = 0x1B; # Reserved LPS22_REG_INT_SOURCE = 0x25; # Interrupt register LPS22_REG_FIFO_STATUS = 0x26; # FIFO status register LPS22_REG_STATUS = 0x27; # Status register LPS22_REG_PRESS_OUT_XL = 0x28; # Pressure output registers LPS22_REG_PRESS_OUT_L = 0x29; LPS22_REG_PRESS_OUT_H = 0x2A; LPS22_REG_TEMP_OUT_L = 0x2B; # Temperature output registers LPS22_REG_TEMP_OUT_H = 0x2C; #LPS22_REG_Reserved = 0x2D; # Reserved LPS22_REG_LPFP_RES = 0x33; # Filter reset register endproperties properties(Access = private) i2c; caldata = {}; endproperties # matlab compatible properties properties (SetAccess = private) I2CAddress = ""; Bus = 0; SampleRate = 1; endproperties methods # constructor function this = lps22hb(parentObj, varargin) if nargin < 1 || ! isarduino(parentObj) error('Expected arduino object as first parameter'); endif # parse args p = inputParser(CaseSensitive=false, FunctionName='lps22hb'); p.addParameter('I2CAddress', this.LPS22_DEFAULT_ADDRESS, @isnumeric); p.addParameter('Bus', 0, @isnumeric); p.addParameter('SampleRate', 10, @isnumeric); p.parse(varargin{:}); # do we have the address ? address = p.Results.I2CAddress; bus = p.Results.Bus; this.SampleRate = int32(p.Results.SampleRate); regrate = 1; switch this.SampleRate case 1 regrate = 1; case 10 regrate = 2; case 25 regrate = 3; case 50 regrate = 4; case 75 regrate = 5; otherwise error("Unsupported samplerate - known values 1, 10, 25, 50, 75"); endswitch #i2caddresses = scanI2Cbus(parentObj, bus); #idx = find(cellfun ( @(x) strcmp(x, sprintf("0x%02X", address)), i2caddresses)); #if isempty(idx) # error('No matching i2c address found on bus'); #endif this.i2c = device(parentObj, "i2caddress", p.Results.I2CAddress, 'Bus', bus); pause(.1); # init id = this.readRegisterU8(this.LPS22_REG_WHO_AM_I); if id != this.LPS22_CHIP_ID pause(.2); id = this.readRegisterU8(this.LPS22_REG_WHO_AM_I); endif if id != this.LPS22_CHIP_ID error ("Invalid id '%X' read for sensor", id) endif # reset states this.writeRegister(this.LPS22_REG_CTRL_REG2, 0x04); # wait while chip is resetting status = this.readRegisterU8(this.LPS22_REG_CTRL_REG2); while bitand(status, 4) == 4 pause(.1); status = this.readRegisterU8(this.LPS22_REG_CTRL_REG2); endwhile # set data rate reg = this.readRegisterU8(this.LPS22_REG_CTRL_REG1); reg = bitand(reg, 0x8F); reg = bitor(reg, bitshift(regrate, 4)); this.writeRegister(this.LPS22_REG_CTRL_REG1, reg); endfunction function inf = info (this) inf = {}; inf.Type = "lps22hb"; inf.SensorId = this.LPS22_CHIP_ID; inf.Version = 0; inf.Status = this.readRegisterU8(this.LPS22_REG_STATUS); endfunction function [C, timestamp] = readTemperature (this) data = readData(this); value = bitshift(uint16(data(6)), 8) + uint16(data(5)); timestamp = time(); C = calcTemperature(this, value); endfunction function [P, timestamp] = readPressure(this) data = readData(this); value = bitshift(int32(data(4)), 16) + bitshift(int32(data(3)), 8) + int32(data(2)); timestamp = time(); P = calcPressure(this, value); endfunction function varargout = read(this) data = readData(this); timestamp = time(); value = bitshift(uint16(data(6)), 8) + uint16(data(5)); C = calcTemperature(this, value); value = bitshift(int32(data(4)), 16) + bitshift(int32(data(3)), 8) + int32(data(2)); P = calcPressure(this, value); overrun = bitand(data(1), 0x30) != 0; if nargout <= 2 varargout{1} = struct('Time', timestamp, 'Temperature', C, 'Pressure', P); if nargout > 1 varargout{2} = overrun; endif else if nargout > 0 varargout{1} = P; endif if nargout > 1 varargout{2} = C; endif if nargout > 2 varargout{3} = timestamp; endif if nargout > 3 varargout{4} = overrun; endif endif endfunction function flush(this) # flush currenly does nothing endfunction function disp(this) printf(" %s with properties\n", class(this)); if isobject(this.i2c) printf(" I2CAddress: %d ('0x%s')\n", this.i2c.i2caddress, num2hex(this.i2c.i2caddress)); printf(" Bus: %d\n", this.i2c.bus); printf(" SampleRate: %d\n", this.SampleRate); else printf(" Not connected"); endif endfunction function release(this) if isobject(this.i2c) delete(this.i2c); this.i2c = []; endif endfunction function delete(this) try if isobject(this.i2c) delete(this.i2c); this.i2c = []; endif catch # do nothing end_try_catch endfunction endmethods methods (Hidden = true) function v = get.I2CAddress (this) v = sprintf("0x%02X", this.i2c.I2CAddress); endfunction function v = get.Bus (this) v = this.i2c.Bus; endfunction endmethods methods (Access = private) function C = calcTemperature(this, value) if bitand(value, 0x8000) var1 = double(value) - double(0xFFFF); else var1 = double(value); endif C = var1 / 100.0; endfunction function P = calcPressure(this, value) if bitand(value, int32(0x800000)) var1 = double(value) - double(0xFFFFFF); else var1 = double(value); endif P = var1 / 4096.0; endfunction function data = readRegister(this, reg, sz) data = readRegister(this.i2c, reg, sz); endfunction function writeRegister(this, reg, data) writeRegister(this.i2c, reg, data); endfunction # read the data function data = readData(this) # wait for data m = 0; while m == 0 status = this.readRegisterU8 (this.LPS22_REG_STATUS); m = bitand(status, 0x03); if m != 0 pause(.1); endif endwhile # 1 status, 3 pres, 2 temp data = readRegister(this, this.LPS22_REG_STATUS, 6); endfunction function value = readRegisterU8(this, reg) data = readRegister(this, reg, 1); value = uint8(data(1)); endfunction endmethods endclassdef %!error lps22hb(1); arduino-0.12.1/inst/sensors/lsm6dso.m0000644000000000000000000003556014545566645014435 0ustar00## Copyright (C) 2022 John Donoghue ## ## 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 ## . classdef lsm6dso < handle ## -*- texinfo -*- ## @deftypefn {} {} lsm6dso ## LSM6DSO 6 degrees sensor ## @end deftypefn ## ## @subheading Methods ## @deftypefn {} {@var{obj} =} lsm6dso(@var{arObj}) ## @deftypefnx {} {@var{obj} =} lsm6dso(@var{arObj}, @var{propertyname, propertyvalue} ....) ## Constructor to create LSM6DSO sensor ## @subsubheading Inputs ## @var{arObj} - the arduino parent object ## ## @var{propertyname, propertyvalue} - optional property name, value pairs. ## Current known properties are: ## Current properties are: ## @table @asis ## @item I2CAddress ## I2C address of the sensor (default 0x40) ## @item Bus ## I2C bus - 0 or 1 (default 0) ## @end table ## ## @subsubheading Outputs ## @var{obj} - created object ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## sensor = lsm6dso(a) ## } ## @end example ## @end deftypefn ## ## @deftypefn {} {[@var{C}, @var{timestamp}] =} readTemperature(@var{obj}) ## Read the temperature ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{C} - read temperature in deg C. ## ## @var{timestamp} - timestamp when read ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## s = lsm6dso(a) ## # get temp ## temp = s.readTemperature ## } ## @end example ## @seealso{lsm6dso} ## @end deftypefn ## ## @deftypefn {} {[@var{readVal}, @var{timestamp}] =} readAcceleration(@var{obj}) ## Read the acceleration rate ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{readVal} - the 3 acceleration values ## ## @var{timestamp} - timestamp when read ## @end deftypefn ## ## @deftypefn {} {[@var{readVal}, @var{timestamp}] =} readAngularVelocity(@var{obj}) ## Read the angular velocity ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{readVal} - the 3 angular velocity values ## ## @var{timestamp} - timestamp when read ## @end deftypefn ## ## @deftypefn {} {[@var{readings}, @var{overrun}] =} read(@var{obj}) ## @deftypefnx {} {[@var{accel}, @var{gyro}, @var{mag}, @var{timestamp}, @var{overrun}] =} read(@var{obj}) ## Read the sensor data ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{accel} - acceleration reading from sensor. ## ## @var{gyro} - angular acceleration reading from sensor. ## ## @var{timestamp} - timestamp when read ## ## @var{overrun} - overrun flag. ## ## @var{readings} - table structure with fields for Timestamp, Acceleration, AngularVelocity. ## @end deftypefn ## ## @deftypefn {} {@var{inf} =} info(@var{obj}) ## Read the sensor info ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{inf} - structure containing the sensor information. ## ## Structure fields are: ## @table @asis ## @item SensorId ## sensor id value ## @item Type ## sensor type 'lsm6dso' ## @end table ## ## @end deftypefn ## ## @deftypefn {} {} flush(@var{obj}) ## Flush sensor data ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## None ## @end deftypefn ## ## @deftypefn {} {} release(@var{obj}) ## Release the resources of the sensor ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## None ## @end deftypefn properties(Access = private, constant = true) LSM6DSO_REG_FUNC_CFG_ACCESS = 0x01; # RW 01 00000001 00000000 LSM6DSO_REG_PIN_CTRL = 0x02; # RW 02 00000010 00111111 #LSM6DSO_REG_RESERVED - 03-06 LSM6DSO_REG_FIFO_CTRL1 = 0x07; # RW 07 00000111 00000000 LSM6DSO_REG_FIFO_CTRL2 = 0x08; # RW 08 00001000 00000000 LSM6DSO_REG_FIFO_CTRL3 = 0x09; # RW 09 00001001 00000000 LSM6DSO_REG_FIFO_CTRL4 = 0x0A; # RW 0A 00001010 00000000 LSM6DSO_REG_COUNTER_BDR_REG1 = 0x0B; # RW 0B 00001011 00000000 LSM6DSO_REG_COUNTER_BDR_REG2 = 0x0C; # RW 0C 00001100 00000000 LSM6DSO_REG_INT1_CTRL = 0x0D; # RW 0D 00001101 00000000 LSM6DSO_REG_INT2_CTRL = 0x0E; # RW 0E 00001110 00000000 LSM6DSO_REG_WHO_AM_I = 0x0F; # R 0F 00001111 01101100 R (SPI2) LSM6DSO_REG_CTRL1_XL = 0x10; # RW 10 00010000 00000000 R (SPI2) LSM6DSO_REG_CTRL2_G = 0x11; # RW 11 00010001 00000000 R (SPI2) LSM6DSO_REG_CTRL3_C = 0x12; # RW 12 00010010 00000100 R (SPI2) LSM6DSO_REG_CTRL4_C = 0x13; # RW 13 00010011 00000000 R (SPI2) LSM6DSO_REG_CTRL5_C = 0x14; # RW 14 00010100 00000000 R (SPI2) LSM6DSO_REG_CTRL6_C = 0x15; # RW 15 00010101 00000000 R (SPI2) LSM6DSO_REG_CTRL7_G = 0x16; # RW 16 00010110 00000000 R (SPI2) LSM6DSO_REG_CTRL8_XL = 0x17; # RW 17 0001 0111 00000000 R (SPI2) LSM6DSO_REG_CTRL9_XL = 0x18; # RW 18 00011000 11100000 R (SPI2) LSM6DSO_REG_CTRL10_C = 0x19; # RW 19 00011001 00000000 R (SPI2) LSM6DSO_REG_ALL_INT_SRC = 0x1A; # R 1A 00011010 output LSM6DSO_REG_WAKE_UP_SRC = 0x1B; # R 1B 00011011 output LSM6DSO_REG_TAP_SRC = 0x1C; # R 1C 00011100 output LSM6DSO_REG_D6D_SRC = 0x1D; # R 1D 00011101 output LSM6DSO_REG_STATUS_REG = 0x1E; # (1) / STATUS_SPIAux(2) R 1E 00011110 output # LSM6DSO_REG_RESERVED - 1F 00011111 LSM6DSO_REG_OUT_TEMP_L = 0x20; # R 20 00100000 output LSM6DSO_REG_OUT_TEMP_H = 0x21; # R 21 00100001 output LSM6DSO_REG_OUTX_L_G = 0x22; # R 22 00100010 output LSM6DSO_REG_OUTX_H_G = 0x23; # R 23 00100011 output LSM6DSO_REG_OUTY_L_G = 0x24; # R 24 00100100 outpu LSM6DSO_REG_OUTY_H_G = 0x25; # R 25 00100101 output LSM6DSO_REG_OUTZ_L_G = 0x26; # R 26 00100110 output LSM6DSO_REG_OUTZ_H_G = 0x27; # R 27 00100111 output LSM6DSO_REG_OUTX_L_A = 0x28; # R 28 00101000 output LSM6DSO_REG_OUTX_H_A = 0x29; # R 29 00101001 output LSM6DSO_REG_OUTY_L_A = 0x2A; # R 2A 00101010 output LSM6DSO_REG_OUTY_H_A = 0x2B; # R 2B 00101011 output LSM6DSO_REG_OUTZ_L_A = 0x2C; # R 2C 00101100 output LSM6DSO_REG_OUTZ_H_A = 0x2D; # R 2D 00101101 output #LSM6DSO_REG_RESERVED - 2E-34 LSM6DSO_REG_EMB_FUNC_STATUS_MAINPAGE = 0x35; # R 35 00110101 output LSM6DSO_REG_FSM_STATUS_A_MAINPAGE = 0x36; # R 36 00110110 output LSM6DSO_REG_FSM_STATUS_B_MAINPAGE = 0x37; # R 37 00110111 output # LSM6DSO_REG_RESERVED - 38 LSM6DSO_REG_STATUS_MASTER_MAINPAGE = 0x39; # R 39 00111001 output LSM6DSO_REG_FIFO_STATUS1 = 0x3A; # R 3A 00111010 output LSM6DSO_REG_FIFO_STATUS2 = 0x3B; # R 3B 00111011 output #LSM6DSO_REG_RESERVED - 3C-3F LSM6DSO_REG_TIMESTAMP0 = 0x40; # R 40 01000000 output R (SPI2) LSM6DSO_REG_TIMESTAMP1 = 0x41; # R 41 01000001 output R (SPI2) LSM6DSO_REG_TIMESTAMP2 = 0x42; # R 42 01000010 output R (SPI2) LSM6DSO_REG_TIMESTAMP3 = 0x43; # R 43 01000011 output R (SPI2) #LSM6DSO_REG_RESERVED - 44-55 LSM6DSO_REG_TAP_CFG0 = 0x56; # RW 56 01010110 00000000 LSM6DSO_REG_TAP_CFG1 = 0x57; # RW 57 01010111 00000000 LSM6DSO_REG_TAP_CFG2 = 0x58; # RW 58 01011000 00000000 LSM6DSO_REG_TAP_THS_6D = 0x59; # RW 59 01011001 00000000 LSM6DSO_REG_INT_DUR2 = 0x5A; # RW 5A 01011010 00000000 LSM6DSO_REG_WAKE_UP_THS = 0x5B; # RW 5B 01011011 00000000 LSM6DSO_REG_WAKE_UP_DUR = 0x5C; # RW 5C 01011100 00000000 LSM6DSO_REG_FREE_FALL = 0x5D; # RW 5D 01011101 00000000 LSM6DSO_REG_MD1_CFG = 0x5E; # RW 5E 01011110 00000000 LSM6DSO_REG_MD2_CFG = 0x5F; # RW 5F 01011111 00000000 # LSM6DSO_REG_RESERVED - 60-61 00000000 LSM6DSO_REG_I3C_BUS_AVB = 0x62; # RW 62 01100010 00000000 LSM6DSO_REG_INTERNAL_FREQ_FINE = 0x63; # R 63 01100011 output # LSM6DSO_REG_RESERVED - 64-6E LSM6DSO_REG_INT_OIS = 0x6F; # R 6F 01101111 00000000 RW (SPI2) LSM6DSO_REG_CTRL1_OIS = 0x70; # R 70 01110000 00000000 RW (SPI2) LSM6DSO_REG_CTRL2_OIS = 0x71; # R 71 01110001 00000000 RW (SPI2) LSM6DSO_REG_CTRL3_OIS = 0x72; # R 72 01110010 00000000 RW (SPI2) LSM6DSO_REG_X_OFS_USR = 0x73; # RW 73 01110011 00000000 LSM6DSO_REG_Y_OFS_USR = 0x74; # RW 74 01110100 00000000 LSM6DSO_REG_Z_OFS_USR = 0x75; # RW 75 01110101 00000000 #LSM6DSO_REG_RESERVED - 76-77 LSM6DSO_REG_FIFO_DATA_OUT_TAG = 0x78; # R 78 01111000 output LSM6DSO_REG_FIFO_DATA_OUT_X_L = 0x79; # R 79 01111001 output LSM6DSO_REG_FIFO_DATA_OUT_X_H = 0x7A; # R 7A 01111010 output LSM6DSO_REG_FIFO_DATA_OUT_Y_L = 0x7B; # R 7B 01111011 output LSM6DSO_REG_FIFO_DATA_OUT_Y_H = 0x7C; # R 7C 01111100 output LSM6DSO_REG_FIFO_DATA_OUT_Z_L = 0x7D; # R 7D 01111101 output LSM6DSO_REG_FIFO_DATA_OUT_X_H = 0x7E; # R 7E 01111110 output endproperties properties(Access = private) i2c; caldata = {}; endproperties # matlab compatible properties properties (SetAccess = private) I2CAddress = ""; Bus = 0; endproperties methods # constructor function this = lsm6dso(parentObj, varargin) if nargin < 1 || ! isarduino(parentObj) error('Expected arduino object as first parameter'); endif # parse args p = inputParser(CaseSensitive=false, FunctionName='arduinosensor.SI7021'); p.addParameter('I2CAddress', 0x6A, @isnumeric); # matlab default is 0x28 p.addParameter('Bus', 0, @isnumeric); p.parse(varargin{:}); # do we have the address ? address = p.Results.I2CAddress; bus = p.Results.Bus; this.i2c = device(parentObj, "i2caddress", p.Results.I2CAddress, 'Bus', bus); # verify what talking to pause(.1); id = this.readRegisterU8(this.LSM6DSO_REG_WHO_AM_I); if id != 0x6C error ("Invalid id '%X' read for sensor", id) endif # set up device # set the gyroscope control register to work at 104 Hz, 2000 dps and in bypass mode this.writeRegister(this.LSM6DSO_REG_CTRL2_G, 0x4C); # Set the Accelerometer control register to work at 104 Hz, 4 g,and in bypass mode and enable ODR/4 lowpass filter this.writeRegister(this.LSM6DSO_REG_CTRL1_XL, 0x4A); # set gyroscope power mode to high performance and bandwidth to 16 MHz this.writeRegister(this.LSM6DSO_REG_CTRL7_G, 0x00); # Set the ODR config register to ODR/4 this.writeRegister(this.LSM6DSO_REG_CTRL8_XL, 0x09); endfunction function inf = info (this) inf = {}; inf.Type = "lsm6dso"; inf.SensorId = this.readRegisterU8(this.LSM6DSO_REG_WHO_AM_I); inf.Status = this.readRegisterU8(this.LSM6DSO_REG_STATUS_REG); endfunction function [C, timestamp] = readTemperature (this) value = this.readRegisterS16(this.LSM6DSO_REG_OUT_TEMP_L); timestamp = time(); C = single(value)/256.0 + 25.0; endfunction function [readVal, timestamp] = readAcceleration (this) data = this.readRegister(this.LSM6DSO_REG_OUTX_L_A, 6); timestamp = time(); x = typecast(uint16(data(2))*256 + uint16(data(1)), 'int16'); y = typecast(uint16(data(4))*256 + uint16(data(3)), 'int16'); z = typecast(uint16(data(6))*256 + uint16(data(5)), 'int16'); # 4g scale readVal = single([x y z]) * 4.0 / 32768.0; endfunction function [readVal, timestamp] = readAngularVelocity (this) data = this.readRegister(this.LSM6DSO_REG_OUTX_L_G, 6); timestamp = time(); x = typecast(uint16(data(2))*256 + uint16(data(1)), 'int16'); y = typecast(uint16(data(4))*256 + uint16(data(3)), 'int16'); z = typecast(uint16(data(6))*256 + uint16(data(5)), 'int16'); # range 2000 readVal = single([x y z]) * 2000.0 / 32768.0; endfunction function varargout = read(this) data = readData(this); timestamp = time(); accel = this.readAcceleration(); avel = this.readAngularVelocity(); temp = this.readTemperature(); if nargout <= 2 varargout{1} = struct('Time', timestamp, 'Acceleration', accel, 'AngularVelocity', avel, 'Temperature', temp); if nargout > 1 varargout{2} = 0; # no overrun endif else if nargout > 0 varargout{1} = accel; endif if nargout > 1 varargout{2} = avel; endif if nargout > 2 varargout{3} = temp; endif if nargout > 3 varargout{4} = timestamp; endif if nargout > 4 varargout{5} = 0; # overrun endif endif endfunction function flush(this) # flush currenly does nothing endfunction function disp(this) printf(" %s with properties\n", class(this)); if isobject(this.i2c) printf(" I2CAddress: %d ('0x%s')\n", this.i2c.i2caddress, num2hex(this.i2c.i2caddress)); printf(" Bus: %d\n", this.i2c.bus); else printf(" Not connected"); endif endfunction function release(this) if isobject(this.i2c) delete(this.i2c); this.i2c = []; endif endfunction function delete(this) try if isobject(this.i2c) delete(this.i2c); this.i2c = []; endif catch # do nothing end_try_catch endfunction endmethods methods (Hidden = true) function v = get.I2CAddress (this) v = sprintf("0x%02X", this.i2c.I2CAddress); endfunction function v = get.Bus (this) v = this.i2c.Bus; endfunction endmethods methods (Access = private) function data = readRegister(this, reg, sz) data = readRegister(this.i2c, reg, sz); endfunction function writeRegister(this, reg, data) writeRegister(this.i2c, reg, data); endfunction function value = readRegisterU16(this, reg) data = readRegister(this, reg, 2); value = uint16(data(2))*256 + uint16(data(1)); endfunction function value = readRegisterS16(this, reg) data = readRegister(this, reg, 2); value = uint16(data(2))*256 + uint16(data(1)); value = typecast(value, 'int16'); endfunction function value = readRegisterU8(this, reg) data = readRegister(this, reg, 1); value = uint8(data(1)); endfunction function value = readRegisterS8(this, reg) data = readRegister(this, reg, 1); value = uint8(data(1)); value = typecast(value, 'int8'); endfunction endmethods endclassdef %!error lsm6dso(1); arduino-0.12.1/inst/sensors/mpu6050.m0000644000000000000000000003327414545566645014162 0ustar00## Copyright (C) 2022 John Donoghue ## ## 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 ## . classdef mpu6050 < handle ## -*- texinfo -*- ## @deftypefn {} {} mpu6050 ## MPU-6050 6 degrees sensor ## @end deftypefn ## ## @subheading Methods ## @deftypefn {} {@var{obj} =} mpu6050(@var{arObj}) ## @deftypefnx {} {@var{obj} =} mpu6050(@var{arObj}, @var{propertyname, propertyvalue} ....) ## Constructor to create MPU-6050 sensor ## @subsubheading Inputs ## @var{arObj} - the arduino parent object ## ## @var{propertyname, propertyvalue} - optional property name, value pairs. ## Current known properties are: ## Current properties are: ## @table @asis ## @item I2CAddress ## I2C address of the sensor (default 0x40) ## @item Bus ## I2C bus - 0 or 1 (default 0) ## @end table ## ## @subsubheading Outputs ## @var{obj} - created object ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## sensor = mpu6050(a) ## } ## @end example ## @end deftypefn ## ## @deftypefn {} {[@var{C}, @var{timestamp}] =} readTemperature(@var{obj}) ## Read the temperature ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{C} - read temperature in deg C. ## ## @var{timestamp} - timestamp when read ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## s = mpu6050(a) ## # get temp ## temp = s.readTemperature ## } ## @end example ## @seealso{mpu6050} ## @end deftypefn ## ## @deftypefn {} {[@var{readVal}, @var{timestamp}] =} readAcceleration(@var{obj}) ## Read the acceleration rate ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{readVal} - the 3 acceleration values ## ## @var{timestamp} - timestamp when read ## @end deftypefn ## ## @deftypefn {} {[@var{readVal}, @var{timestamp}] =} readAngularVelocity(@var{obj}) ## Read the angular velocity ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{readVal} - the 3 angular velocity values ## ## @var{timestamp} - timestamp when read ## @end deftypefn ## ## @deftypefn {} {[@var{readings}, @var{overrun}] =} read(@var{obj}) ## @deftypefnx {} {[@var{accel}, @var{gyro}, @var{mag}, @var{timestamp}, @var{overrun}] =} read(@var{obj}) ## Read the sensor data ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{accel} - acceleration reading from sensor. ## ## @var{gyro} - angular acceleration reading from sensor. ## ## @var{timestamp} - timestamp when read ## ## @var{overrun} - overrun flag. ## ## @var{readings} - table structure with fields for Timestamp, Acceleration, AngularVelocity. ## @end deftypefn ## ## @deftypefn {} {@var{inf} =} info(@var{obj}) ## Read the sensor info ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## @var{inf} - structure containing the sensor information. ## ## Structure fields are: ## @table @asis ## @item SensorId ## sensor id value ## @item Type ## sensor type 'mpu6050' ## @end table ## ## @end deftypefn ## ## @deftypefn {} {} flush(@var{obj}) ## Flush sensor data ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## None ## @end deftypefn ## ## @deftypefn {} {} release(@var{obj}) ## Release the resources of the sensor ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## None ## @end deftypefn properties(Access = private, constant = true) MPU6050_REG_XG_OFFS_TC = 0x00; MPU6050_REG_YG_OFFS_TC = 0x01; MPU6050_REG_ZG_OFFS_TC = 0x02; MPU6050_REG_X_FINE_GAIN = 0x03; MPU6050_REG_Y_FINE_GAIN = 0x04; MPU6050_REG_Z_FINE_GAIN = 0x05; MPU6050_REG_XA_OFFS_H = 0x06; MPU6050_REG_XA_OFFS_L_TC= 0x07; MPU6050_REG_YA_OFFS_H = 0x08; MPU6050_REG_YA_OFFS_L_TC= 0x09; MPU6050_REG_ZA_OFFS_H = 0x0A; MPU6050_REG_ZA_OFFS_L_TC= 0x0B; MPU6050_REG_SELF_TEST_X = 0x0D; MPU6050_REG_SELF_TEST_Y = 0x0E; MPU6050_REG_SELF_TEST_Z = 0x0F; MPU6050_REG_SELF_TEST_A = 0x10; MPU6050_REG_XG_OFFS_USRH= 0x13; MPU6050_REG_XG_OFFS_USRL= 0x14; MPU6050_REG_YG_OFFS_USRH= 0x15; MPU6050_REG_YG_OFFS_USRL= 0x16; MPU6050_REG_ZG_OFFS_USRH= 0x17; MPU6050_REG_ZG_OFFS_USRL= 0x18; MPU6050_REG_SMPLRT_DIV = 0x19; MPU6050_REG_CONFIG = 0x1A; MPU6050_REG_GYRO_CONFIG = 0x1B; MPU6050_REG_ACCEL_CONFIG= 0x1C; MPU6050_REG_FF_THR = 0x1D; MPU6050_REG_FF_DUR = 0x1E; MPU6050_REG_MOT_THR = 0x1F; MPU6050_REG_MOT_DUR = 0x20; MPU6050_REG_ZRMOT_THR = 0x21; MPU6050_REG_ZRMOT_DUR = 0x22; MPU6050_REG_FIFO_EN = 0x23; MPU6050_REG_I2C_MST_CTRL= 0x24; MPU6050_REG_I2C_SLV0_ADDR= 0x25; MPU6050_REG_I2C_SLV0_REG= 0x26; MPU6050_REG_I2C_SLV0_CTRL= 0x27; MPU6050_REG_I2C_SLV1_ADDR= 0x28; MPU6050_REG_I2C_SLV1_REG= 0x29; MPU6050_REG_I2C_SLV1_CTRL= 0x2A; MPU6050_REG_I2C_SLV2_ADDR= 0x2B; MPU6050_REG_I2C_SLV2_REG= 0x2C; MPU6050_REG_I2C_SLV2_CTRL= 0x2D; MPU6050_REG_I2C_SLV3_ADDR= 0x2E; MPU6050_REG_I2C_SLV3_REG= 0x2F; MPU6050_REG_I2C_SLV3_CTRL= 0x30; MPU6050_REG_I2C_SLV4_ADDR= 0x31; MPU6050_REG_I2C_SLV4_REG= 0x32; MPU6050_REG_I2C_SLV4_DO = 0x33; MPU6050_REG_I2C_SLV4_CTRL= 0x34; MPU6050_REG_I2C_SLV4_DI = 0x35; MPU6050_REG_I2C_MST_STATUS= 36; MPU6050_REG_INT_PIN_CFG = 0x37; MPU6050_REG_INT_ENABLE = 0x38; MPU6050_REG_DMP_INT_STATUS= 0x39; MPU6050_REG_INT_STATUS = 0x3A; MPU6050_REG_ACCEL_XOUT_H= 0x3B; MPU6050_REG_ACCEL_XOUT_L= 0x3C; MPU6050_REG_ACCEL_YOUT_H= 0x3D; MPU6050_REG_ACCEL_YOUT_L= 0x3E; MPU6050_REG_ACCEL_ZOUT_H= 0x3F; MPU6050_REG_ACCEL_ZOUT_L= 0x40; MPU6050_REG_TEMP_OUT_H = 0x41; MPU6050_REG_TEMP_OUT_L = 0x42; MPU6050_REG_GYRO_XOUT_H = 0x43; MPU6050_REG_GYRO_XOUT_L = 0x44; MPU6050_REG_GYRO_YOUT_H = 0x45; MPU6050_REG_GYRO_YOUT_L = 0x46; MPU6050_REG_GYRO_ZOUT_H = 0x47; MPU6050_REG_GYRO_ZOUT_L = 0x48; MPU6050_REG_EXT_SENS_DATA_00 = 0x49; MPU6050_REG_EXT_SENS_DATA_01 = 0x4A; MPU6050_REG_EXT_SENS_DATA_02 = 0x4B; MPU6050_REG_EXT_SENS_DATA_03 = 0x4C; MPU6050_REG_EXT_SENS_DATA_04 = 0x4D; MPU6050_REG_EXT_SENS_DATA_05 = 0x4E; MPU6050_REG_EXT_SENS_DATA_06 = 0x4F; MPU6050_REG_EXT_SENS_DATA_07 = 0x50; MPU6050_REG_EXT_SENS_DATA_08 = 0x51; MPU6050_REG_EXT_SENS_DATA_09 = 0x52; MPU6050_REG_EXT_SENS_DATA_10 = 0x53; MPU6050_REG_EXT_SENS_DATA_11 = 0x54; MPU6050_REG_EXT_SENS_DATA_12 = 0x55; MPU6050_REG_EXT_SENS_DATA_13 = 0x56; MPU6050_REG_EXT_SENS_DATA_14 = 0x57; MPU6050_REG_EXT_SENS_DATA_15 = 0x58; MPU6050_REG_EXT_SENS_DATA_16 = 0x59; MPU6050_REG_EXT_SENS_DATA_17 = 0x5A; MPU6050_REG_EXT_SENS_DATA_18 = 0x5B; MPU6050_REG_EXT_SENS_DATA_19 = 0x5C; MPU6050_REG_EXT_SENS_DATA_20 = 0x5D; MPU6050_REG_EXT_SENS_DATA_21 = 0x5E; MPU6050_REG_EXT_SENS_DATA_22 = 0x5F; MPU6050_REG_EXT_SENS_DATA_23 = 0x60; MPU6050_REG_MOT_DETECT_STATUS= 0x61; MPU6050_REG_I2C_SLV0_DO = 0x63; MPU6050_REG_I2C_SLV1_DO = 0x64; MPU6050_REG_I2C_SLV2_DO = 0x65; MPU6050_REG_I2C_SLV3_DO = 0x66; MPU6050_REG_I2C_MST_DELAY_CTRL= 0x67; MPU6050_REG_SIGNAL_PATH_RESET= 0x68; MPU6050_REG_MOT_DETECT_CTRL= 0x69; MPU6050_REG_USER_CTRL = 0x6A; MPU6050_REG_PWR_MGMT_1 = 0x6B; MPU6050_REG_PWR_MGMT_2 = 0x6C; MPU6050_REG_BANK_SEL = 0x6D; MPU6050_REG_MEM_START_ADDR = 0x6E; MPU6050_REG_MEM_R_W = 0x6F; MPU6050_REG_DMP_CFG_1 = 0x70; MPU6050_REG_DMP_CFG_2 = 0x71; MPU6050_REG_FIFO_COUNTH = 0x72; MPU6050_REG_FIFO_COUNTL = 0x73; MPU6050_REG_FIFO_R_W = 0x74; MPU6050_REG_WHO_AM_I = 0x75; endproperties properties(Access = private) i2c; caldata = {}; endproperties # matlab compatible properties properties (SetAccess = private) I2CAddress = ""; Bus = 0; endproperties methods # constructor function this = mpu6050(parentObj, varargin) if nargin < 1 || ! isarduino(parentObj) error('Expected arduino object as first parameter'); endif # parse args p = inputParser(CaseSensitive=false, FunctionName='arduinosensor.SI7021'); p.addParameter('I2CAddress', 0x68, @isnumeric); # matlab default is 0x28 p.addParameter('Bus', 0, @isnumeric); p.parse(varargin{:}); # do we have the address ? address = p.Results.I2CAddress; bus = p.Results.Bus; this.i2c = device(parentObj, "i2caddress", p.Results.I2CAddress, 'Bus', bus); # verify what talking to id = this.readRegisterU8(this.MPU6050_REG_WHO_AM_I) pause(.1) id = this.readRegisterU8(this.MPU6050_REG_WHO_AM_I) if id != 0x68 && id != 0x69 error ("Invalid id '%X' read for sensor", id) endif # init # set gyro 250deg/s this.writeRegister(this.MPU6050_REG_GYRO_CONFIG, 0x00); # set accel scale to 2g this.writeRegister(this.MPU6050_REG_ACCEL_CONFIG, 0x00); # set awake, use gyro x pll clock this.writeRegister(this.MPU6050_REG_PWR_MGMT_1, 0x01); endfunction function inf = info (this) inf = {}; inf.Type = "mpu6050"; inf.SensorId = this.readRegisterU8(this.MPU6050_REG_WHO_AM_I); #inf.Status = this.readRegisterU8(this.BNO055_REG_ACC_ID); endfunction function [C, timestamp] = readTemperature (this) timestamp = time(); C = single(this.readRegisterS16(this.MPU6050_REG_TEMP_OUT_H)) / 340.0 + 36.53; endfunction function [readVal, timestamp] = readAcceleration (this) data = this.readRegister(this.MPU6050_RA_ACCEL_XOUT_H, 6); timestamp = time(); x = typecast(uint16(data(1))*256 + uint16(data(2)), 'int16'); y = typecast(uint16(data(3))*256 + uint16(data(4)), 'int16'); z = typecast(uint16(data(5))*256 + uint16(data(6)), 'int16'); # 2g scale readVal = single([x y z])/16384.0; endfunction function [readVal, timestamp] = readAngularVelocity (this) data = this.readRegister(this.MPU6050_REG_GYRO_XOUT_H, 6); timestamp = time(); x = typecast(uint16(data(2))*256 + uint16(data(1)), 'int16'); y = typecast(uint16(data(4))*256 + uint16(data(3)), 'int16'); z = typecast(uint16(data(6))*256 + uint16(data(4)), 'int16'); # 250 deg/s range readVal = single([x y z])/131.0; endfunction function varargout = read(this) data = readData(this); timestamp = time(); accel = this.readAcceleration(); avel = this.readAngularVelocity(); if nargout <= 2 varargout{1} = struct('Time', timestamp, 'Acceleration', accel, 'AngularVelocity', avel); if nargout > 1 varargout{2} = 0; # no overrun endif else if nargout > 0 varargout{1} = accel; endif if nargout > 1 varargout{2} = avel; endif if nargout > 2 varargout{3} = timestamp; endif if nargout > 3 varargout{4} = 0; # overrun endif endif endfunction function flush(this) # flush currenly does nothing endfunction function disp(this) printf(" %s with properties\n", class(this)); if isobject(this.i2c) printf(" I2CAddress: %d ('0x%s')\n", this.i2c.i2caddress, num2hex(this.i2c.i2caddress)); printf(" Bus: %d\n", this.i2c.bus); else printf(" Not connected"); endif endfunction function release(this) if isobject(this.i2c) delete(this.i2c); this.i2c = []; endif endfunction function delete(this) try if isobject(this.i2c) delete(this.i2c); this.i2c = []; endif catch # do nothing end_try_catch endfunction endmethods methods (Hidden = true) function v = get.I2CAddress (this) v = sprintf("0x%02X", this.i2c.I2CAddress); endfunction function v = get.Bus (this) v = this.i2c.Bus; endfunction endmethods methods (Access = private) function data = readRegister(this, reg, sz) data = readRegister(this.i2c, reg, sz); endfunction function writeRegister(this, reg, data) writeRegister(this.i2c, reg, data); endfunction function value = readRegisterU16(this, reg) data = readRegister(this, reg, 2); value = uint16(data(1))*256 + uint16(data(2)); endfunction function value = readRegisterS16(this, reg) data = readRegister(this, reg, 2); value = uint16(data(1))*256 + uint16(data(2)); value = typecast(value, 'int16'); endfunction function value = readRegisterU8(this, reg) data = readRegister(this, reg, 1); value = uint8(data(1)); endfunction function value = readRegisterS8(this, reg) data = readRegister(this, reg, 1); value = uint8(data(1)); value = typecast(value, 'int8'); endfunction endmethods endclassdef %!error mpu6050(1); arduino-0.12.1/inst/sensors/si7021.m0000644000000000000000000002003114545566645013756 0ustar00## Copyright (C) 2019-2022 John Donoghue ## ## 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 ## . classdef si7021 < handle ## -*- texinfo -*- ## @deftypefn {} {} si7021 ## SI7021 temperature and humidity sensor ## @end deftypefn ## ## @subheading Methods ## @deftypefn {} {@var{obj} =} si7021(@var{arObj}) ## @deftypefnx {} {@var{obj} =} si7021(@var{arObj}, @var{propertyname, propertyvalue} ....) ## Constructor to create si7021 sensor ## @subsubheading Inputs ## @var{arObj} - the arduino parent object ## ## @var{propertyname, propertyvalue} - optional property name, value pairs. ## Current known properties are: ## Current properties are: ## @table @asis ## @item I2Caddress ## I2C address of the si7021 (default 0x40) ## @item Bus ## I2C bus (default 0) ## @end table ## ## @subsubheading Outputs ## @var{obj} - created SI7020 object ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## sensor = si7021(a) ## } ## @end example ## @end deftypefn ## ## @deftypefn {} {[@var{C}, @var{timestamp}] =} readTemperature(@var{obj}) ## Read the temperature ## ## @subsubheading Inputs ## @var{obj} - the si7021 object ## ## @subsubheading Outputs ## @var{C} - read temperature in deg C. ## ## @var{timestamp} - timestamp when read ## ## @subsubheading Example ## @example ## @code { ## a = arduino() ## s = si7021(a) ## # get temp ## temp = s.readTemperature() ## } ## @end example ## @seealso{si7021} ## @end deftypefn ## ## @deftypefn {} {[@var{relH}, @var{timestamp}] =} readHumidity(@var{obj}) ## Read the relative humidity ## ## @subsubheading Inputs ## @var{obj} - the si7021 object ## ## @subsubheading Outputs ## @var{relH} - relative humidity as a percentage (0 - 100.0) ## ## @var{timestamp} - timestamp when read ## @end deftypefn ## ## @deftypefn {} {[@var{readings}, @var{overrun}] =} read(@var{obj}) ## @deftypefnx {} {[@var{H}, @var{C}, @var{timestamp}, @var{overrun}] =} read(@var{obj}) ## Read the sensor data ## ## @subsubheading Inputs ## @var{obj} - the si2071 sensor object ## ## @subsubheading Outputs ## @var{H} - humidity reading from sensor. ## ## @var{C} - temperature reading from sensor. ## ## @var{timestamp} - timestamp when read ## ## @var{overrun} - overrun flag. ## ## @var{readings} - table structure with fields for Timestamp, Temperature and Humidity. ## @end deftypefn ## ## @deftypefn {} {@var{relH} =} info(@var{dsObj}) ## Read the sensor info ## ## @subsubheading Inputs ## @var{dsObj} - the si7021 object ## ## @subsubheading Outputs ## @var{inf} - structure containing the sensor information. ## ## Structure fields are: ## @table @asis ## @item Version ## Chip firmware version ## @item SensorDd ## sensor id value ## @item Type ## String for detected chip type ## @end table ## ## @end deftypefn ## ## @deftypefn {} {} flush(@var{obj}) ## Flush sensor data ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## None ## @end deftypefn ## ## @deftypefn {} {} release(@var{obj}) ## Release the resources of the sensor ## ## @subsubheading Inputs ## @var{obj} - the sensor object ## ## @subsubheading Outputs ## None ## @end deftypefn properties(Access = private, constant = true) SI7021_CHIPID_1 = [ 0xFA 0xF0 ]; SI7021_CHIPID_2 = [ 0xFC 0xC9 ]; SI7021_VERSION = [ 0x84 0xB8 ]; SI7021_TEMP_MEASURE_NOHOLD = 0xF3; SI7021_HUMIDITY_MEASURE_NOHOLD = 0xF5; endproperties properties(Access = private) i2c; endproperties methods # constructor function this = si7021(parentObj, varargin) if nargin < 1 || ! isarduino(parentObj) error('Expected arduino object as first parameter'); endif # parse args p = inputParser(CaseSensitive=false, FunctionName='arduinosensor.si7021'); p.addParameter('I2CAddress', 0x40, @isnumeric); p.addParameter('Bus', 0, @isnumeric); p.parse(varargin{:}); # do we have the address ? address = p.Results.I2CAddress; bus = p.Results.Bus; #i2caddresses = scanI2Cbus(parentObj); #idx = find(cellfun ( @(x) strcmp(x, sprintf("0x%02X", address)), i2caddresses)); #if isempty(idx) # error('No matching i2c address found on bus'); #endif this.i2c = device(parentObj, "i2caddress", p.Results.I2CAddress, 'bus', bus); endfunction function inf = info (this) write (this.i2c, this.SI7021_CHIPID_1); id1 = read(this.i2c, 1); write (this.i2c, this.SI7021_CHIPID_2); id2 = read(this.i2c, 1); if id2 == hex2dec("15") type = "Si7021"; elseif id2 == hex2dec("14") type = "Si7020"; elseif id2 == hex2dec("0D") type = "Si7013"; elseif id2 == hex2dec("32") type = "HTU21D"; else type = "Unknown"; endif write (this.i2c, this.SI7021_VERSION); ver = read(this.i2c, 1); if ver == hex2dec("FF") ver = 1.0; else ver = double(ver)/10.0; endif inf = {}; inf.Version = ver; inf.Type = type; inf.Sensor = int32(id1)*256 + int32(id2); endfunction function [C, timestamp] = readTemperature (this) % write command to get temp write (this.i2c, uint8([this.SI7021_TEMP_MEASURE_NOHOLD])); timestamp = time(); pause (0.02); data = read (this.i2c, 3); value = uint16(data(1))*256 + uint16(data(2)); value = bitand (value, hex2dec("FFFC")); temp = double(value); C = (175.72*temp/65536)-46.85; endfunction function [H, timestamp] = readHumidity(this) write (this.i2c, uint8([this.SI7021_HUMIDITY_MEASURE_NOHOLD])); timestamp = time(); pause (0.02); data = read (this.i2c, 3); value = uint16(data(1))*256 + uint16(data(2)); value = bitand (value, hex2dec("FFFC")); humidity = double(value); H = (125.0*humidity/65536)-6; endfunction function varargout = read(this) timestamp = time(); C = readTemperature(this); H = readHumidity(this); if nargout <= 2 varargout{1} = struct('Time', timestamp, 'Temperature', C, 'Humidity', H); if nargout > 1 varargout{2} = 0; # no overrun endif else if nargout > 0 varargout{1} = H; endif if nargout > 1 varargout{2} = C; endif if nargout > 2 varargout{3} = timestamp; endif if nargout > 3 varargout{4} = 0; # overrun endif endif endfunction function flush(this) # flush currenly does nothing endfunction function disp(this) printf(" %s with properties\n", class(this)); if isobject(this.i2c) printf(" I2CAddress: %d ('0x%s')\n", this.i2c.i2caddress, num2hex(this.i2c.i2caddress)); printf(" Bus: %d\n", this.i2c.bus); else printf(" Not connected"); endif endfunction function release(this) if isobject(this.i2c) delete(this.i2c); this.i2c = []; endif endfunction function delete(this) try if isobject(this.i2c) delete(this.i2c); this.i2c = []; endif catch # do nothing end_try_catch endfunction endmethods endclassdef %!error si7021(1); arduino-0.12.1/octave-arduino.metainfo.xml0000644000000000000000000000225414545566645015454 0ustar00 octave-arduino www.octave.org-octave.desktop Arduino Toolkit

Octave to Arduino interface toolkit

Basic Octave implementation of the matlab arduino extension, allowing communication to a programmed arduino board to control its hardware.

arduino communication http://octave.sourceforge.net/arduino https://savannah.gnu.org/bugs/?func=additem&group=octave GPL-3.0+ Octave-Forge Community octave-maintainers@gnu.org FSFAP arduino-0.12.1/test/0000755000000000000000000000000014545566645011165 5ustar00arduino-0.12.1/test/make_conf.m0000644000000000000000000001351014545566645013265 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . #Usage: octave --eval "make_conf('/usr/share/arduino/hardware/arduino/avr/variants/mega/pins_arduino.h')" function retval = make_conf (header_file) if nargin != 1 error ('Expected single input argument of header filename') endif pins = {}; ispwm = {}; isalong = {}; num_digital_pins = 0; num_analog_pins = 0; fd = fopen (header_file, "rt"); while !feof(fd) l = fgetl(fd); [t, m] = regexp(l, '#define\s+(\w+)\s+([^\s]+)$', 'tokens', 'match'); if !isempty(t) toks = t(1){1}; if numel(toks) == 2 if strcmpi(toks{1}, "NUM_DIGITAL_PINS") cnt = strrep(toks{2}, "u", ""); num_digital_pins = str2num(cnt); elseif strcmpi(toks{1}, "NUM_ANALOG_INPUTS") cnt = strrep(toks{2}, "u", ""); num_analog_pins = str2num(cnt); else idx = index(toks{1}, "PIN_"); if idx > 0 name = tolower(strtrim(toks{1}(idx+4:end))); # id have other crap in it ? id = strrep(toks{2}, "u", ""); id = str2num(id); if !isempty(id) # we have pin already ? idx = find (cellfun(@(x) (x.id == id), pins), 1); if isempty(idx) p = []; p.id = id; p.name = sprintf("D%d", id); p.modes = { 'digital' }; pins{end+1} = p; idx = numel(pins); endif if name(1) == 'a' pins{idx}.name = toupper(name); pins{idx}.modes{end+1} = "analog"; elseif strncmp(name, "wire_", 5) pins{idx}.modes{end+1} = ["i2c" name(5:end)]; elseif strncmp(name, "pin_led_", 8) pins{idx}.modes{end+1} = ["led"]; else pins{idx}.modes{end+1} = name; endif endif elseif strcmp(toks{1}, "LED_BUILTIN") id = str2num(toks{2}); if !isempty(id) idx = find (cellfun(@(x) (x.id == id), pins), 1); if isempty(idx) p = {}; p.id = id; p.name = sprintf("D%d", id); p.modes = { 'digital' }; pins{end+1} = p; idx = numel(pins); endif pins{idx}.modes{end+1} = "led"; endif endif endif endif endif [t, m] = regexp(l, '#define\s+digitalPinHasPWM\((\w+)\)\s+(.*)$', 'tokens', 'match'); if ! isempty(t) toks = t(1){1}; if numel(toks) == 2 ispwm.var = toks{1}; testv = strrep(toks{2}, "u", ""); ispwm.test = testv; ispwm = {}; endif endif [t, m] = regexp(l, '#define\s+analogInputToDigitalPin\((\w+)\)\s+(.*)$', 'tokens', 'match'); if ! isempty(t) toks = t(1){1}; if numel(toks) == 2 isanalog.var = toks{1}; testv = strrep(toks{2}, "u", ""); # simple expect analog after digital testv = sprintf("(p + %d)", num_digital_pins); isanalog.test = testv; #isanalog={}; endif endif endwhile fclose(fd); #num_digital_pins #num_analog_pins # fill in any missing digitals for i=0:num_analog_pins-1 name = sprintf("A%d", i); idx = find (cellfun(@(x) (strcmpi(x.name,name)), pins), 1); if isempty(idx) t = sprintf("%s=%i; id=(%s);", isanalog.var, i, isanalog.test); eval(t); if id >= 0 p = {}; p.id = id; p.name = sprintf("A%d", i); p.modes = { 'digital', 'analog' }; pins{end+1} = p; idx = numel(pins); endif endif endfor # fill in any missing digitals for i=0:num_digital_pins-1 idx = find (cellfun(@(x) (x.id == i), pins), 1); if isempty(idx) p = {}; p.id = i; p.name = sprintf("D%d", i); p.modes = { 'digital' }; pins{end+1} = p; idx = numel(pins); endif if !isempty(ispwm) t = sprintf("%s=%i; pwm=(%s);", ispwm.var, i, ispwm.test); eval(t); if pwm pins{idx}.modes{end+1} = "pwm"; endif endif endfor # sort by pin num (id) [tmp ind]=sort(cellfun(@(x) (x.id), pins)); # output file printf ("# configuration generated from %s\n", header_file) printf("function retval = config_XXX (initdata)\n"); printf(" retval = {};\n"); printf("\n"); printf(" # default board info - must be provided\n"); printf(" # will be filled in on connection.\n"); printf(" retval.board = '';\n"); printf(" retval.baudrate = 9600;\n"); printf(" retval.mcu = '';\n"); printf(" retval.voltref = 0;\n"); printf(" retval.libs = {};\n"); printf(" retval.port = '';\n"); printf("\n"); printf(" # info expected to be provided by config.\n"); printf(" retval.description = 'a board description';\n"); printf("\n"); printf(" # pin config\n"); printf(" retval.pins = {};\n"); for i = 1:numel(ind) p = pins{ind(i)}; modes = [ "'" p.modes{1} "'"]; for m = 2:numel(p.modes) modes = [ modes ", '" p.modes{m} "'" ]; endfor printf(" retval.pins{end+1} = arduinoio.config.pin_info('%s', %d, { %s });\n", p.name, p.id, modes); endfor printf("endfunction\n"); endfunction arduino-0.12.1/test/test_exampleplugin.m0000644000000000000000000000152214545566645015254 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . #arduinosetup ('libraries', 'ExampleAddon/Echo') a = arduino(); b = addon(a, "ExampleAddon/Echo") b.shout("Hello") b.shout("World") arduino-0.12.1/test/test_jig.m0000644000000000000000000002354114545566645013160 0ustar00## Copyright (C) 2018 John Donoghue ## ## 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 ## . % test_jig % expects a arduino uno to be connected via serial port % with test connections as folows: % arduino - 24XX256 EEPROM chip (i2c) % arduino - mcp3002 10 bit ADC (spi) % arduino - hobby servo % % Connection of arduino to test jig as follows: % Arduino % 24XX256 eeprom % A4 - 5 % A5 - 6 % 5V - 8 % GND - 1,2,3,4 % % Arduino MCP3002 % D10 - 1 (CS) % D11 - 5 (DI) % D12 - 6 (DO) % D13 - 7 (CLK) % VCC - 8 (VDD) % GND - 4 (VSS) % VCC 2 (CH0) - chan 0 input % D2 3 (CH1) - chan 1 input % Servo % Arduino Servo % d9 - signal % VCC - power % gnd - gnd % I/O % Arduino Arduino % A3 - D3 % D4 - D5 % D7 - Not connected % D6 - +10UF cap - GND % A0 - D6 pkg load instrument-control [~, ~, endian] = computer (); unwind_protect printf("1. opening arduino\n"); a = arduino(); if isempty(a) printf("** open failied **\n") endif assert(~isempty(a)) printf("2. I2C tests with EEPROM\n"); eeprom_address = 0x50; printf("* i2c terminals\n") terms = getI2CTerminals(a); if isempty(terms) printf("** getI2CTerminals failed **\n") endif printf("* i2c devices attached\n") devs = scanI2Cbus(a); idx = find(devs = eeprom_address); if isempty(idx) error ('scanI2bus failed - skipping eeprom tests') else printf("* opening i2c...\n"); #i2c = i2cdev(a, eeprom_address); i2c = device(a, "i2caddress", eeprom_address); if isempty(i2c) printf("** i2cdev failed **\n") endif printf("* writing i2c bytes...\n"); # write data to address 0x0000 write(i2c, [0 0 0 1 2 3 4 5 6 7 8 9 10]); # read from address 0x0000, which should now be 0 1 2 3 4 5 6 7 printf("* reading i2c 0000 bytes...\n"); write(i2c, uint8([0 0])); val = read(i2c, 8); if val != uint8([0 1 2 3 4 5 6 7]) printf("byte read/write failed!\n"); endif printf("* reading i2c 0002 bytes...\n"); write(i2c, uint8([0 2])); val = read(i2c, 8); if val != uint8([2 3 4 5 6 7 9 10]) printf("byte read/write failed!\n"); endif printf("* reading i2c 0002 uint16...\n"); write(i2c, uint16([2]), 'uint16'); val = read(i2c, 4, 'uint16'); expected = typecast(uint8([2 3 4 5 6 7 8 9]), 'uint16'); if endian == 'L' expected = swapbytes(expected); endif if val != expected printf("uint16 read failed!\n"); endif printf("* reading i2c 0000 uint16 as register...\n"); val = readRegister(i2c, 0, 2, 'uint16'); expected = typecast(uint8([0 1 2 3]), 'uint16'); if endian == 'L' expected = swapbytes(expected); endif if val != expected printf("read reg16 failed!\n"); endif printf("* reading i2c 0001 uint16 as register...\n"); val = readRegister(i2c, 1, 2, 'uint16'); expected = typecast(uint8([1 2 3 4]), 'uint16'); if endian == 'L' expected = swapbytes(expected); endif if val != expected printf("read reg16 failed!\n"); endif printf("* writing i2c uint16 reg...\n"); writeRegister(i2c, 258, [8 9], 'uint16') printf("* reading i2c 0102 bytes...\n"); write(i2c, uint8([1 2])); val = read(i2c, 4); if val != uint8([0 8 0 9]) printf("byte read/write failed!\n"); endif printf("* reading i2c 0102 uint16 as register...\n"); val = readRegister(i2c, 258, 2, 'uint16'); expected = [8 9]; if val != expected printf("read reg16 failed!\n"); endif clear i2c; endif printf("3. SPI tests with ADC\n"); printf("* opening spi...\n"); #spi = spidev(a, "d10"); spi = device(a, "spichipselectpin", "d10"); if isempty(spi) printf("** spi failed **\n") endif # chan0 printf("* reading spi chan 0...\n"); val = writeRead(spi, [ hex2dec("DF") hex2dec("FF") ]); val = writeRead(spi, [ hex2dec("DF") hex2dec("FF") ]); adc = bitand (uint16(val(1))*256 + uint16(val(2)), hex2dec('3FF')); volts = double(adc) * 5.0 / 1023.0; if volts < 4.5 || volts > 5.0 printf("unexpected voltage ch0 = 0x%04X (adc) %f (volts)\n", adc, volts) endif # chan 1 printf("* reading spi chan 1 low...\n"); writeDigitalPin(a, "d2", 0); val = writeRead(spi, [ hex2dec("EF") hex2dec("FF") ]); adc = bitand (uint16(val(1))*256 + uint16(val(2)), hex2dec('3FF')); volts = double(adc) * 5.0 / 1023.0; if volts > 0.5 printf("unexpected voltage ch1 = 0x%04X (adc) %f (volts)\n", adc, volts) endif printf("* reading spi chan 1 high...\n"); writeDigitalPin(a, "d2", 1); val = writeRead(spi, [ hex2dec("EF") hex2dec("FF") ]); adc = bitand (uint16(val(1))*256 + uint16(val(2)), hex2dec('3FF')); volts = double(adc) * 5.0 / 1023.0; if volts < 4.5 printf("unexpected voltage ch1 = 0x%04X (adc) %f (volts)\n", adc, volts) endif # other SPI tests ?? clear spi printf("4. Digital I/O\n"); printf("* reading analog high to d3...\n"); writeDigitalPin(a, "a3", 1); pause(1); val = readDigitalPin(a, "d3"); if val != 1 printf("unexpected 33 value %d\n", val); endif val = readDigitalPin(a, "a3"); if val != 1 printf("unexpected A3 value %d\n", val); endif printf("* reading analog low to d3...\n"); writeDigitalPin(a, "a3", 0); pause(1); val = readDigitalPin(a, "d3"); if val != 0 printf("unexpected D3 value %d\n", val); endif val = readDigitalPin(a, "a3"); if val != 0 printf("unexpected A3 value %d\n", val); endif printf("* reading digital low to d4...\n"); writeDigitalPin(a, "d4", 0); pause(1); val = readDigitalPin(a, "d4"); if val != 0 printf("unexpected d4 value %d\n", val); endif val = readDigitalPin(a, "d5"); if val != 0 printf("unexpected d5 value %d\n", val); endif printf("* reading digital high to d4...\n"); writeDigitalPin(a, "d4", 1); pause(1); val = readDigitalPin(a, "d4"); if val != 1 printf("unexpected d4 value %d\n", val); endif val = readDigitalPin(a, "d5"); if val != 1 printf("unexpected d5 value %d\n", val); endif printf("5. Analog input\n"); configurePin(a, "d3", "unset"); writeDigitalPin(a, "d3", 0); configurePin(a, "a3", "unset"); pause(1); printf("* reading analog low a3...\n"); val = readAnalogPin(a, "a3"); if val > 200 printf("unexpected a3 value %d\n", val); endif val = readVoltage(a, "a3"); if val > 0.5 printf("unexpected a3 value %f\n", val); endif printf("* reading analog high a3...\n"); writeDigitalPin(a, "d3", 1); pause(1); val = readAnalogPin(a, "a3"); if val < 1000 printf("unexpected a3 value %d\n", val); endif val = readVoltage(a, "a3"); if val < 4.5 printf("unexpected a3 value %f\n", val); endif printf("6. Pullup I/O\n"); printf("* pullup d7...\n"); configurePin(a, "d7", "pullup"); val = readDigitalPin(a, "d7"); if val != 1 printf("unexpected d7 value %d\n", val); endif # analog output /PWM printf("7. Analog Output\n"); printf("* pwm duty cycle 0...\n"); writePWMDutyCycle(a, "d6", 0); pause(1); val = readVoltage(a, "a0"); if val > 0.1 printf("unexpected a0 value %f\n", val); endif printf("* pwm duty cycle 1...\n"); writePWMDutyCycle(a, "d6", 1); pause(1); val = readVoltage(a, "a0"); if val < 4.5 printf("unexpected a0 value %f\n", val); endif printf("* pwm duty cycle 0.5...\n"); writePWMDutyCycle(a, "d6", 0.5); pause(1); val = readVoltage(a, "a0"); if val < 2.0 || val > 3.0 printf("unexpected a0 value %f\n", val); endif printf("* pwm voltage 0...\n"); writePWMVoltage(a, "d6", 0.0); pause(1); val = readVoltage(a, "a0"); if val > 0.2 printf("unexpected a0 value %f\n", val); endif printf("* pwm voltage 5...\n"); writePWMVoltage(a, "d6", 5.0); pause(1); val = readVoltage(a, "a0"); if val < 4.5 printf("unexpected a0 value %f\n", val); endif printf("* pwm voltage 3...\n"); writePWMVoltage(a, "d6", 3.0); pause(1); val = readVoltage(a, "a0"); if val < 2.4 || val > 4.0 printf("unexpected a0 value %f\n", val); endif # TODO: servo printf("8. Servo\n"); printf("* create servo...\n"); s = servo(a, "d9", 'MinPulseDuration', 1e-3, 'MaxPulseDuration', 2e-3); if isempty(s) printf("** servo failied **\n") endif printf("* go min pos...\n"); writePosition(s, 0); val = readPosition(s); if val != 0 printf("invalid position %f\n", val); endif printf("* scan pos...\n"); for pos = [0:.01:1] writePosition(s, pos); pause(0.02); endfor printf("* go max pos...\n"); writePosition(s, 1); val = readPosition(s); if val != 1 printf("invalid position %f - expected %f\n", val, 1); endif printf("9. LEDS\n"); printf("* get pins...\n"); leds = getPinsFromTerminals(a, getLEDTerminals(a)); if isempty(leds) printf("no LED pins"); endif printf("* set leds 0\n"); for i = [1:1:numel(leds)] pin = leds{i}; configurePin(a, pin, "unset"); writeDigitalPin(a, pin, 0) endfor pause(2); printf("* set leds 1\n"); for i = [1:1:numel(leds)] pin = leds{i}; writeDigitalPin(a, pin, 1) endfor pause(2); printf("* set leds 0\n"); for i = [1:1:numel(leds)] pin = leds{i}; writeDigitalPin(a, pin, 0) endfor unwind_protect_cleanup clear a end_unwind_protect