arduino-0.8.0/0000755000000000000000000000000014171012362011343 5ustar0000000000000000arduino-0.8.0/COPYING0000644000000000000000000010451314171012362012402 0ustar0000000000000000 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.8.0/DESCRIPTION0000644000000000000000000000100314171012362013043 0ustar0000000000000000Name: arduino Version: 0.8.0 Date: 2022-01-16 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.3.0) SystemRequirements: arduino-ide (>= 1.5) License: GPLv3+ Url: https://octave.sourceforge.io/arduino/ arduino-0.8.0/INDEX0000644000000000000000000000642514171012362012144 0ustar0000000000000000arduino >> Arduino Toolkit General Functions arduinosetup isarduino listArduinoLibraries scanForArduinos Arduino Functions @arduino/checkI2CAddress @arduino/configurePin @arduino/configurePinResource @arduino/decrementResourceCount @arduino/delete @arduino/display @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/display @i2cdev/read @i2cdev/readRegister @i2cdev/subsref @i2cdev/write @i2cdev/writeRegister @i2cdev/i2cdev @device/delete @device/display @device/read @device/readRegister @device/subsref @device/write @device/writeRegister Arduino Rotary Encoder Functions @rotaryEncoder/delete @rotaryEncoder/display @rotaryEncoder/readCount @rotaryEncoder/readSpeed @rotaryEncoder/resetCount @rotaryEncoder/subsref @rotaryEncoder/rotaryEncoder Arduino Servo Functions @servo/delete @servo/display @servo/readPosition @servo/subsref @servo/writePosition @servo/servo Arduino Shiftregister Functions @shiftRegister/delete @shiftRegister/display @shiftRegister/read @shiftRegister/reset @shiftRegister/write @shiftRegister/subsref @shiftRegister/shiftRegister Arduino SPI Functions @spidev/delete @spidev/display @spidev/subsref @spidev/writeRead @spidev/spidev @device/delete @device/display @device/subsref @device/writeRead Arduino Serial Functions @device/delete @device/display @device/flush @device/read @device/subsref @device/write @device/device Arduino Device Functions @device/delete @device/display @device/flush @device/read @device/readRegister @device/subsref @device/write @device/writeRead @device/writeRegister @device/device Arduino Ultrasonic Functions @ultrasonic/delete @ultrasonic/display @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 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 Compatability Classes matlabshared.addon.LibraryBase Test Functions arduino_bistsetup arduino-0.8.0/NEWS0000644000000000000000000001037114171012362012044 0ustar0000000000000000Summary 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.8.0/README.md0000644000000000000000000000637014171012362012630 0ustar0000000000000000
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 * leonardo * lilypad * mega2560 * micro * mkrzero * mkr1000 * nano * nano every * nano 33 ble * nano rp2040 connect * promini * promicro * raspberry pi pico * sparkfunsamd21 * uno wifi rev2 * 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.8.0/doc/0000755000000000000000000000000014171012362012110 5ustar0000000000000000arduino-0.8.0/doc/arduino.pdf0000644000000000000000000126255514171012362014264 0ustar0000000000000000%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 /EP!PX!M!cZ@Hؾ3F2AdN1<:6b8,B~A0SVtDW! uqrSՋgsvG|ŲBgx]S-y<> ʇzZя`?pp -a 2q(!AjÌ 0 !׸mWMF/G׼~M~ܴYiU>t]`o% <O0E׳)i[z(]Uҁt 17Njc<\5M@ȒP݊ endstream endobj 13 0 obj << /Length 622 /Filter /FlateDecode >> stream xڍSn0+tHE|#r* HAQ.]r~F p;;;fQ?yT7n&kT??Ge5LyNyVӌC뫼_+1-+\L}V&ɳ<&Y;=k$J$ʴn(aU.AI-ecoFۼ&!*N-֨=EX5!꣒ fΞ1>nYl+rRݙ %?\c Ǻ2kZ ]1w7*}c$eHswx8LϴSPm WaP>jJIA:)B$k\Cw Fy׹M#=SwŶTu5> i5m@P퐰`AX|Pe(%"WuY \+F` jC&zo6na] m@k`&" )\]g1@&XitӘte@.WN5Qwx~[8%+50 iߣUមg;k/b <$7z m ൭?q endstream endobj 19 0 obj << /Length 1062 /Filter /FlateDecode >> stream xڕVݏ6߿`cǮZUJNXM,aFHd<ols4v͊%*u%`fuQ'H I"' Vd"C!YZh2O}Me>WCyZKWiq]Y?+roi+"e wΘ 9In@)auuxBg/_Za0vG[aŧ޸Ga^J!៓_ğ"vc(%U.臱 ʦ&ž: bWc(p2eOʁto6>7E+A8!Ac(;g< Jj"{'O K γ{ ,+nmO(%z'%~m Nad> Uć\)~_7$h+^:Y\8cԴuBD8|'_<Yt[H!g lզƻ'Z⚦Ib r[P肂W{<pQPlD)PL7@ K "gESo8P*{3̽A7ˆgNVv8e5C2;_Ob~2q%dV"3 mE1xړoݞn ru$SIziqs|Pd"`ݦ۲0HKc]Mk!avE[?/~ٞgp2-t50C'x82 #ޕOc_D?ߗBfa t`Wei"/Bw^03qY1D]ͱ-kqSױfE2oa˛'hjqCfuє!XZ7MTQE`~7DJy6fitfBh/MI9vtٵnoXcM|+д*g~,Az=7 endstream endobj 69 0 obj << /Length 2646 /Filter /FlateDecode >> stream xK8^ B򨙩S7ݳ 6Uau+|W1叮,C1] C ^7r5募E QSZD6v۲X/.@PY`VQ.H(JT >/|fq\1輕'[UcU{+rYU8:L=ZyLUi0T뫪!3O ';uϠq`ј\AOy#L@yk9Y-2Ur""\s 8"Uu\l3*|`әryO ]WR8LWD^%a jHnwj-d۪_ІW1<* +J,`0!՛˱V?C=SshCtt|20e"oj#&31ޢG{/rҕ:4H&%'8\,!%x$)8 S[ L2˭_C^ 1=Nyy%hD>@P 7(&D"#w!hin:!X$;+\LF' hL44x"4/C0y ͗)HRK -0)xS[)0x;;ZН21|:'r9a .OE `BT0H}4Sϰj1zv[x1Dt9;=HAT50?L=Z%?HfES j&P~qd&uӲ2rC2qc8rOm ۩nkgurHA-ڊE-3t+ &D$ɂ tCt qm)fY8myR_\w=ϧG\4ʍW3ןE:-4it+A]>6LHۼO^Kt޻>!tn`Bxnyg;Y lb|nW9׫z50F ~v F7w3-mJ2+eG+2C>lY޵#NUceNlRostF&_Dז_[=@wq 3] ]@ фěwmv/W=uS$R6ǰĢL(D'ގ ׈NR>j)bRIB{DC>?0[.é~i{x  5i4|M &s[TݍC ^+1Tg @yZo:_k^ `4!uٛJN9ZE>rauϷ c98H59{5lJ S;]۝}f|;/sz/Ɇg .x?073H> stream xOs6{>(ff6x=r֖2N w]oºPU\^dSwqIԭ"z|=?ǽW._/- t IЍCw~Uo^/|,MȯX,[]k{8RPJ f,*"L0W#nanoMבd0ZfO+ch|!&AȂjR̢=Z -cjwou~k'xoe=|6*cq$hnQB_^rp\qg|*s,o|!B2T2xI }w.6Eqv mϚa7짹5Ke`&@b_?ZN8ݷ m2XBKPM K4RVhK9ƲYnrS2:q6ca|R1&13HwqowIW_Z:sabդ`Fs{ڸ+#q7\]+P 7Wvʧ`!"&"STs}@ьPLډ!.7} 1} 0TyJF(+\"<DzniV_ULaNo|!F:JTBirC؂o?Ut{̷`V*&*[U>LntGMcOaZnh߀FC(tդEs{2`[}<;aܗ\s2}Sk 0mmmhAH8 A/Moo߭;;]ԱrN6Vޏp$E{FjŃĮ7RHWF'ߏ2XbORw;L'~,|C cr&7JCQIa%ۜbP/ݟU]>o|!fÂjR̢YeЬ~WU_ o -6B8 XA5)XV^i"4Za1"2IТhA8<+XMZ  a5)TܞhBqH5S`{um}K[*]Cs 0qqqhn/NP. n?o),w@Vvun(LD Iэ!OӾ̔ί|=UYSΎv3C2PդPFs{Ts4PC_,#9oG?x⠚h81@m%\ޏX^TA) RR;LQ}vwBvI3vg`!}1&E"StÝUbxzWU@|1o|! AtjRtOcmg=N1i`oyǂu{Lgl >Cy"BXM z4%Je"|ע\>c<|!C܃jRܣ{rI{GӳyщLqzCL=դGs{ICbO}h{UJx8ȷ`?>&>{3}9BC}լ7׸5\;r#ΦޏHA) cHcx}ۺ?,, Hs^C~:$'$XG '`]Y^,?5擺E' >RÇ>HJLIϥ>G+>ox?Q0(EE J endstream endobj 9 0 obj << /Type /ObjStm /N 100 /First 832 /Length 2274 /Filter /FlateDecode >> stream xڵZ[[~ׯcBq83F$-V]dEH0dR!s'fGQ"Gb 㨎ԉ4'X] d|]%ݥ(v4٘b01a"QTx$dT@q@!HĠBrBxGԝB;N8IxoT@\ v (rH{e$NAQ-bSiT@UP}QT8A$wߗ\)AA!6*JR*4c`XT8]R;v5X8MF`̩W\rŮe %@!V@pN3%a)@ 3 {)l@ (l`섃= !{, "fH&OD  Ac>m&JƩ{;:X Eh۳}xfNgV +mLј̖a6#ɓ/nwp|G;}UpaX`r7ߜ =y 6ӾK`9COo^+ۿ<.o LB"^?GX1'2fyw̡ wp~ߝ]3@">>Eog'ze-?>K>i?yxo ?~z<`2#CbO{EݾUl;~駻vbу.ac4}aqVnMdg2 )M~nqC  7i(PHC" E4i(PhCц E6m(PhCI %5PңOR~$MtXK#9$e+1p2n%?O^.Le4sQ+" Oa˪ 庬_HHG >Z}QS)cƸOeNfpWJ$y eJAZR[)pv!nR6Z Eyq= LTu<gJxYW' X鶒i#%a=L>ϙR-J8g2rxNTF,{X=u#YQ_q`9 2oD)[JCHJZ 9l=EqԌc:aJvV!"8װe4p>+F'Һي@1)s9KqI s(Uv@p@+lhWV҂8 y z4g_[X[mrYZXq+H\Q\2^xHd3t+ 2Z ^n]>k|:nCnRQ=b/\KiZ*UCӢ4J]ֻMwUXm`ԆRJm(vFc#Qػ!1QǣG:^oӥ+D7Z:^xuJmJn(mxIIIIIIIIIIyxcW (@ \ɇs9#fξqŒ|،3 Irt,0ՂY7ȇ.5h.'ʀÕS<u@nn')>6Ks|ƍ2uiזyvF骢h:r>70|ɜ(?.&\N2T3g(ĭ\mōrE$\FcCaW-S9P~`_aÓ9- SF5$kڵVjmdNFW߇86 Iak\Nxp3r2r2'4g3NxihP2biZBq"ӡCNDI49^:]t.%RP D*&+zJD")ݫj"@]/ALu1nTD$x^M's"؍(7DGCŠo^~8LڔqFap`=å$<IPֹ$O4Q_?،I^,KP {Z䭮Y+ʙe2'F"Ӹ&VdC-T endstream endobj 217 0 obj << /Length 2581 /Filter /FlateDecode >> stream xKo$~9JqfNIonN4k.f =jjF4 ̓0`iUb?BE]oDo_/|;5}f o߽BIdPO >,~ZV׻oS(p>\I%_t.A \()_Wai97!0iew/?Οf?,e8l_P҄a[r؛af16USN]}w||wga쟒Bv sqejJI1k]=/?[\8 YzIڀtVMt;IR1jOzy0?q¶#f&)R0wR/;ae_WzVC}i31d|11`8cxf4?OE;QiS!ayPwj yԆ!{^:.Axk ~P Ϫ)s'}x7Nz:a9ޭL`fՔ`gE9`?=y36 '_Ɣ0t)0wECjiϫ/7Ƙ_ֿ׽z~Z}y+*x+?&`ܙ\)0w:`~lE"['ZߴN68ȴ%d 8RJIrVHZ]m/\}~-̺w]Czi{Ęi2}1R%NJrlMݗHi}[duwsQ\nmRd6Y5%6ad'֤v]\ \ YŬ0Եu b7׵i6c6uBGZnD;@ع8USNlmVOGMM4eQB:\ģ~P4B0X5%#N#`LzK#@όwH/iΐ?OngՔy2߼?6~YA`i2dh^MwxYͫ)s'@35H^.͹ P d(i(tRxi(:2 Gs~yE)YϪ)s'+_^K}xԧ4řv|m ls_66=5+xJlէuMҮ҅wR#~Y5%~atl6JЊgQm M/tV.'C˞G' J)'j8`@uN5Aݍ{O] ̪) s'nɲ}$oO8;;\nMl fՔȆldOmNf9}}z qWf^Vhj h܉p\GX۵a|mXP/ \Ϫ)s'j:]6?ձQ9z{VM {{j+ 0׬K3N cۃOV8@Ĺ3@USBG>Mos IߚDzY)a(&/Q9aN\>R@&WuE[cҽO"KKS)x4 endstream endobj 274 0 obj << /Length 2384 /Filter /FlateDecode >> stream xKs80Lev9cV)h)DMrJ"+Tw؄?lbXA0#uZ~~ѫ>()"vG%7Xk'Fe$mn1N>/>o.1(Kۼol;? >qch!{58Mo>C}107MH PM 4w_!h|>d?skR"TݻvgtNbuҭjuϮdUK%2Euvw 8}u]O.`5#r<冐nۘ=XARbb{2T (.ff\ Z} 4tĐFsw$Κ6ftogko`(,V!)e0Y;C[hc%ƫ?@hPh~*לhѬߝkC %fph|xLJhLJ̈bn/߾WfTի;1cղqhpP&7F"@51=":!"B9_9"΅ޮqV:j㩵}H`` RPCsԸ )@Mޝ$ 0Ɖxx E:7[t&枣Zn*|f &6݄S|v"a W& T a;{g`l<~po̯VMqU#)kI:Qyj"{uV:1Wݖb';=Z4CQfPMf4w{'2aC'|oO~>ϛ)=o=\d ~j"㹻Y\Kw?ӻrE+V/j.']t-NW`$D1&F1W*%\OЧlmt> Ctjbt{݊7k Ȼ>=KOwO`!28&8.(\_?3?r0 ~/&0\ϰ &0rSl^܏goɛGE64>E^}+4xxEswK=lsYW=}ɯE~u{ZNyUx/qԼ9p,޽i#ͰR7}M,bEXv F-L${3ٷ|W]__nxc`f/ЄjoJ.m]΋σ P_-0{t1 |?> stream xڽZMϯ1p `\@tH"ȋH+y5SLqs ;jǏbUT.5ժh)?3'V4BI{CRx_(Y= '- Ce-U@joƈ@$QQ6B["2'/["PH0%1zԎA|Ǩ@.7ɿiFZ18V{ĭP$>TIsIȇjXi1#z^1o$|6 7X2-n:OFH*>!Ieu=K:yjڔ/dMX DXHب̿ NŷzzanW-*#u}%uPo(u/w'$|7 *'$ct`C|0";ua-6|Xk IRaY^.aFS Rfh+,hq&67nr)nް,}*t*X3此Yʥ}^Jwǻw:7R决ɜ&sqlN*YئrvHYzJi NrHc(0K_am*ꁱuد>uP!LǿopVpJ#~嗏?!ٵoz<֓Ë?p}| 5߾~o~O/g?n?G/sz盯'x7?釻_ C3-|:,o?}i)C#m5Zh5moǹ%{<^x=,,,,,,,,,,F7ox#F3Gs[h9ZVmh-W>pD e^$YiWC7P&s֞,NeFs9dOEz^lp""W2dn3GOn#0l+%z\TrltZgkyoP߉G^OS=\m,dqY \%ƴuN)#Xq֒L洖B Υl%Es)ud>P"p.wl5MD66b؉\Nǔ+ąycZMjmŠ);qZͅNA,2ӯ=8xA,z1^Χ 6ṜB.s) /qLJYh.'R<%5LDG /s9,[8yQډ_ض \Qw/p]*Sm'NF-bfu.']r"vk/N\.\\\q"}OB0m&s9p"*opT $yҗ@F2ɰ݅Sr"#'i Ν$.h:б$hZLDtƥ~dhx.%r<]P5\KOVWFTN_2gcdNdu(<>m䙶 y~Zh嬔 O9 7ژʉ$OT=TFxܖboH\+_yQ`KzY$лΈOջ,+/YP Af8(1 U l6 \ < < < < < < < < < < < < < < < x!QyBG!QyBG!QyBދ PZ^^nv|nv]_\Ny .@s9ٲ\(P]788@j7Χ+PQznD:n?.5nE2Kw52h.'#A]AAUkʼnp7ܺ^[pڮ%A<*$(ɲQֽd/5xɨTݨr7KM l±^dIn^[)}t/ rY ]maD0^ϐKʝkPy.Wʊ#ۨ;]iɜɓ4x! endstream endobj 292 0 obj << /Type /ObjStm /N 100 /First 887 /Length 1428 /Filter /FlateDecode >> stream xڵWOH~_s+J@'(85"ǁ7k:ٙvldfg2˘Wˤ)$3cs\˜հ;\%5]Ɯtp!c}2бDe 9@ %J8ShL* I eRT :QH[jMudcځxҠ*V& 膶2zFѝ 1$(KT z2E:€+4+d "rVrFAs< C&!yINHU:dd rQ%4UVCjA 3b˱1RԀ5<AL%{{gq]6].xR՟~ha8'}ٲF4xRT/#MjHJF6f{{ltFo»F_ 3io0~I xgct ^lrF^|^Wr͋zJy(X{~%hIiW5AȪ:G9ٯksؓ]+]D'K߮n:]vp)>:rtUa':@2Ab[Qu8ѢkE+cuGʌe_V|+ܯt[TQ-/fnHt ]CDzk",4k L >G/$b1dAhm(Ct{Y,?Lҋ YpeX,VuUmcyr"o_W؂sU-[li-{e>}?ob^'ru=P/b&LWp=E0r/~SxqX~go|7h~HbGC[v).ߘ;^y\'`7p,/軪~yGy|.C^C >!֪%˰8~.7s"''m4tݏ}?=Rd |ժ~_ م[\f_.gQ_ xUA0ѪR3]dGkܼ۟o)fdmNo,kT]CIuMͮC/q.B3ny^7 endstream endobj 445 0 obj << /Type /ObjStm /N 100 /First 852 /Length 948 /Filter /FlateDecode >> stream xڕUMoFW9yf? !'5ŠkD$oh$JY].ߛ}#Ey2C$̜KkX`CZ˫#mI{1P98Lp-0:} ˲F1"/XI] X"|"~8!nt &/|H>%EA40Z (qS}rD#R`(iV+SJ `0*5&R @Cme"j(ȨuDx 1b0qX`hH |Ul@^&Iviavz,dtSty}q ߛu[ϡy}=oU4CuiߺV3 endstream endobj 597 0 obj << /Type /ObjStm /N 100 /First 853 /Length 877 /Filter /FlateDecode >> stream xڕAo7+昜DI[=HfCkJ)FrPkMJ,=rfvT2y%q)% 4c1#NsĨ#c,w31X񁘡8AXlP`!aGAq 30v8'v:(3B {I@Vρ)ٹ!RgHseGOs'1 bl])gʦK^9=*Ξ#w*HR*B%l{6`[X<czo)Tlk0a&昚ٖPLy=+R<Qh rHB![K>fI*Ym T)YUfR6@e*v9ExRPZs(.*T?*gVg+ P /;E{PXUWt d3LA)=WŰ AD*;Eð/@HS2gؚW5"U\*XOl )(`|xN;ZVMHo_o+ 󾟮<a߈]8^OY>o%۴= oq~Zn3n?~wif6I}ͼx_{+s!ϟ*RU5YYxrlpJ U88vU[9fߙm>裏늣mB>&6nM|soϞ*PW5UEJ@l|]M.ʒkVc^i-2q$\3x*\Zp, 9, 뇫LkU|Pj/sn[['WZӟekգNMYz endstream endobj 888 0 obj << /Length 1528 /Filter /FlateDecode >> stream xڭXݏFG,[J5uՇ4pN׿>3;6`커|~3<F&,&7v=}Ý#_77?u#F)6@EIzԷ)!_}~jsTfZ'Zgp Mc"fZ2|aY]WnFYSCf΂{@`-N涄-RtšjZp(?WMW0>nsE s[64YAT(P\ Fy̸s ڋug)Gavl!,EHD k~ҹ xwa_WVUWC@]ֆ<oZonW aۑB_"(촏7r \YsəNq=]W.k-Z龙\C}Nhtfp@@U=Կk KM1z#x?|LJ@4V\I SSMh7Z+OARiR}nV#ج6[78MV߾ۼ.fDaW~9V#iC)"B4/6_LgƉ_,䬹C^&fB.0/'B',4M<\jhY9ve$_9,\+`Ó#ed Ā]NW:ȳ:11mqbjX(1u0&0P,7q6!KLwTlZk4R{iwX۔Ҡ3V.WJ Eb¾%UލS-ѱZS1!%83!1 V* SB尋=c%2}VE>vFD3Lyi *p:)=ΜGǫ¶QIt*80.Mf;$]g08}ԥ~MeWmC9꒱3s2COH$14rЗp2`a5*&U,N-hَVsiRKpQGA|)HwUT-A5[Eˮ)Qfmz$l𩪳Om#b la`|GYNZl>FO-4]nCo fSJ|S}5BX=Q%d/[hA^}nΎ W\rR*?Rn{C[j)bd&a)QB& ZS֛'Q?bX‡qX>^iM,N˟ZkMoyי endstream endobj 894 0 obj << /Length 1628 /Filter /FlateDecode >> stream xڽXYs6~#51}sM;n4MQ6kTx],Ccxaw!ǜ;Q,XDN=5rh#fq[5{WYm^j|sꏣU/(HL;,8 $F/x8# I[&uX(pvhҾ䱧E>[묆Pn[k2./c҉6"V`7@ C7oii{./rͮ]]]v7;-/K@&<0rZKy QƑ%ssۼhjppl"0X^uuUi6]'!SSM?޴]0wFt YpHb=cwjm㾣<HKJLت/Q(v qķᄈ56Ν:Rk(a\8GR=* SZZĽ^F/dI@}DĞu,(D9<釤䱼zL`jis[3({7PV-[4/ # Vi%/u*(D4Ӗ/cƤL.J[`lql&mi=4$Y S=&!L)!W'%1!Ef.%@2ͫ9I2{[s9檾SSܽ uSCW"Grkݯ}Lo)1yK!dY -^@['@m^؃fY^񽷅;GJZ~;qv=.t|/%WqݑO)l_< u `=8 6=DOCJwƙPwTۡ*aÒq!y 2zpu_,s1ib8%fMZ_T!\VNhݬNIQVXړ9 ꬭimZ2f*O Ã$^G9 9z=4}-qz-}\xӷ3M- WȄM-|9O'Gbr?DE,݀-,iyH\7{a)묥I$ ;KcZc>@[>S(ap{~AAN >r`XGxU%܉O_VwVv.vI}?]~젧dm;igR endstream endobj 897 0 obj << /Length 604 /Filter /FlateDecode >> stream xڭTMo017@-J҃dd[3Z)k{^潙yE~ip̧5J qzXJD RT8LUxte9/؛Bޕn)2i)+f//QLb)ܡ)UP Xa"ERPɟVEVpBnC'_O[8q%߲2,$4s ٫Km[CKZ 5nFJ"h,>JNvΦ!ێ˱)e0ew Rv*Ю& \Y}Rc%Ta_/ bm4Kbp5>Ś1tw.f7M4EqS1LWa:7TMTfʸO%> stream xڭVKo6W{S .vhm *,ɕ!8[-97 )"2bɦ~uxHnɭ@p~}sޘDpVR$HxQu1O7ֳ"# 3Z]i5J0]DX&h9VU2J]6S=d+eu:8hC`x%)\gJR2YpAu=6  Ӂ)~VҦ.|UD Y ɕUZȟ=5&(Bҹ<Zcl%KaJQ2!`nW)KpRt?aތa$]>'^~?LH怋VHw*XfbH>ƈC tOn6?qugpTQ‰S%t%+U<)Y˜V2"`T'_;Z{h3Oj؃K ko>ԹA+E) v%e(kv9XfK.kM4/&X*DlqDbXѼLnw kgDži[MAlKezP!8 |Lp0f[H EH7mρ y٬rLdd*PJ?] ?% endstream endobj 904 0 obj << /Length 1507 /Filter /FlateDecode >> stream xڽXY6~_a,PT öHH_6(ܼ4-h Y2$ʛEYZk A!9{!g *qWJn1WZp\x3LezHj6 M/(0M/T^NT^DP &Es* U1iyۜ V?O:Tx-$(#h"9bY^8lnMśwsX=b*wus9húYi+r tp*"ekjLws,woMKǡN5XX)]Wm]QW,FxДmQ óʰ},*&٘ma9_[ ]ĢEN¼y LQǸ cV>]%a57ٖїǦ>rׇ3̓/2?p> ;;'o,Ĕm[yKzɊM$;M. s3]) }$V+lR~9z(( 2m?G*;椨#AB ,v9#u9I~pQ6z llM𙗻,9"6p,J"Ͻ=X>8ɀ(D0R㔅i֞BphƀoY/)YU/[̋}L F]*: ^M)ʲgY_ʔd(n a 8DT* )$aҙoIΎ H|^ δ)e9md18c`{l%q2:u5O8X>-4陫YR&9؇ H@Y^rx<~a5t_w $ oh2 pgNO,#P׎箟/4y'^Q|=q8LBiJb`a } endstream endobj 754 0 obj << /Type /ObjStm /N 100 /First 848 /Length 1355 /Filter /FlateDecode >> stream xڵWnF}WcB}g /q`i .ںFAKkL $߳+n,JV0sff猬3qaapL19 yYńġL(2P IsI)1J&5pN1 &)[@v@ȣDVb0X)X+T٫S5 rxyÊ1+7g ++_o||x=[t0% t7(T]ڗkP~ o> : ^;]Tu|ַe$[9ſ : 7T؍ dYOw欺ۑYtkӡ$=%[&ݻQs\PgaEFv+03süX(~XNvQtrMIsxmfA|o|—mNtKeۘk 9Pº!‡Ź>>v\>.~ü|,o}{dvUpZ`Ol[aoB`y:Cʫn^U5Ǵ1+.fz4Kl4Og~ַ7z\+BCcU߬"}yBroP4<,,@d<u|CChGY1 ]h'KMOU< twtA9 Z`q/꺁ŋOa]fs:ϊvi_FǓ]Z4+m:4ohW!xq';'Uǫ۾w?}Jv>.溿G)'EcX.v~*VC -W=Ls*Nf2:> stream xX_o6 dϒ%pwۃj+l}"%۩{׻a(PKER#O, (INEy-_Vq~{,[8.2GzV?<oLfQ&긟^˅(")U)d8CY$ZӆDeow \!LdZ?+"#; $P]uT ECߵ!b:HD=K(qhBjk;CYЄ thTS Z"::+4q "ޒ-\ }ewjR;Fl"!$ Wi^fjLdŃ;MbGiLǫC]K 3;m0 9HdFӪ"nOM]] vQ紻?!m}8g& K`-w{0X7Kb%o眾zFTYq}B/rC\W6 G[jh]KjO Ʃjw:hH8`[$k;|Ia1~S&E`mx͎EDX3cE\<ftiw I>uJ->.aYfܱuGbj|Yd$SXEIʊ81⸗N׽7u8#(i1ⴷ[1:sңTV5~qRgtwCc΃f'жQ_ԉQDr(p Cg}4=@~7?06?@0:E6,qBg._}}mIYO _*us<?uQ>XDQ ˃z a9Ƒa1dctb> stream xڭVM6|"J$oClE95=0w@ 6Chჩp4HG2 * M9_oc4|y cMmij{~4BQe݅Q3FQZZvv*' z\:I~7R<~JY^EZ +R!(PeȽ55(iҶKZ ۘ{¥ Q+ R0u6Wڕ\BBjQx(Vq1Uh ~ 7)a W8i8V xџx-.Q^ L$d _kspysѼ; μGGdT -5 m%T>vFq-F<^T3g Yӣ2?8_L*S l'dsf QR:!ճHO,qw ,"QyNȞ+˩D♧HW: 0*XJv>+24X7#PCp"kk5(pY:n@G/uc>+6/5Ov;}w /n7_M€lxK Iӱ:9hLF.^g'Usj{ ZO$\i?O,yUҤ5X\NK m {m֐C_ZmBogwcWXN &'mO3txJSۡ+bZr:_j0s4ϺlX^n^`Dá-vk&;[J endstream endobj 915 0 obj << /Length 1762 /Filter /FlateDecode >> stream xڝXK6W=HHmSE%9peZXYr$y;/a+iPRp&&ӛ,Ug*aË w3w$(TEXDMCv/vdD%&AJt7QtVTR.Ifo~3uO{F.7;H‹& ʭ΂= Snu'r贽۟n $ MܔC6$|am7VôޡqhMH@̺:+/Zb/yų*BfQAr3 ?Gt|L qb^x=vVh2S0_mG;iI>ؒ?P;qrYgΕC2wy,0wvNBqt Eu<8=VB8ny H .MàdGMYr+&KaV l辞1uVlעdES4%c֭8 @~5o&*әH]أ{CŊuƉC]ƅxby䩤74$[F FzGmH^Z>֝uĉ%&Ts~=@KH@ !\n|ۣ{>8T(Y)hay5W';"ePbT|se7:a2c2)P z0@> stream xڭWo6_a`/2P+$ZraHuŰ.E緶D*dI(g_;Xa>yf* WIiU`~E\1˷̈́5+`Vb*j>xR7QyMs&ϛ#iTR>7aFۭ?y?(!y}%J}5 W,꠆[?౅ZA%+Tu& J~K%UM +u);!jY%J ( c4܁gϲ z^fa-+TޗuS6oRtV.B `e 7G:9FE8D.0!4.0A=9zǞ>M'Ne.ݑ.uljгM:uI l0"VVLSQ99mȀ^Zo"lK rlLtKtM2nwۢE>dvYS/Σk4Tœ`O0rDC;\;YRDb17e DEUT$mֹO*a-G%G\>$ao(\#DJ ¦i&Ӯ{V=2{Tiʹ:>4yw5 ϳ1s1ybۻv= @ >O|.dX`^^%\ISĸZqo`}8\[="6!ϴȚQ88L'Mޫd^G o_f; endstream endobj 922 0 obj << /Length 1450 /Filter /FlateDecode >> stream xڭWmo6_!`_d bEJKaHv&}jAX,,~w,9JHwɇ'X9q$̷͍C?I@i\={#}tew/پ3 /0EUK}׷ -SqHW_^-Zi+c*@̑uH*uW=% IϓR`evyκ67Tz:Q&FD$hXIIEuH_>֖Na" xi˭It<|ۼ+ʒC{'ԻB*YV٬EŽỶ^c=:q-wmfIE;t29dž`z!]C2kU (K\Lb*nI61 砠@nh՚ sQ˺oL8@ m D~ere0v (v NʁJ^\5e;J6/|n=Fd?JVh{%CůŪɚCoi´|_׈f~Ͼ)nvԺef< G ^}ޗcg'm)ir;ىӺfS)a2EuC"l|ߠ| ޜYݓۛaح605C3'9LcB9lgFc:>uYૹy0%KhgLOvËGSߖlRʧ//~?rK;H#pPe CгucƉq"oywrE&Ν9aQr;ԫHej83~i O&OPXc:P@-$vtic %'6v~2uAТujt~2뮥{iJNiWsJ!TFAaQ03`Ncau ߜisX$VCգВPj?NJ.^SIs0ʶ~>(/pYRTPP"@(R +<5^PvcMoM ̯VZ QfWPeN2.CvCY$e'Vi**Gukt 5Wԛ,pAVT`? |r"7#n:,:G`ȹi syN|2~M]6;LN76WK$Kd ֢рi=}bHȧT2E:=T#ˮb_0}qth;jl<[6+b4u bG߱>/%2a;=dO?sz% endstream endobj 925 0 obj << /Length 1121 /Filter /FlateDecode >> stream xڵWmo6 _qH·ƎsRC,]6a /͊wmĒ(>$RBf!E0[YVfbz;fyp|3{' -Ce>9/Ffa$s7b,k!qf;R5[nX!d򗃟88 ns.kϏ#7nβ`_W״2ġ ҊypZp`p:S9E;ãMSo 2-W`aF ]xrivUfnRu[VHG R'G;S,4:LֿI^["S8S5~ip 2uf@%-gg_h)҄L'?myJܸ0|p9:i%r  wz }/LtYΡ7T28_wзѾٚ og7RWs3iZ95H,f%Ҫ=>iNiW%p<ʇDE$-*%-V܉ND|ɸݲ&9-P-%þ6_֘<*v .HoSnk[F 0,<±3hck瘑\eBpb4)̰8MQ?OeɟI mGcrv2j-JTh߿ Ñ=ܞ?F Sm#L3?|WHmGYƯh4pc|*ЫW=CKo_@ږ-jcbҲ?UD 2 EAsJoNwVg[;6o jvo,ӌvQuͯu OHbbr7> stream xVߏ6~߿`U}؞ڪU\_p f; iUh=oy=_> stream xڍVo6_!`/0"%Yr=Zd@v阨,y,x'Yvvb>(DPȠ(ӸL:\%jZ|p%o ՛y$^%+lvA.xf6+i揫7\qv)QR02Npfh/p.akhycPG/Ri& Y;_H-DȺ^SuXȒT]mod4-)Be5QuL6Hß'#3fĞp頄%BPG %-Z&TXE@S؜mh5ˎ9Y!}j,d!Z}rkekYo0̫Vnƈlj4|!}:U]s|;] M^p`>@T# >$MojG˞l,HVMe蕄ƲYa|K׈cVq9ԟO^2ѻaiE'"="F`c W$v]; ^q)5v9cWoG,'Q L6`|, CG#*Nf!>K?33?ݤIУ;QB>͹+ 0K7(}8f8;&)aj& K$Bo=G^<`ʖcxwi_* endstream endobj 936 0 obj << /Length 1157 /Filter /FlateDecode >> stream xڵWYoF~ .Qjчvz[CSr(;3H[vd#as9ofv-~W$^1OyZxIVڣoߞ A0I^|瞈EElз?}-89_$,=l/} `xݥ!~O+8W|}n|`Qh?Vݸ `h^G 0gvd `C/)񝴖Y@a˕=`;2e,MUuTq/Vk̰[ɏj%=shL-Dhj9 E6>9{4Q`[mhϿ;^9G9FicrgcP֣. s,XPi֦B5Q0lTqM쎢YK -*]J;=W:LkhˆsjwRiTa[)Q-#> stream xڭWmo6_a تHQ/ΰYutܭ@[Dlɣ&zq) x & $ia2ɶ' -ޞ0+7@럣h,dZOZ0 t:".vQ5pǢ'R#?n9|„;x ROQ̽uQހ3Ih*fv; זE&EۢYJ g%g<%u x2DjS.W(^!xWI^$q HpY; 9(Fa`~F\λktљpBEmY6x9O>*/)_Ͼ*ՖT7']!8$]HbڥU*Nڒ7%;SmQVD|?#fhqmVUb&Y*?LܴZ复3Ҷ6x +UUY1ԚV5F(U@!fC/Y\|ȣHj02#L0n}/ =R,:RqB_G*N_Nƚٌ™]?JckՍ7lδ)f? 8~?G:eH|~ZhaH,kX B퀜mY `UG,r )J!m-{.Qey`Ȕn,_:@{Zz/vsȔTmh߻Dɛm$ 9JoRn1 #gj@ҩEHynnfC2!JmgF2 mj0^|K!g)n"H]r-\J<6Sy̌pؒucFڷYyeYcd#{.lq> stream xڕXYs6~Tk1/QnHQ63fd`Plw 2c+p-v?MhꎦgGto[ގht (_^,`{h}fNF|wRyVt:~`z]&*e?X8Z}j]K |@X15vE7k}Lk&1.۱Ǭ}\ ڼOfmǥshN%Ms|`_Whf6s#ޤJ#%H?jSȺg{& +X +xNd XT`a$06́; Ġ(nO3~ 8m1FFdrT lnp3"A$`Rꅞ|vW^wBw4xܣxMW ` UzsguVӼw'D!7&0DVRi gILEa q#;uYFƯ\2-]+fIE?BCFQ"m湚ʝax,1i4u\(`!8'4Wth|΋;oLkd42 @aKO;Pƴ74B` M?cB ߊ #I-"e{Ojug-n/Q0îuS۞ߒ9.9~J8@ۨe0_P@fXy?2BPa$VtUd0> stream xڍSMo0 WL%i}v.ij)T@%8p&<;6pQ*PIvE5<9b4`>R3:c3a@qI$ XI4.Ebe27)?eh e*mƔ lmuY޶Ƹͮ""G"Rl n(G!nڴ?=B}t'C"xBw=`)xsYJ.876Rt$M8;aNЪk쉫nJ>VCR7xgKcf*^ք:qF8}c΄Y)r_)0"U=u:, [Ѕ(\)_e endstream endobj 949 0 obj << /Length 1637 /Filter /FlateDecode >> stream xڽXQo8 ~0jIeon ;0ܖmN4;G#>+vCQĒ)H~Lh$Y$sNr."u]P'e MH4Z"AStԷFc/x5 &H#YD%aTfos Č̶b)2]i<4]bɥ?TQƬ$ђs$ q x3tbXw(QяqYv 5jJW݂ۡjZke2noƙsktխ f̟PߩFue(.<5jN Y:JG\ɈRRw4Ǖ?`O: SN .@ʽ\GiOBpE_?cI9(7Y3gI hp/tڣ]S|K_铄'ٹ>8֠l)Eh#%+@.-m,,=.8i/ Mqt`uWUm^NM~9տѭvFnvjk7w[9gD.g1'ItY4 @+ksƛNZlSZ]J7jqfXg7 Ƴ?߸fj2=zbf@xÜ99bڠ`)J`H7-/0)_}>g*H~gݥo濏:F08矿&^B J"N4P}'Ԑ'${+ sbb}/ؗARN=%ٶt ? 11]?U Tߛr w㿛\+'T  8x.+488̠b>|֧u,[*ծ|)ool}?_u7i y>Gu~{8vU]%#KH4=ׯpߦAfۇr> 79BՂ}qȥaIzt8O$QW > G񣂎Zթ=Ex46;mi}yw7= endstream endobj 955 0 obj << /Length 1685 /Filter /FlateDecode >> stream xYYoF~D{qI@@y0uy 5fG=4FG37y5!bFP60PT3m$J:δ}O˦j[wS6Mu³8LL S!VE==eAV*F) ׭*Z,ߌ)\AdZD.Uc\ێX8A v<<p<#XA@ ulQ-t\3Z@<^k2dEv;N;CVBV>\YdQ( b!!Fs*lG)vsnC \ ~zP_P-ZB,Wl&Eo+p }eꚨ Mn8Б¿=; endstream endobj 958 0 obj << /Length 1510 /Filter /FlateDecode >> stream xXKo6W2+ P۠[lb]=mHwҢ"7@@LQ73Tf{ǩ$Uo {wr(CxW-y'b~ Tz' hD?##b *c=[ﻱi[wC4謠vIXg~؈^/LļW+"^k-jM94a1~, ? 5nTi!0J$RM H}KvV2;Q XEdr n87zB7ʆB<_:C", ĪOi;Q9ʈrLLZX$aozRQ%p$c;pXJhKNڴ'GgPC ~gNPz3$jC,n(+YL h YPV7N D y,9Dz}jೃWT/#W3W7tԊ4Y"fȲpfvm]ć:jY,nMLJ t8p=ZTn _M',%؍-LHn?{a1ZQJ&][)ч(!TRa?Ue&Xsa ^Y*C`͈Zhx\ÿm]D8(+&|nv]jxgԔX%i63\F=[/2?L'  [j{8EP0ΪBqT`U*sf:;jAZ$0W# bxikrxZiaTPUܔkG~ WU5U`ϓpR%GlI2Z^ < RK8wwEjNz5 >/r16}B..rUƼj7.ۖyX$0^>K;EaHЯ ̩HNQ?HbIVXۦ25rc,R0pdvihlbڡ|עӝiߥ;F~3]GCwGEOsn"P͜SX9O/4ŁIy ޡqe)T.R55 WtGs\TO!=(fk˜hZAO7R[i7ށԎs 7k__?Z6s1FIYFyۼ^$a_m endstream endobj 961 0 obj << /Length 1426 /Filter /FlateDecode >> stream xXn6}W,-ѢHR&1mrjV4ovA$3g"?x$%(%"ߝi]3|0'?E( 2XmV=wY/{)w˔z}wE] ox&Ay!^pv5l(y&Rc}7  ip>U~a}]ŚB&9o̍q7c rpfR[ޝR){*XMF֊VS/Ԫ/gNv(~!E ٛւ\2H07'PAx3@öɝyAq#I֔[쟢,U[C2P(R^-ng$^PEhr@hUY8U)TOR^FN8%u wq@1 JI%^fQfϫSJ]S}xBOƫ E(ń>5L!~TAMֺ$@?\C}*N-s䣆gY}L8)\Ym+Rc7€uE1|Bb~Rp >!d0Bf*> sDuzq c2LիXϜZFsJf\_bjpBI'N(ϋVVW/јvb 4MSƜ9zCOŶXF'Xn ^}.UJ@|'P3֜w=,[I-樇*#6u*;˲plm[ j!\{nG.qн /YW7'7#:Zȷ3qPΌzo+uFHj?L,Tܦ=oɧ? 6{sL_*uXbwYJʈV(t0U_ 8V:y׃˺y0nL(}YVȁz;,\wZ旷Sa[ǞPB_'}A3$3v endstream endobj 964 0 obj << /Length 1806 /Filter /FlateDecode >> stream xYKo6WQ X(z(i(jn{hzP܍ZCIv"€MI7Ό*U0x_[[/(a?݋7Bh@ Tfw1;R}Ƙ\ :^WmQW ɭT J0\~ËE(HppE F$MIHQ}MWTe^Ww7EnSO6k՝M(%0$,F N}"NI+߬5n6v;L \SΈ`®~` '!20=9KRb‚8"KGC_*G}Ƒgbax1J.a *-e잎N(A2T_ _Wr]@u:Q0qy+˷5W3ׇ}cGL̟Ozrcf Y&fN%N4@)D0,kCmKGN 4|h@SgWLD(~h?YCT9~D:j \b$yY f ḑPG8M_[ʟDY)&ky0!! by%aaQ:ӧ)Z80Eg_(D4qڠa44z` 3E,yEc^dhL"O9Y|0T'g?@:(? 9Wc5Z RZ;t9'$V3,EaA3X aseGsH~Wlo,{*̺2kko{m¾|; j`0k`צJuvVjXEd]u>3TTq4n,}\+zx{ɪ :̹,`hVش2d -Sm2 x]Q2hccMkQ tN1u[֐ )3VVe)aa0Bs{9ީǰCخF6Ͽ+~ѡU6twm?Qs$IdeS\LIx:v)Rb(l&]l.ds}/f̕CƠε 3/N#ۂv ;٪]좊IDoW$|Q^َ9TMIMe/s)NL6fO%?<={r}ENM>-lIy3ʘ%Hr̵g! \,ǽ֎ڒ8쁗 ۪zjI7k٢0 /3Q endstream endobj 967 0 obj << /Length 1174 /Filter /FlateDecode >> stream xXnF}W$`nKE$pѠ@>}ŕł"^;˝He'M ˙3bbʼn ͝g>`(`8|xA)QҔyX*پM !mJA"ZwE]_YotB(Z|~u8\qEgZOM`3G*iM 'Q?fMU&ץ1˖`,"2u9_]fݒ>!b9ƣjPsVtmf95 !&G:'KIW-&ZLfxU^-TV"6ݺ_*Wh/FΨpI^ls1ۏ!G[{žչK먴]@9ڎzC-*YgWH;)Wc~3=#if֮#aݸsON$Y kz\W{2?r:ij(6C6?;YM":5 3eɦsR]!˼c}xeߘq7@y@(BuDdb<@sq Ѫo@/cqFh2׬N7M9P_z0.nY0FR}"~=p3c `S 0 endstream endobj 970 0 obj << /Length 993 /Filter /FlateDecode >> stream x[O@OmBbb!>25vӋol;]%$==s.CzqPb/_a{ąZ{GBx[,T+[d1?} (HWyWԕr)Y2iԧVEhN]mPkدa3:fVUlvMQ]kM\74(V2n[ƧY4V[la&OSNȀNم*Zڳp#Cx@:FԢzEv@!ǩneO>zЙL1̹weINPBxsx,yL= LܲW#na7Lx@|%|ɟj]Ⱥz8G)G3W8CLP$͒"3+|߭Ut*ޝMM 6ԭQw==!v4zekf촚m Xt~ endstream endobj 974 0 obj << /Length 1427 /Filter /FlateDecode >> stream xXnF}W 5PQK GoIYH}gqUL-3gg r+IVr_j2ﯰ0Yzw H ۹Sr\ UfDݤc8'qF/Y[(|u@XO"PΙI8C|w* j-qVX (3{/wuٛ;ԍYk}um.a>Sps*AdQ8zk<".oR7RyML\*G& LOxq[ +o׷7GS.{릵msUCշcq=U[TM*ȑ><aաZ& Ωy⨜| f'8j12eו_cqExf QXP43g#cN5ۗ(i¸n<כהs\V bH7\"I#=)0 C/ !Q9Ai)-ӮZ]Rpd5ƅpE!+w •Qb}XX}\8`0ؽ6ChwdئEs/GuTE1 05v^~1 t0OdvYD8xj$~ɶ7`C=S 'f5ӍOrv=z jx"*P[mTn8YkeN*@Dh&EEǡY5^hG9m5:>%c '誡<37G`{j!@Qfxe \J'(_ECulŻȺ\v~nWQAPEgj{NQMk<EFI+gVD%m*X7ZqpQ X8dqVrNU3JnF<3%7HH͝i_kP/a=bXΆ7 bik85Y[Nә)Wt9gË>^ҥ !RH9BXľf=eir7lI5gޚi~{ d7,Y.]F$a+Bԃqꖺs;)ܩ+ješ0SL|bz~3Ф@7Yn۱I) FlÐ< CA0z \N<9X Bs̯A 87Fv՜-U?U5zM?g_!x.pjМޅ]OWĢ endstream endobj 977 0 obj << /Length 1113 /Filter /FlateDecode >> stream xX[kF~ϯ$A4P(]K eMЇnyȒ%%gnq`R"9.{`/!^R+vWn=}q YO8p(~j~?>^AH)A?)˦0V܋VԅBDq8c8'qFFSA4F8$Fg/CNևeE^SY4CMb4BD'0Pnjaߖ;yQؐB S5W MIW!ҼfG)le]b'tG: n Ue90PDCDbu  1Pr BeW 4RIc1F`8uf<p|PWu|6F L2 EWmb y:C׿`r\=9=/:vbϢ\Kz9> stream xXYo8~ϯI"[lXl1 [RRERiXu ofL< K ,63?[O_\?#.pB(V7SV쿻AAEܿM[֕zWFHQmDǙO߫A8񈝨>R7aJ4F$4FGZ]{F벩u Ibf(>4 /̱S8Fep?jgCB7%=s/d׽L9uHRGJ0<]Su)qFB[^FJYԞk%^RӑVJe]a C#M6d"J#EWV 2eA4 %(㜚;K%@cJej1SB9viDQ.LI$RF3VcJD)iH1Cq!ߋvV{p/X]nR45vuM?oEIR|/J{}fSW_0TV6o)gqYXvg(YSQL)gL_C^pw ÐPZ+LxpVW},2FP61]eiwSWac:8,bP/,%PĭŐ,eecNޥ>blU37=M9|="Fq+{aQ)Peu50fdg13NbYbAD@NpĒ_CIU=H\Yzrr x \#8OAu~x@#+ӈN!)y RӋ|?ًGd!)NZmWMMo}KM]ZFoU0: ؉R^ Y(rX /{RTy/7[ w Yd5'v(xʰiYjSWNLڐ۠Ы̔0øky2>-<5,͡XW7s VځRbyn|_WLD/lvL!JbJh*eb/V6@:(%.7: 1~A[F, 4'եuMscnnf`O]IMs*i[;YXЬ/oV.LdM= !'\\ ZhlZ`G4Z5v-s iɢoو}D;v| vt> p1O|?6R>mBۮ";;%,eip~׻E_Vk6P endstream endobj 983 0 obj << /Length 1263 /Filter /FlateDecode >> stream xX[o6~ϯ$˛DÀu[u u-;l%iw(0;sCH h 22& om~:#F.x&}~M#% \U)}F1c,$|e<U_5ZU)۲^QLNeH|2%評~nFY4E8a;epRf9 .@vuM]5u]rzFh8I1geCnU]|prIȴq|YG4 'ӖojLZL!ߔi\eM@e6Z;F_UD/E,4[P U]  1QDTߙ"<,4nXm&!H& 5>=KA<(&8Wxo}Fan7|FHAI+tUD`Ċ y(V#Tɍ!լ};TbnUWšHM/m5ϾnA@HÝڬ~?KlFbA]1 b-$S4ɋs(075tLQ'A.;rO\ٴ>=.=g=xTxrȳCG Tk!Z}DCs,l[%]nT pb7TτY4V{L>=EGёBBɉ,.[ĵ!e 3$#aV'mY9P F, g݁@e%{n^)}m̨Hϟ㓓LP:4X ^pD>Ǽ {sS#ẖV-æu%\Ws2y+w;#*¾̬hVh%\1L_ubPj{\#C*F2;v@mZyDUoM۳]~,CNM=t[62;žCcרr鵻 xF8Ƚt+D%@lbz6Vt\y`:?e!ɛZ|%a wȁjMbw;Da`,|6/>n/q1$aXSGo|D@[I5{Ơ? endstream endobj 986 0 obj << /Length 948 /Filter /FlateDecode >> stream xW]o0}߯xrw^j/׺MFn﹎4I3 4is=ԣ,J5ǚtsD"ohK 0D2g$dޅ̢T9ʞƉ@|Zܭta綴 KϓGg6dKȴ>tX h+LurCh MdWT>Z_Yoa[O!M9ۭo*]Śb]~f@VL85Jz Oj*P *89(R0E=ʭYlq< NL4 OzZ(5M}$c,@=8T\ n XV1s{`;c*:P?7m,e w'.fWmz)G+Λ. LE+3O<K,~ 㱬I@Lę5N$V*_̹͊/9H04]wկd s? g|P@Kq],VX{= F'aifu`/~+bQJ@+7Ywy_X28FN@Sm ~j ;cotE13nqܵ!\UvOQɈ^Ycnd`%Lse{9Fa)?V_T&70ZzbZLxfaSMRtI߫D_wPտ~\cbnG%[XvNޭB?!kCvbglk+=y)n m-2a)kzm&9vU}[S'a!_|(hb1f:)1u/\#awS\XlqB1U endstream endobj 989 0 obj << /Length 1495 /Filter /FlateDecode >> stream xX[o6~ϯ$ˋHI +ڡvk恱h[%y,;H:C 2);"?e4rrEn n] /^<" j*꺌>į7r׫n0"IS]i|h}6MW+թf Ͱ(b7?^#3iD€W"ȤaZݡAb!BٹEHHZ&/ۦQ^V]ٕivpM&N>;cʽR}*#(O;!a W d߹/)_u- sC)IaE\hoѾ[9b`D1bnxxg#8)E4G#:9"ٰ2$%C aŶmdBR UA@iM$!y ӑ '_M,|?-L:d(p 9:B"Ͽp/wrVଐ}ѐC7&ڄ1n~c۝zhdf5ۑin$[:h .VŴ"ܺ9ʀ2NLdTdwo:cSpрt&0m6a[ߵI;u'ZS[ڇy҂NȘsjXuݻj/]AYw[D91x@bH>ge"CI,G|~18t{Z;/HQ^Ԅ#O%NYSftF-\Ba #sYdiQpXqf?`W9_ПP@`1S٩5V4ÎV][L땊k !]ܦ֏7:>/a\؜8TA= mOrE滕ClCй_j<)<U9z1G:WY7'9LLaw&xm6S{oRڵ`F{}nSA!>D5$~9tANБeAOڝ"ϑTSW<<_OH| ӟ,GQX v]npTK3K!nⷩ"r$aH. Lƍ, By\ݙ2ëL-ɎҫZ7tX&rp~6e]p4z3G[?jwc0rz(g9ZODy c*>s2!%hva:✯ |bN<Ȁўq۾mUH)}OO3?"tY_@Bxlj3URq)hL0!P~h?Ƈ#sۨ3R_>SxL3EB2 nCQ.kuTo\8sK>}I?n<i$,FC Qi endstream endobj 993 0 obj << /Length 1181 /Filter /FlateDecode >> stream xXnF}W$`W M->0f!*/rt,;҇€Ξ93{v$ExqBQBc/ߜDm}㙇oN 0Y~89J{b῾ͶRꧯ1_ 2oT3/We.đH}??6#H{{pa"%E)" f+۶F*<"0F)D-0]Xq1(8` 8q) {f@x(a8#Gآs2A4e^`ٚd Hw }R!e^YJ}ˣ3۬1ؗR)\ݕeQޘxλDAh >295Iavmc#OǑ!%ѥ=Zʌ+s/jBQQ巖,Yﻮ=2C'(〣‡2fH6Mvi6 窕̫Δ}z!,Uljl+bJN^fjnXy<%3'U{}#YğI>>}qײ)ƫٺyqh L]gyWxvz(݌ѺQNv|ҹ-#`)Ϻ=׺pwJz,TQ_W NU}E^\t۴UdEgnxrxꢕyͮpT Yߪ-lgK1 y1pjmsi;9zL9)_$t/3Qx endstream endobj 996 0 obj << /Length 1006 /Filter /FlateDecode >> stream xW[kF~KAdBm>4}ήUvV33%$ Ңs9ߌY@)LLjA6p?zP/xkFINs,7cWugxuX/XJ2)JdlLmʕb$Zvq+Lt30A(kRBt))msᡸ|\ bDQit;UҬvzed(V*d.jcIrr6xF,; ~lܺȥ q8u`buѠ>7I>RIwKA.NSUbw৓}҅1|7nh@=S$vE1&5ͦrB}t_axer֮"6T5h=M$ 3ݺG`_u..L#$=.$QHP쎄i1 b].wEiU P>7dJ||)~74z97*RL~T0Cl|mze8M A _]ebnHq5ƒ\)>.Cv`M:YJ =%XP-{K>;۠8QߞŜx%n2|76O+ \#41ۊndTm ӁOk3^Dh&guB6W9st \k@g|Hx*N dJDOT"pѫ3? r.LlQ'L %K F@k֜AbD3{>Gj bIyNdҤ PgmNTOfoǾix!чC]Y٧b~&iWQkˎ A_B3EFXvZ_쭤SopTBkGĘrD"tv1ot#elJJ k<߮?_hǨ endstream endobj 999 0 obj << /Length 1182 /Filter /FlateDecode >> stream xXKoFWpX)R'm.+y3=6F<9>$kk|i0 0 A2$(/Ymn{sqv137o 2`l_«Щ&ca69(a_]YW N5*T,d,uŏpAt~7qIT",!B(&a˪ +}glj'Cr} i.N*,ԛګNBL:g(I?7xk {c 쬒;(V=y")h8\^i!`JPJ6J7Pj˹eܣHSE%#}-9*0$ /S(Kc`]j nAM%^"F3WC}[]Jy6$c5Xb)u #FsdW9dbgfKSM?hh јJl#],ܔ-T/L# LtL+ijsCQvK]F6FBc&M8| 8xrKE Uew1-S ]:5F rpz:;I8XL3w "|)s2:~Y*Dwq.2)gCe^\Of ׻;eW꾃Ew̪i*┉o@X4-db Lqyl|vܤQikhexD3Y1 W)F>mϲW ^@vPD63Q/_Q_[HJ> stream xXKo6WQ,Q(Ez ArJ7BjE[ڮhQp̓̊(*\ D>P;mWnp CwW'gR%-j3Wu^ߔAwq"7q2UM5mcVRotJ iVD"䇫p%x"R/+&A'n`㊹qtdPX mgv\M~U}[W|-Au SDf)Yk%(X7iCʹ=UĂ"Dff`i7#:hoR&F3M%Z:+S37S!(y*>ytIMNZ@l) ` lRitv.?St2*3KA^J$ 2$MRT~&Ndn>!ic,b.Xy ?ag)}7`H@$-Dx ~AMǕ2oػ^w5hׯ!SeAWko\2.E&L1Wѽ;zFfm<+uE{@R #\jaԼr-ɑ#"hYޑSY eDr!Bf7lsd69,IE};Ooqvbnpqmqtkvm+ 61#]k7^^?h8*wLJE!ף'=ew$=30>/#4Hƣw& ̣,M>) Gcuޭ޴)w1r7޽ ~Ũ!ϵޔn04s2=,S8Yҥ _L"?/M/Ăʇ|r+/No?FZV˷bEj_>FZ7^PG.(\y9F YE ƶg8ۢǶm-s tw;}Jaʗ:s¡g03:WG^_?1ouX_dkA+qECi!|0eS}2mjXnknEa$ Z  KxY}yF-Ex [o;ݷcW$Z̈u\> stream xXߏ6~GV:|"U6U}j-,- w%[U(R57 8$YMVρ w8Fy`\ڗSэEI]D) 2NaFޡ8^4@2X8Hw#4Ӟ74H4^P.\I2T1sxHWx 8 ;yjQQ훭m)Cs 7Jc-kǗEcpo_/s2 qjQ}5:N` )~9ls兣dAVe/aܡ/a sJܬ|U׷]SŖ/#uzJnARsZ]KCWnRt8T(JES;OU]+ht (ӹ8;䚱qk~m[!βVGyPD3(GQbp"7E9AhdYSdjalC{>XFҲbّObW:7Z77i`#/iUFISZ4gk8tR{lμ5[{M4^1=yo>Lhvtz ٞ>>S0n`Yݏ;H4~QV}bmZT&&!u} ?pL!돩'A~F5Ss ܪVS|FPWWTٺ+l%d#=<EӚ*XxZ1*jj64RRi'ұ7S>N'CPC endstream endobj 905 0 obj << /Type /ObjStm /N 100 /First 873 /Length 1100 /Filter /FlateDecode >> stream xYn[7+ ,Fm] ͢EE.lHgԗFŕr{Ι3bf(é;55bajVZ2SkÿT*5'cN= OuZR,>-U4ʚ)rvhf9 7|v VjE:UP Tu,b@Rzʈ֑\,8 V T]8cA搕H*00]<$[)) n򼩡WpIǀ`R%UXCsP$UŰ(cZaEX]zP$ eR`W]ib@`AET"|z}v>iW7tyI+_A@;c ֯nykZzyE7Zo}wnV]u~t~s~|w^4T̷ۻ;,AYLL̗_I=Ox,*살Jctyuy=Ѿm־@>#+ffdlbd{2րK,-ڍ}>e,]_Oru9 &,eA]Vxس2O󟶁M_ۅزW JZ[>"Qx[FQV4H}_vL̃5ϣj<ZXI-|Zl|c"sȠY]_9'QQŎ'R<{Q^-<ۤg#Zyj3>>:EoGbG.Z'fŻ`-ǣQ {g#Q' 箧MGc에Y]yfq ;X_b_b{gyT oʶ?Nwׯr?h. endstream endobj 1009 0 obj << /Length 1386 /Filter /FlateDecode >> stream xXKo6W(W|Z@mh/zt6 IN;P2i+NZ@yp"]lQhN4/ܭv7 \xF\Y ٛR.hNʼuj5yw[mӥ<)ߦ2yjlP}"K6i&X2*%D B\ZZZNH.B2._d {U5T^,rDT;aglgg5[C @}E/ 3ZQz~0Vw}v![m=#-Ir34wL*|6MX[.M ;e SRJɼ|YPSMjCJN8㦏 ؼNj95%:ss 5`9dNqtN]s6!~Tc]׵̲m՚"BÈŗ2cBq.$P8[ ׬S9'ǒ&e:ާ tl8^[gKn S7>xpf9¶lcxu"jimD׭00 l'fqyieR0.̔0 m0ͬ:`c=vֆC'{29FFO e.< Eb$F=RAzt NƫkFSSٽ&*q3)_X[C;ZS,DLqRT*%H.6']ةsѮWZq;]N=4\&Pkp hZG>])3Uc =کָn ʬ+ow-*>׼y9U/Vx,E^3t^άo 9tR Sqb5FEiRk`5(VdL.u@;^,_$? 8 cWf.{bq^B^Bv[X[E1nc(r;cM y/d/%R}[I+H-R#;#ţ\.-.cW5f~E䜀LFG`ilwe=^mw+7pntlW;wOacRytHNТD{.kYSpO.=$ܿ(Frv/,JpJ= XvBG:27Sܴcn3gKK!Cġ"wﱶ)#q;i?#ER>( 7ctArFC9ۯE:vD ?Y3_ =˙K,\qj08,Thkb?m_4rzlP@/H 6~愌@Lc_ endstream endobj 1013 0 obj << /Length 1392 /Filter /FlateDecode >> stream xXKo6W,X )zԵ !@,qm5dHZ?RwHҮض9>K 3|ي[*8x*OoWvq C'/\1JrzZ} Qa97a$ .LoDp֪Wm(Ni< \vr~/$R#-u{fqB^mn8!T ke}=8O$(XGA3 Pd]/U*ovtk,Pڄ,ˆ5,[t{̼oF ٫%#YNHwz{& ކiS_hؑE[-U1ud$SkXb\ OwdGW<~C EnTvhԘ*;xg̛ y̻n՞!zטd֯[֟)6SI+.6Kvi2Vȝa{*݅5'ĺA!f6ö+m**D %4 ri+j-. TkfQxfRNMq&',\&pmAOlvWۇ\BqD2U5zǐf<5:CO\MYJ970 H`&'>{˜b:|C;eKJƞEE)ir™1?.5nHq(VړzS˼Y ۍQ]Wu1qȫm+SW,÷zaJ/0s^)mCѻzԮk<3b2nt2?2ZDTalg>Se1}= >n\i"wU̾dSrxJ_!,> EφLs7;ӹ ;+3| /뭶4?DEoPeJHo$^Sh,8}]4w\Syw1~̴' Qo9%+[MCq,Riaܷ+)|4M#2}C?L%w?7 endstream endobj 1016 0 obj << /Length 1336 /Filter /FlateDecode >> stream xX[o6~ϯDH`֬MЗM*IХCo(ӎݵ[ 1Ys>#8Y񌢌*Vw+}+lE0|xus (szM=nV] #Ji߆Q>̒`}YW$x#Zq4 ?vqܜXBDjW S^ (f0b) ~lh?^Wp`#ڛM5"$,!ܧ|1#bA8Z*zKr`ZC(ڶ£ YOꧏ>K8 acq8O"̰^d[`'̴PuI5(ֽQV$I=UwB rjZCus#\cj3>s`!( FsC!1[Ov3U^E/6ƽ̓ kX͊%HbCaUMPg+1 q+AOCW!8Ej^5%,] a/k2NZz2$Z$g %?AIP'^_8Ȫ]ɏA\s{Ti3DS* %iouDn[P٨N$EtPE`7 mt={ 9'dk- PL %gloyG۷"/rg[[/5;Bw0h2#Qz^Rp+s-="֫і랲y0E.^Sqjo4I3837]w=rޚtF4zEnҤR*NʪCM_B endstream endobj 1019 0 obj << /Length 1085 /Filter /FlateDecode >> stream xŗKo6BNK$]:E{htom]nV,zP$Xɉ- h i$A!)Td0YqD`w?Y&)bx.,CWy]t**knܜ8/TWr% 0E 5re$E gVOewS f3Zd3&ԇNmYsϪ}s~hky4{cz Yy[ Y-UaJhx\mRvSkȥHș-wZ߅, ItU;W Be@s[EKpRy>EM0U{اFnGavt,10Re*aiqW4Ef6U5Oz7; NN:CD\Yd9{|3 o!l0=xr!zf>xs$o%K,'׫N*.ߚMv+dg 3igw✵*2h֧(*?y#/[usP ]d0~ ؇@&i'f!qC @@e2E4뼵~zn|A_4 f'ww3Z?B8ػ]l3vCDvyʊI|9| ='q_Iúg`0DYJ``pŭbQ*>[wI59FzWG]Nodln,O!+j_6'(m7F?!>nntuM['qvƽ95Ƃ\^wXF AuL F $)o"3}XMRn j|p{bz`Ϋ6oظsNq?!//3 endstream endobj 1022 0 obj << /Length 1322 /Filter /FlateDecode >> stream xXMo6WۋDH"@`S@ 5C٦-lGKrHY93o3 8$9E9p1/R0v$^]\1IUOmSJ:ӔwQC髦V_AD+ꍈb“$ghXJDjO$%K2!,#Oh#^JcЮ2` ƈҔ1zi(\Q4-y8aI٢@InX""lfIňJ&]ؠ<c%"0?HIe#3zفL ?H%f|ok})\qZ!uCZ|8wqSFsEo0)]M/mՋ,b%PzY^J=2+$of Pwed_A3gih/uyK_߳G ~PYHF|ԖԿ&g*>tUD 6է6+:ACIR\Co2~n)KmD%"pRNW,FOeb H8ѱA+8+f6M]KOe0FF8C݈d{"l0݈OrA;O^oC ERDzj;T k`+{0_nf+P`j=n$Q)Ey"3aKT{Vr!PO\eL8;6%c9s-$}r'NPv=6]Yr٦O2xgGvηr2R{]_q/J)b)H 7ZnO 6ЍQDvo{j/0J a ?~/a[֏VEGcE/KX-><QjV3-:~#jjVc!&Z2Չ 6Z<  Z۽4a!glo?n\,Lu, P_= ReX hZ2\6_J&-nk]jŪsۓl}1}ٚ_SP endstream endobj 1025 0 obj << /Length 1373 /Filter /FlateDecode >> stream xXnF+ts 0M:HN9$9Rb ;T/\8@`]]˫W&~,D1X2[b|__h34NlZf6١qZy-&5piCsm+e.M ABm)-l`'UkZ]wvg̟ȇ`,7vsT7 fϤ9f\Ґ}CL8~UQ)kEuu$)%8Z?ەjߣ1/ C{u3agHP!bP[RWES.GNgP<6 &t]/:bhCHmKl0'Mʫ63*u}DFR&2 /r_'Ulv"$=? 9tXi 2㘌N pˑ]>zzğ~579Mä2}JGȲl; 3/@A dmH`̆FYO`f%P5]K̫cYbyVH &WjڝJ̡1 C[shLcbOMeNK殣9,fN*aH[z_%k&.VY]V暧v /MNv/`C;CͶVw8A JEm:naϾيxd> idVNDwxkԵIU5`&&=e:FSD1Zl'+ xm9L@fX endstream endobj 1028 0 obj << /Length 1442 /Filter /FlateDecode >> stream xXMoFW 0(H遦V(A}g?HqeFQ#Ыۙ7oIf3339+7خ3pv)#_.>1#)n9vuܬmyK<\$9OuUMm~ɭ^VץTL%\PgD[0gHI3w?ۙ;5DyVws%`,wmRZ/ܶEW=-f㞺vf~vEq1$oQwu (G[Uևt~kNa #L ArB y*2Ss׫Vtd3BRr;S3ؽ!DOO̷[?KF*R6IqZvc}|T@@0U&X^pE'  xXwoY'":#\ΩS#`<,(:baՈFE{P$`s""Hw}ct66SU\ yUnʯ'| ,B|"CL(VmI*IE #_U&}I> f}T `27\uS,~0U`|~O#YnGe^jO0Fңg/ԉK]z֘>Q~!W{f(Wk9H wP+pΨfŊz<ѵWy[&pKm^B[ۉ:sk۪޽X 'M42;m$)6V []Ϙ2vק@ToH"s9eS׺KL.U CW bQSc2~TH]NS.6:yQ%ԑ$>p$,l)A,etxkVUܝ*OAt10 Jگrd6:daH:@@v*|7+U[sb2U/kΧ oJFm1Ӄ(/m,7 Fv w8EY6mf; /Px>PnUVC`}˾ʹx+q4棽ABB':d5+Ch:ZQ*ר_~8 թ$a[c K6dCx|:˒D\Q258pŇeoM.1'qH?b䣂@~׿~<||RF_[> )*pªM:m 1T6~mO䴐0)jf0rݪڍh8^`ÕpȒ/2uq@Sq,4.8.#u=Տ}O _ endstream endobj 1032 0 obj << /Length 1234 /Filter /FlateDecode >> stream xXKoFW%`O.Ӆ{iȡɁ&W1[Yp>(r%V\`of RGFbX,*R+m>Eaz (&gWBD$yhZVb&Nc(' t+MۍBt72Go.Gp)RSK,DHkoU ?.mʀYD΅V%c"3u_S-ER V-OEB4RaJ԰hm1oRT(h>(]̙09@DfBfBIej۸@. 6ƙ̦&!|i vfX=ROc!)N)yC %2C lbюԝ'!d8gb m1ȓnjU+7s)eBͤ40!N B>=]˺5i&@BbM`dbɲBs{/Vs)Φmv];#<=g9M= >Fnwf^9l1!P~ImOϵgC,5DֆCnSr@ |sj` xMv.Qf-Ueq_Z83}½Z~ջeQ=l22?=򵆾. FJƒg{|p7ŝeH|v\agdJ"G_MR:Jt"fDB:FqH-3SU[I-}ZGu~QM=njKgzU憗M aqw#v/WqΆ}H|o?U69u/+O=>#bXW3Nnps> stream xXmk6_bY,PJ ~ck/F&{-H6 ǚ=3M ?x#FTlEjު 0L]\}|STmCُR 4* c<,:t^aGJ"Ҭ⇻ysN8⌞t> (n!,'Pʙ|qCp2t`2 qV$%6k[Yꏚ|lty"Ti9OpDJu97m e(g IeQQ>[m|C'CU~rr)#9=b"")[r{FN L89g&D T_d~L^Mꠚds)q1rAIH"nc `|J'wKR3Z xDB>qZ(cTpNDW w\s|?0 dשZ `~bUrX 8[Ynm7띞SodaLY뎿-N endstream endobj 1038 0 obj << /Length 1355 /Filter /FlateDecode >> stream xXKo6W21Kn饋@mEoڒG%6;mP`$of(In_lYcΣ?7X|l͜dתbj;Q:PsxGݭILpľ3X0AQMQNKxRPు;loXPa7$e\jjer.|diVj߃;Ij0 la轖9Χ1ҵ£u3~U-we[]iKEq,SzY j-Xڈ"̱%iU)(Sb8$ 8\H @G!`mo\ZY3z~iA(J]4Ge }jG7$tXuO)Q9>\lm '; :m2^!3 Pk5KSO2ur#=A2 d%$`xj>®TC0\LQdCU\:Gkm"yC< OxUQ5`MD߃ju(&*tќOs c]ZL/ȬÚVy,Uz?V{V?zk>SM˩`;O+;Dԝu+׮ﰘ$>w بypS&ɈnlUkOT d;X1 E[1DP682Kg쩎2uOEiW ד#Mb1 ؓu( -0 :D>X  J̦ ň#~y" Q_*3)wRiG=捅l+pꜺ{nR$"l4mrScٝzaL/PrLO =+|@q_44CeT&޻aZb'z,>)ѣzcS%TS7`;;#0Ops{N=pmmh] kk>ya*#о(R3j }cJ. 7=\:E]fo +-a`piê ƨ&\r$Cf(%P@j }~V8w"m$1ӄ ;Vd}}4M0װ'2NeګtSPoBvfα{ U]AԁǴ endstream endobj 1041 0 obj << /Length 1469 /Filter /FlateDecode >> stream xXK6 byRDz4Lַ٢c6Z#@=l:M{irD.[-RH(Ȣt{ |HA"8^0Ü-6Mû;N+?"/򅈽Lxzש6_^e+\< /7?m1XDDj/f| n,< X x1S… HhIh&&Re||ԵuDwmg|A W01 %ů1Hh5VTk|I`Pń#[ "o-eJkrojgDey8zIZڦeVIwEs(ԓ;!d$ܬ7h)릓h {f,f:pٵdp;ʃZYRN PlR5;=i':,jg-eA]PN/jR"h7B2;CW fACI`>rByMfoRF$ɮ&)k4mY9WTȨKЗiuwjcv ZDTPXqpp̋QS#<8I k#KEB!jDQ)'V#լh`f([$uDŽ a1qU]['"y\Vo[boABEQr /dx65miH ϗzk ݒGdYV/QKC$g}P38 }DA-N%FEY6yB< /yH-jOY~yzS4ottk:Y !Vkd?}Jb?[;lͭaqi]3|,Z5 AIu~IT)l6릖˫ނ@?>B[]ƒu>vLSmHG#7tb4tT*o<L"Xgv,p@o_8kjLTJ鴭`>AyrfZ)!LX.m47#&ҳ9hPl -T7v8k4t2K> stream xX]D}_aO=_q%$T`QyUkv۲^'"@U29sfq?  I"*7}܇w`KLov78p4qJ㯟nT&M6ŇuۘoXN=^5$DY3eͷcpN8^4_ȕ$ȕ8IRΜ߂(U?j5At(eԿ{R.a,U{T .1@ۺn7Du=.7866lqI]ġւ*YڐU.{UT)xc`47aeĖ_jʸ _wl R/Mt7@n,Î"̱f^ v2g۷6 2aoR )2zh'jVopNBr$, b5!U?`QW0 }}ly8TʘJyZl[UXw09{~t-l~oJWwul;Cfb 1oV&ޒs]p},fz֥:qVRnoճyA5iu'#.(WCzD#rx⋾:#%h 8@k6N͜#1"16ٽņ"Qg)(oE{d΄ʣpS/S>5&,$S&VKDo\6y.Yc|Jםmp \.PJ94iag3'ϙ4K#AWX"d}1KXHa͙d\!Oy.5i4 /H2Dx@2_/,.[ax#ϩMbƐX86?K36UpOҿOm@_ TR&)pv=v 1tK?iǔEUiIMI06;Pzvz{+rqI9$]dVgNޤN1xQ}XI)yί'%|}bfIsc?_?b:K$1'-{F3G]n(bFP{OꊋG̀nπ~\+4;>"T endstream endobj 1048 0 obj << /Length 1381 /Filter /FlateDecode >> stream xXK6QV z(v-Kt6u =6M~}f8,ڍ.<>Y,8ĢTTbul~A?^/`6ŵ1 Y+LUݬ&Ww}o4SJ%4$i^ۦzeL<]txDOr!79F܊̤ea/Z\#yUHԬ,Jڽ^K3TL \NRߤ.SjńPA7|dͤ5?ʈ,2sZ x$co9P3)S c/5 #^U^}kW~9eq825+ߢ2dIn:g'':e2ܧ tK-l6Eg{ݴ}tVHS7v.w4o1BoL;aim~}e \$+7#l`X  5L}]~rY˕>R0pKY5umW]S1#|;G:Rؚv-jt c@4g)IFur.׸#lvëPlg)R_!F2.dTc] ڮUe˨jҡKcC:VmȧAC=- endstream endobj 1052 0 obj << /Length 1660 /Filter /FlateDecode >> stream xXێ6}߯0bEnb  ~k [tԖ I&!9Ŧw7 P pt?lfdûn(څ`,^ܾHtڎ]_ݮ8vY 7LjөoDNne#\,<7cX"up36De ba$'l ~* >-Јn$R1Y+`hdl&4Jh8&I;QѨhp|lBfi0gw˲m;_gd=Z` Nr.F0['<@iN^nGRXgnQU>4#˟H1H U!#S75b(<#,(MC0!OOUq>wftYJ S?w1t"FkdIY =*P7$j40xWM}8,X jˈ鹵ydMyRUMf*nEvԵCM$Eהޓ@9S/t+`3z|ECth B皟a3c6,X|Z `I/:3C-N;b7݂$04ok<{־p>m;οkM =fk "=\oǵEzB'\mhRVu's)4n1FʰaoVI?˪$"+`nÝ}>^t!8]RFr`p ;m)vGNN)L$g0zuNNMXNMoMҍS128--:]Y━xqKŋ$.€ܝuL;4#RAi!‹^d[QI`=4el }>dei煑Uj {{:k mu;uK;b\9viuUiNY a 4y f$ie-i^!×:\*le71j?txK- :v r IƏ]143dTh #?Ё$_E^kt#5RjZivsLeCm6W$FG/Lڬg 1'Q/ZJAʳlu2 $!:.:4"^kFW2]fX>ٵ:hgW|d֡K k?$I&TA#Urw"jM> OulrEKZqTzo8ټ}kXͩcs]ў)kGU}2:ЗCh'U"H1V,X o-D;5j T;zͶС1ʵg/vo.Y6GgDYBsC K0񤛜E@%߸t;R,0`P}Akb<ƽ<$ӿy_ .]US5','~Kˬծ~V+ hC!Pǭ endstream endobj 1055 0 obj << /Length 1051 /Filter /FlateDecode >> stream xWMoFW 4PS.z0bݚ(J$.%^9N)€]}f툢^SS͕=^En3~0 oWohD(z7Zg> BιҿrU|7y̓(N|e} .$RW*jQN"ЋruLNH #݁(%ǦyyF^H=&j2ʷاɴ!p٪͡\0oP1!,ILMJ '6&O;+6iM3ۦY-il9䴋~3MAnuQbթݦ_fU,.,5B3m#_]^<+sMRhbC[k[l5sA0&HĬkõuq4eh8d'l*2ğ2pUM㇢nOK6LJ6&$AB0*_c)"o01  .&fS&*T(5aZ&[̹RL^1 ʺ[pO9բ s WPY$'B 7J͌/x}w}# .q &b|Sw37ܜ){s}*3f%M#IL:! )%<JJdl]U],Ek*TC?6^xcpy޴oO endstream endobj 1058 0 obj << /Length 1287 /Filter /FlateDecode >> stream xXKo6W,z"%P4hPoMk]K =Ç\kMl8NQ]jq|?X%lܖq 2C?,q!H’.!abPF(9E;J3 TӔݵrΒk]Yƌ8K0{nm/- &o1WMb3sZ^]^Wʙ%f)Vf+|opcA8Xʛ/t^K,IIe: B%#a$$ ~,L k7bHtH&8$")pP`I0K0'*1a8ulnNwt %!o.:.9%(a3` .!McWj=R|(DZvZ%%>~GXo5kx_vgڴw1eSƎnMF7vg/ |4wBvGّ3р/D4FܧtYڵsVyMZ^|$KrGN&^pdJteIY-3#ž1l69M!\^[M {$3bg*C/LZF;x#WOL޸̢tQA >uNm H}UP;b9k a5=t[}%_T:e.\]WyJ=~ <k]cbԨy!suj~' !CH N CBN{tB3$ ̫)E"SHgoCS GAا;8sfyxYr!'sҽL?ӝ:B7|QgscN_Fm%nA~ 0I /`z> stream xXKo6WQ X4_ںu^.rhz\[FZaCN ZA9$|3lA_dJ%Ef^.~9b(`<,IlqnuZ^XoItT2겯BuR/c4ףDj BA_.O MS7'9Q8Iy a]UQ.#yp.b.[>KZ%{ORt7I^h|*Q,5YHe*@MuM׼9#w la.VAP7y6?g/`9˵.o^39+3niCi+3l$m /mJ[z>d$i~8LDÊp)ɢ^yC[4[}t"妱c&qMcC DZ9‘9s؞L NnF>JMB2FU^.#=H7Ug6%|H4*#Tfo͡mī8GAmī5L5Bp2f7SvDinO,enܗ+a¿(`]_ed'5|(yg}M+"f+寲zy7A.zi#0q+lOɉLgzB~W OG}+;:ILyX(Z8"opʮ+K\Cnk°NVz[SD.MP1&^ w r$pBܙMrl-5C[Z2,G2)w1?_ endstream endobj 1064 0 obj << /Length 1017 /Filter /FlateDecode >> stream xX[F}_#Hd0DT5TTU c/\fl3ޤiҪFp滜’Ç) RɐdiPlopWo{q q;!Q3cU}wQ Q̹E}]tUS_xxJPQLSd`ѯnVHpv\I{2A$N ,5}ecp%Kw(/ $Pl]:M]!SEg]cXkk:fmL2gOOmz.Ȃh FB!x$! k~s"xUV) t'!(XQŢ2ơ8N9ɉU^B44 7i!F5*W]!*#]1Z7["'SOTY4u JTYf^V㾭%Y;cunsH2i#@y΋ͯ!NstLr n]$׎}7}hU6n, 'Uv˾iya:+xlVl;#̯sFu~WxYӴ! Tyk5!D4 67Twy>`"!/ wGxqYz) zyi)wL >$rLقe5TW{?Zi!88,>W ,wD~\} 0~}.Ѥ>MPl@if Na~՟Rq^ψKҔh (]/NW;%yR&|8̪?͏e6c01q1`Y8O2N7:?SK`e\a_le B'oaoa=^^ON0B۬6ۭz;60 (+w_> endstream endobj 1067 0 obj << /Length 1455 /Filter /FlateDecode >> stream xXK6-21D4-Z$H}k{mW,zdPdm-PbyZd&'pj{o$˅ N$ݽzFF =LU펛җ6L$(^oCtn`h}eQlPn8"jx*B^nod""pT tƩ"5z0mB4aAӲR 2u2!Y~MSH8T=߆Zڥ!+ %bդoөl/UAG"I!xЭ>X{syAOաg@%H7ҘsHe"Tu!O[ ܟ KNmJ>=(LQaɢb%:::sWD lz;Pk?!,xjnVe)/rZC³qyP %tD*eWX3i&(w{HG/v xym(ND8;_RƵR7=K{tކ2W.Y@=r!Yq I3ɟzum1Oc.$k"̸^ lH.톶2#$\js>IǦ9a.R&q/Ltp+/_x9_W̘ͽ|2Pkd=FE _U<_!Md vO,*v*4Q |%Ρ 8H"8xphxMV]yQ\dQֱ?Tt-OfөO7-hB$,˕Ur]Ed,i>Zp@DtsT:*'>W`Lfs\1/q=u(Q֙ cY3- Wp̮e7 U7Gy'\Ȇx:&?M \!2%'Tw'X-v[KSlC …U!6YcӪrS{Zp!vsYJaB ?ra6hQ)rB  jb6$n#->%hM.qMrǩ51-qS̛P`ӓ\|BE ~Br 9zpA=Uu):z+vH9}m.H3ntl>tQCǛ&+r>oNCd~S[9DYCͨϙқ?^R cȽZ-n endstream endobj 1071 0 obj << /Length 1382 /Filter /FlateDecode >> stream xXn6}W,$-.)>4}PVWV2$;.ʎ@`pxf!) oh"g}n3Nv37gJmxȲ0뛹bv!)w;ֻljFzWFi?0<;^H1%3'ph ƌ'3Y$B~w6/ 7OX,ue}i}6'/ MxËO[ Vop)k^ /^űW'(Lk!7{?OcB?_6aAK~!ڷx!Gmɇ&!>5/^uU‡ Q]:PG?xX[#NL |1%惦BU7V!T,0s! LA8!ms۾H'pD~D@ P`͂Zwxɟ\rYTD`\$#w'C)X&i q8M)(I<L^B*&&Y&)ios Iv@$x_rWsYyՓ+ qG!MYpbb-iC+*ۊx;(`޶]R|<%nįU0\*e/:sƂvE,k'f]Q5Ǻ_J'I&HW&TGwC;eM=3J~eO\~ar m1N8ić Xr!>R|MH0jc0pJC| ;,ՔAct}x0) T7W1!ML&?VO]r7H:Z۱N"N!@hqЦ8ec2k{v<8p)'}FNmܜoQn=}:o,v\o{IE7v/kVYUG8ٞb~s vd$@&y^h/wNcUa7lWE$ W˲i,0st7f0|?0 endstream endobj 1074 0 obj << /Length 1171 /Filter /FlateDecode >> stream xWMo6WEbFH}!&-v5Cۃ,іRY$:CKrMR ͛:>Q'bN$"'۟nŧ(ڭp5|>¡>I:tuid筂 p+oŹp8:SeS_Ine'Lz+a{\0A^Z?3. /TE]9D}gp̮+N 6C0~46+|݇=,(z[u)(ꦩ{2 1eL4n3nyQbs9pxhv_Ɋd  iDahpBD8]~(k|oS(ƫa7{%+ z w`d6_BMAs؆@t.!!(N̮[\R R((栴Vb .uQzYMُa*α~zB/֮,<(M::PyT< yo/RVfBYPI@DK}*P> dclI䟪t5v޲.g502ӕ*0UZnLQfg,@n'G@T pI)1D1luAFso+͏>K?ŧ׵^MG|jx&I5S74BmwxCc}]U|fO=Tgcٯ̆C_ֻ6loZJŁK^q-/ R|P{]vR'fĮFL'E f .52Vb5D¼80Ϲ}2|\qܶ#$dځtp,+k5ٍg3f<>CUUrծQ͓`>>[AtU>FekP-{"ZleV CzEW^t=bdj}Ezu=N&YJ^`b>ͩ]0?k,5o> stream xWMo0WH#NޠB {!q۠4^C-Il/I6E倪7ތ4 GX4oO쇋w'E`M,_oN^"+htvm;݄0cކ2F}w]+:aR($ɛ.`?އpei >Y- Q`{4l>ݍe޷n43[>W2l4xsBOĞ{$$1hSHSsm]ˀ,X@bB"Y ٹ}jHwSPl]>ëFkpucD)v0GsQ 8pevyc&I|B4TqPm5EY_GYV ]'sNrz\0K9e t<lطPN PmPAV:[3#zuZCg,Cwݘ[fM6e9z$n ރC4GIc6%w$zvvķj€ubQ7ppAgތΣg+\qf d9FޞDkәc2!QSMfdXSӘ;gDg 69Sb8ć1 t©ɧj͇bR ոUY^Gm=jRn61$-ݪ)ilك-n#*$/4^Rd(CpDemJ[|*6gorIj{zӵo+ŽL̪֜Ng_\6 endstream endobj 1080 0 obj << /Length 1100 /Filter /FlateDecode >> stream xWMo8WE"ߔem]JLD 6~gDʖl9ubc ̛G-(|IIYgmo~ v &#_gZ0J2zjY.nm!2NT8Ѧ.ܪqEFmm]8,Riuٻ6()ND:XM BkBpl5 bmvNOH 3DaG(†IJ 1O|*ܭ'_ y[nVuoqttg G$w4aVu7Kʣ8pGPU ˲i*?d:n>e+L) Zg޼vԒQ= %F}as&25Ö4Y0" 9g cdF@~ s`hĖjk 32L=5`2\ KüM1o :檩;n Yp`Z`qnr4-?;g1Ő+'\kߞ1u|'5\@aP/!a5==}T r&r*5&j֨y<ⴎ0f[AM3whA@ajӎOn{-x> VG盈y᳗!+#PlmFJ}W[RiBs'S;Hd'-}k%];>KO#vA<f+i> stream xWM8ϯRK&JH=}690&čoL0aZz^2@ ?d4CeAy8]u؋3bO"_nxy@0qN4ն QKŌ0I7H¡-uݵf% 7r'lK4i a^]BCԪYæ%KZ wK.n$rYk{ D6U,\*,~Oϗ[{,mɔQTҙ|0`f<T[ PDS.RP2i 7Uݛaɡ5vcVJPx=o ¬^.X4#z=ܢh'v?5`_B:7]\g؋hi}f!(眎f$81MڏP"؋"aPZV0kGd~9%g1Țc[܋aw[ĽKhk&,ܞ;ntTizw?0Ey7ܨ@ צ#Uc.H* #:arw6YgF,T2&9Z 0M8dѷnVzњ-#L|<Ɲ^~a|MȾZfk -1__vWra-O- ֓[NX)TCvuWTUjN]5~pdV/drп.gݡgLUڵcwߵ-Bu氟kκ,`3PfķOY| endstream endobj 1087 0 obj << /Length 1175 /Filter /FlateDecode >> stream xXnF}Wy"pͽqI})8W1SxQM""AڀC-gg̜9 Ł (ʨMWρyx[ ϫ8Ay`ZKdŔ0bx>X86jr#;٬ey&џ_oޭsgJ nFLQx\3Se7TW |aXO`OPA ",=66iXHu>yxљoZ<c{j!ErX!c/aK%  (<"׃Y#I' k6WX~x?:AQp$JNSt^޼1F`Qj>`sɸ՚[Y4'6WYPtcԥ̻!bBs[9'J0F9sc>ShF.П"՞aDyQ,ܮo< X%jAs4Յ2(V]u$=Z@#A_oMHnis"RJJ0o28:No~4?^*5jd8\3`ƯWd19=iTS}=z*Lxj'u>ЊKlv,洙ݑr8=`4;u(әGμ[eZT]o5RVHrXqӌV4fոi#_OVfP5OE%X]9b)P*RoPM1nR1>gw!Q A'kq bˈbtE_=Õ!N8"ln\wn+*_gs%f/qubiZQ?({^WQ2-i e_VʺU,ܫ;Nv췯VQU?mYu| @I8PZ\_t.c8ZS % cb۷w>tKZs|kwt{,9>mSfN[W.:N?D endstream endobj 1092 0 obj << /Length 1428 /Filter /FlateDecode >> stream xX]o6}ϯ0$oRE.=(ݸ%OK:u=l uxxy& dBi4S  JXNFxw Q+[OoCL,cEzYr.wK͋c6]kY޴+,²*$YqۻqrA]4~BWaHJt+DRRHZ}sܴݦknu h ]xؘmH-M\ԢEIyJI8"  MxۇAò$ÒcpyQCbuH ȏKZJ0.ZR?O s՜B.rl"P/|zׯ}.>Հr\ʀ] Ѧ=xP,VFz0M2%q 𳼧o7,#Q!s6t5܇ɬ oO`s#nl _?@޳7ANk&HӕO(KdrR\(%̒=oÅ"jB\љ}ƙ:Zۿ~kN68IDU3)S׻[pЬ&8٠ЧXw/(_^Ug+H3qBlV&Ε%cn.)?@{弝&viqTTi\?kN^,B4ٴ@;[me9s$vQC&MџGvݙ3 nb߬49\](T(iy=BջJ_?ֵO\8D*(brl^dO5HQ 9IE1gs'xX8 #NdyJB`$MWвY~H$wl&+\7 ʛc'{vj+x+]O ɹGVMYvbڵϞt"ׇؖp~\d:s wmaiT endstream endobj 1095 0 obj << /Length 1462 /Filter /FlateDecode >> stream xXn6}W ^DRZ/KmY}Pl9B\Iv~7$-A`gP$3 d&L LΖ {ixA] g=3Q 2[}j[fSƪx=O'yXwz%7պvYS*(A,~x&#'2u'ts:# a T 3C_vTj~XW2ĩ #[r&K7?em;B)LI81C8bZe_2\zvcjVwf]5Piн^tm-9%kCiG܈H2h b;"Y58}}?")<A6eyFYkrjPg}͑`оPM9D]h {@p򱪌} 2qn\8ATW`)!%HHi փ%sPcUH̍^~!Cn,ի44v"HA$a.E}uomHQ  xM}ψ:hL7~X!υsQy0j4kɫ;JH$)Qa{:U ^ 3 ud#]s;7qʾS*N>^s<.4la eԏHI1~Go8ҫ*BLso=0w jUTjO(9H,wC18`DT`E۞W.>\gMeN'br#e0v̎~˝Z;KT٤ endstream endobj 1098 0 obj << /Length 1312 /Filter /FlateDecode >> stream xXn6+d bėH MI 2uPd9Ԗ =R$%ѡf6mE]{HPp/ HR仫xm^=x  ˫{4Nq\ϡnYD0B+Oźh*/q ]rt G Z ŜiuW7݂ sMMwSk6*h`bam84`!P6^qFGqF݅( gYrԀNqO۟PC(1^Ӝeͪ/ZfޮuWVu3\glew;dM]| oZ_dz4v_h}(NuKT>^ҿ^e\'1#9z\R~6ʹdV^~1+VL-q(W7K >.ns _95Et" j~%> stream xW]o6}ϯ X~*-k 4yItԖ IΚK$[ܴ s:iB&%plN6IxF 7JPsf5)O:פLަF}Ut+}t+׸pi4Q9R"77O%X ~&a  La"EcL*~I3rjvU[7P8&G!IrFL mvM9BRKmtC(TC@JF>㍳nu!ŦEE >b)lb uw>!1J/SQ}-dƽϩ/W'd X*,22C XFB1q?%$xԜ&޹{]"ëٻ$!h0c5>ۼ2k̔{#'}qλ:_»iW92nߵcX#0+.CB$_f|-PQK)w(eu ݻ["Bh=  G ƹtX!ITwWN kOa &lbnUū}3>SI~pxĈuȡ|34~L\Iy\u݁M-\ |Ga9=FS\իi1AQ͜3mttn=lh]3nŪn6ꊍjǝq*Mu˳Uৰ֏Umc&{6}\XPXt4̿@̎[\],ݴM6"JP&^rE0a?wk6Ky]uM9ac@̟w 9"9D`%f=ߤy0 endstream endobj 1105 0 obj << /Length 992 /Filter /FlateDecode >> stream xWMo6WHO C6F 4v7y҆bw(R$" !7C.h(S+E35ב_l.hK0XܝJʈFi! GMpQxY.[׏+ۏwع2Ǯs i0..EgNnZQ.fsp1~c%φO:텓f8rQE㟯ҩ) R,Ds*{"ZLbNˍk9F f<[E%:{wSn6hw^Q{WBMڠQT;! -oZ_yK7r1}Aug|PLk z0B1ʫ6 }lҁSY蒭9m0Ĩ^YZ.`ؼ?zρ/ीzeso]h|HUM״CjשPX`z E(,aЋFGP.鷒( S;4Ρ+u|]L}l˚N|H}9>y1 FLqto UcfIUUзaVy%^ovgo; P.1#3OcFœԦ"2t09ވ̊-;YV.o0MsA忰 endstream endobj 1006 0 obj << /Type /ObjStm /N 100 /First 951 /Length 1195 /Filter /FlateDecode >> stream xՙn7 z]IH 0rh imtQvS^]]H_ҬSbH1ZHYC1dހu#@'9HP V(A1*,V{,Tca̘r.'uטMrt"17 mE=<$MϪ#@CkXGJ!Q(yQ蔳\ZD!KjàVȆ9yGգbR#(Ue+SO>15K,\i`Av,1/, #)orK1Y(QI`[9DZ`5*U)kE!M9D͒Pr9YC /#IDa(ir c2ֱTv5KPxH3"ES%’R[t+\ ߐ-'>A,zDykKn4n&ORSFSNOJ,T@lJt`UV3ĚPEtd(KX^UQr=4,bZ_\߇ "~w Anm`!>mǛ7_7*߽ o.w6fZP6wmTZ|n%͟[r'UƺՏbxp6\`%@p˗=ˣS}j'H#a)?ˣ7.U89 pp!I{yaҸ,qʏ ED!mqC&gWHtx8WHOqSyp;U2@tp'ǁuѶciaQGXyPWHOy!.g@(hR!LΣ#,BّthS\qBAD;q9V%,|G1|bcbKUWb-3ap/#h8sRhk m/$Ca-O%cO/}pљ^D;@tkݡ]1w$K8zCp,#,i<zh>Pl;> stream xWMs0WxŞ%wC)2m8DmI؝YYrb(&ؖ֫o߮`DDi4Snunoa>|=;8"! jj2K>onek,gas.ғL󴫦 O͕iL55YNE*ee~x^\Pg;"4! akjT",|Z-veqp8ɉByò9B8`QDқ掀Ƹxfͫ{^}Fu::魙1 sh/hފ*l>[jU,WnlZW6 53JP<FNbp`κvG:)=$xBң B/ގ#u^ra<$#AC#*L_x _bQ2D g蠻Aۖ}k~'qNB$n9|LK?<8*!BО_Hn %;BkCl3P1g`bxa:zbz PbH*$V${[t-ƕhoG ٹuK[KfGoeq571asw7ku0!A6Cz߶>̫^u#@vfav.'H= ;B}2\L*=|P#"spa|Ū>%fË!OiES<oXMjf%#Oiݮh-b&ňp Ta;QG=~ЛC+j uG]J#MԺm:͉:+`2ӻʎ{_U:ΤT\> stream xWMoFW=tK9$ȑ^6{ `+)nC@Wկ^ 0@@ LOwۇ@_~AL\ "OFH_BK;^Q (\C]USOxxUBE18DF_\|?o.@72/4 aka5 Xy[Ut]td9'!( 8)E:V#""kw7ST_~h( -$qC+IXvzQ"_ HpSXd'؇P$n'?4#A& .%#6SGU7UmB"A<6`LR4&E uSITmsVmO{8O-?)@Yi_+%@I75u׷C7(F hU+}6c#ws^3$%'ᣏ7~a6ؐ<(R7|DBE4 {،I#k3C'M6w7WNZVK҂<,4YL8gOdP~(|E9c ?ڵc]\d)yv.Gem=%Ju$!)Ck(>2 (1 LӍ{+ȏU5l,n:WE>{H Pʳӓ Fw/+) g9NvD2FOQOé*5af8~< % endstream endobj 1117 0 obj << /Length 1026 /Filter /FlateDecode >> stream xWMo6WE,".+w--*vq@QBSÙ73 iQe6=6.~b.tb͍RRˢvj]Dƫ]~\BؾMR)U|զ+ۺU\ƙI~_|n)()`} Bg*pqݮH,.ZM#ƈU{{i-<ʦV F'MVS~.9VFGg 8cKR8ZB'XjCS\=WF S]bg RNy Fnޔ[Mx 'jtuqW#k7;{X1\j`7䏶=VkǴF$`4Ʉk Ql Cnis2oЇpwhX{Y6 d'30!M7??%}ҽr&Ͱ>ɐ3~;}$e5ZAaP^6s-Li:_UgqRՓѡbW u ijhnBY%EѸ -_M[l_p^C+QґBLYl%R> tK/pn0 f8}{7 %Q\U)&)urn2hN2`#Lg#LwiMLfsEKdֱcoټ w./Nb+-ǛO2`,4rK EsvPi񰵸[VhW{\Ȳ9ⵯӁZNǿsi= cXIL(d'AC>0 }[]TH;U!J(܏ ϋPzYp!]Xe|I̙%T;Z(eH 'SU'Mbτ=/؆Wx&pړ#܉!@DpXYV#AXVoEI ^]kozpÿ}a endstream endobj 1121 0 obj << /Length 1264 /Filter /FlateDecode >> stream xڭWKoFWH$@I)ZHukzX+-E|$"i*°E/=|›~&#,(fKiq>a/`2|{ NL%lSSb{νnR8aGEC˦6oXIt뽎BFBli;:#荑d)J!^n.&(̅>}gCrr\IpE.?\б@.Ra} cLP$v(!sar!yԫ.Y i hړ2DD' r䷩u}N1U9V59dtY@<;c= A' :+&e(WeA#U z.vo\=C&.#.EG.pVFs ~ng;C b !λDM-n`ƢjSzk;,(.6#9 (JZs;ۊ@FOusCweU-ܵ}2LFr2=w_ q3/Ρ HQ -cۘc@f_nbt]iLյ<KS67˨o]xi)nK'cl^1pz]eR:ݡ8]̘̘܁I^96 ɯ-z]3aHm3<sҽ?t;k8G>5 G/*SF! H!dvki!60ZLHgK!&y~ZELڦΚ4P{JsE5"־7VJm19yMQ9nӏmW7擜Ì/5>J.Vz啌o 'aaOEٝ+ &Pa1Alw\w8 ߻Suk %tiι㺜.6\lJ? EUk5eIs1+/i}Ba@^0T>ǀ`MLєA+jQ̴߫.+M=˰@.>tô|~<%!&Yt)xsfWMVWF[-AOX% reJrJc0!ʮ_.3o3r0Ҁdmʹo!/.Pi1xpZb endstream endobj 1124 0 obj << /Length 1604 /Filter /FlateDecode >> stream xڽXYo6~ϯ0$Wk>tMX,[Eru$ͿCR_Zp8I]t4H.PÇQ|x!w4 yq)yޏ}ba1ojQt\aG~=oK4Hr/ ?pͣ=<cFM Y @_n0!AP_<<˗;$4oe o0jQHaaE{BK4H-؇ (cQklE_Mz!?xY[계9/d$2T*'`_i#?C_k$P2X">me jN1UJrSS6yx2^ Ll5xƠN5KI@O\[4C֥-IƬ_&𯑂6 >襢8O އ;F~!.E6!JeXj5r1 $rmp "ښmN`yun,bPHYSv0S5hvuMzO|,XʳՙIJ6[ɻW*FZ(U%=׮k+(s$gK`UOUՅdIױ.4mc_D[6S^j,H7x>ꊞש8bXf-κ?ʃhJctJYu5@HTY%mN) `%@w"DmUFB6e-]D a~ꦾW1HLe`yx2FSCIPL:l@ *xB $/J q3T015)]iBh!J0e<3j4|3Wj Ь jJGg# C[.0Sir9KDϵ<N5JÓGhFr.f$X ,3{dj\t甤OhFLlh"tE$<k!vﺇӨe,DQwO, :Uzܴe8?]1]O!!&4Т/Bfڞ=D\'}^<Í,Wb87ū+YN,)!C {%^צ9jYϪy;Qg}Q%͍aS f9ݫU]WH:OFDsѸ0eɣxS,g2M20D٥#!Alm[ {Y cNCm-Uj&y+O>\ϟȒ.EuUG@lۋᢢa m5$&נj^xCc I6Ԣ#Yku1V-Xǿ8/%k)E#F' 7~K,2)_n2n2;b ߀pG6 !,d#fS 2oSn%K 5EIH`'?U; endstream endobj 1127 0 obj << /Length 1791 /Filter /FlateDecode >> stream xڽXY6~_GQ"uC6EӦY%AAKZ,9:v3Rj-Zp8Ml$dIoo͆~o wRnR?q*jo>{Of K_lwBH6^_e]QW#O]ez b?Joz.dROq?P7 6\PDS7/2.;އ{+Ֆ{P2|Q:emC[rV/@fғ43N(ОTs/šQ+j& ,2pzIfcp (ȥ Ԥ ATxD˾9uSMUMԒKUKl}[T7Dkl#,$'ioaFd'B&Bmf9t^Ih62 7F01kǁw`EYIqYKq;,UDP.M) d:*JE iM:&`."2c,/un(qhx%x7ޖ T5)zgu͖^ M M> stream xڍSM0Wp46#Ƕj{[U}xHUU=of޼y  2dȂ겋Ws!.`A~:R,E\lKܖU&؇QHrCe;=HB^T*F<ӂd> stream xڍ]۸=o֊(Q>Kp mEDDlɥ,"%{`5$pgIڔ馬Ms~Ь;l7J𶀸]`<ߨ$%;yor"ἇvϨ뛟Iyǹ~UQe\.m"ӵ@eE}xt'|OamL7ŻJo@EW"w?ˢ잿:u$InJXA$_*zqpD`$\)s维jg8ԵU=񗮉o4.ݦ4bLbįgXsnW۷a4Vq+Ҿ5!|My{4?=k ճGAU(՝,v}F"8/p%R*gN|rO4t{"XKclw;^>:Y `}HI]*+O;0Ӫ!VpbMhxF[4 \كSf:ɀiq;4*6 :@?`~]+ס0KzuH.Uf\Vr5Ladh@d"`hb ɍ3WaAo$N1 ʹ:dh۟W{WEÑNvYda< ׶I 7=멫U#HA)0l|" 2GzwՂG$-Y#Ы_dI.ëqt1l */1'x^\p?s5H̹ݰ=\Β!`ǁiA0yRFU:BS0AFW/*r4j8@* PlpAʺHPbC8<$K <-Dī/yWwtbt& {gNPhu8<@di<$ufct,hfۥZ5HHNX(cQ"Ou,=pM ɭx'@* []зMy mahR]_+rvPy~ibqg|i`wI;d @?A*-._l=O& Xp#ZKmr (Ӝ= ]aX)4^AdzP1U;䯲]zp<1nY '=ّtX" ҥuW֞sAKJ8y+e|L,>1pT. "m7Y62BRB_* %TDWBw-.o*rQRwX|4q Gϐh;rv9ኪ3a\×z s^i]Py> 6 B+s|1b[ i#RFWq8xD{\q@'_RI*͇ yC/ 8L J./:K CۙSZzeןz_4w!}Is0{9p*Kg;Pz hL0Py T\ͫ&W֕Kp(})߇K2*!  >_d\EWe?-^e(@[Ta @eZ/EQDI`u G= ̷ˉ<^Ɉd#5v=EbkIK# |YdKSގ~}~{dπډC*`X$[}gi !R!"s'3 ]fa%@VUsOi>qvI$;H $_ϻaCfz̏7x 5Y7PݯC0˻46ymN^G|j#<!˺(pv6cI.1U#A-Z9|#vv_Q̄8+/?AV2׎(ϼ!gdt{gѬ7}%ٵvd΃t#~ -}y}T1 \%r l -K<"^YՃ(7Y).9/8KI˕) |c^&' !;R=Ɖ׬fZMִ=eBŬM QqFmS!u Ul\ zxwA]qw)Et#%doHu_klJkGJMn5wCd:K)WB>|dꝉkvHTr𜤥,Z-tHe{ѯ[Tʅ97A>"^ W?=vNKro rZ WMDo) D endstream endobj 1139 0 obj << /Length 3225 /Filter /FlateDecode >> stream xڍrܸ_K*̈́7nZ[k)`cò/vm@7h47>7Yx>y?ෟ_n w|x&_7%nn+nEp{?Vfӡ6%1n ",ÿ_{p %aO/roWB>^!L~30%oyǷYB/f ̙ۥ_ nhv ٧9.Oۗ fX3vzf@*"tG3JR1 .Jy̞/3gosoNgYGVCxvyā5ɓjK,@Uz>-xO>!a09 ( хݘkeӨqX~.( ~S[g ~͓ZP %6jų8Y#|!k 6kGN /(յU.UU8x{%`35"8!new[{Mm.-h6ʊ9Ig j*31̾DןTkP szCo쐌$ENgʼgQNU(z+ Y=;x;ጦLdzӞЍ/d @" Z;b4c=b}^fL90Y:c +5o O_şk.HuVu|vdå7_ԃﱝgB`a-b\ Ho col|10bqt4 PJ\n#LҎ%җ/PPB)(\!KClOM½6& B(HWAEW=h V2Jp _eb\ GE! {1X(9vd*jkL? |!0,SH<ѥ w6ƾNEBqꑬIvMʥLGPy;i9 FP ʺ2Ȟ<8g4)/U)H0 {gDN|I._ S|!ul gd%= Mm"̦W=AQ 3|{yHk%(hcZAEW3btjzG@j-9(a wjc?'acC># C# FmKH3dPY^$ T9=wmƒq~Bv8Gqg>Qށ =t%N_a&b R~4˂vؼfR #ߺ"{E!Z j]1Ʋype@2lkQHeǰX8"TBŏ8*h3,;I5SMJQ7#O+6.}ao _ۭ"R<=*LGo60 Du8'd֐}@AnS' 蔘0ʟ$W.qq+`F^3.OP'.G^] smX NZ=XҔ8<*v{T[^eY!zW^k?<I!n@Viiauxŭ1]yƃ\6AAՅmʮUdT6) LP$%XS|kR+|ZI-L5P5.H6gBJ@MSMg)Vr]ѝm\hϲl',8??ۼ}K= [^RYKSu)_%JUDt%`ЂYXLZߋ"HI_@N>o e]nsVwէK%8VUg̖KpD,$,hwvHv] ASoԮ,OO<M fNp8&V_<|gwF|ǾkK9D\F#`ђ+LI f"#um2׵QPH&# (u-pBKqjH'pѰ^-Y#$DFYábNq)!OKQ=9EBBNeݚ= j<6` |!3 4_n(_*.Z9RVn6Ot Z!8 uS .еh(KG,#/V6'JÂ*r>1(5Skr 1s'e$˓;[vćnD vN reF)Ns~'`MV8ѤvxxW@\JSVj:*ݚІ$[%j~i藸cB&SdY+C i r X)ƭL Pf`9!u|+Vm΋-Y2P29xi,1  PJ\ խ]TcՂBoص0y U[$5eEQ)HjW;(BV_^HH2-K0O-6C0 p9% 8X?\gRGxC^Jxb}ov s !T l٫*#Z(q^jXd%6*J2#W.%N"VY_R Boa g%?4PJ[՘Uy <4m 2jwkSb߫ *0ډ뼌G$I^0?#wXj̵`LC >VjTö uBZÕ10"ĥ6! Ѯq†AlT? Uю'^z endstream endobj 1143 0 obj << /Length 3152 /Filter /FlateDecode >> stream xڍْ}b*/˩QxMrv<`(HB-gJIJ@Jb%wUzWٮΪ{tg=2ypQDMtC]30v!&}6-veRl7O wl?e}&+ؙi2C?Z+-JsG9q+dnG/.eK; 2=( ^[Zp|)3Ati ;yqݻ-Q=nrh߉tzje䂗0 uYӬf oPfdNt0/f&ƕI9v|:A05`WRKyVj}sLx'2_۬|'EONlfmj%i!y7\5D2m3D8oe90SCD;bΚf,[j"+L9s0#+{D9x1;.1EQ0/q5Kwx.E${VC8С,̨}5ta \EJβPA2 S򕷳=q43P2r9hwg0b-},c7r]g.&G/q$ƌA7_9f&̵/7Yl| 7x&rN@A9"譈Y0he Y÷"VtĖlR IL!L73poG}S%e߱Y0ΧaQlUpyGMg2ocJwvf eGUW;$b'ӨQtZM(DHnU k`%dqi-!Sr>a6XTI"k߱Vf B{.ݱِ4)E, ǃq%sq9A*'BɆa2y4hK NhQ[(>3Tnjڴ)9:+;0\P¸B?k4$tCeæhpۓ-+%̡PUܣ*IU}%>RX(mC$kAc sc=6f1 S BFԮ-_x-vErdK57nB mfR>LML=w1R3 5؜2 {1Xפ)k~]fpIfXM UF+ WG CŶ)_̼Z{μ$rO>0t1W 2y˽ֺ|ct1`4'X 02Le+TG6kEQ4l3ty/%.eFl%*.Yai@Hgz1Gߌ§[p Ć'io(_տ%Y>Yҡ  i\WU{SC?& kZ)Yne♊?2 >,^ NGޚ۲0MZ^fHv"1ȁjtf8 ߌx5L #yIʼnw"|xhWH%J_b endstream endobj 1147 0 obj << /Length 3187 /Filter /FlateDecode >> stream xZK50#6aAGbwӫ:%GM"cU4S *}TgS{{^w`_߿7Eħ&n_W֑:p̲,KGA[37-3ISQU~9P"!B'"-OqN$*Q]gO$gh7i4*Yy7N~ /vvn:@QS 1NI+(,"e56rENcqY"jx Y%bfe/VݘRf)aV6ϋp 0a#\(\۹L" ó^nfc+o彭%49osJSxow+qJ@ŐGb*kQ!nYxd6J3tD~\3pZ)"}5 V(_!AM3(hO8q%D| P*^V:HB|U~6 q#aaE:\9[hoR+{!uCG䚈:8lc?ߴ 7n-- d 8GtgeGb  ;N$Ag_p|2l J`>-j7.~ŝ`JwWB|QFfdp9j[r+ŽezW8e_}V4BO2 ݩ4_8PpH x l 2nFo$/Wap̫&3)%]l^x;p,da,khd$iA&R;TFYF r@"SYYJzVp r+ncrҔ}SKFNQE5Pf2| H ߉o`kkIɦ HxZP<t#P,%qGnVQ4r 5v$Oh!LKG h -쾤MSiu y:%.bUq*@sƉ<$NBrZ!xv<هqlNgr{c8?iV͖ۭF|\6k xSN;6xt,_HF.z/Cp߁#LwV) 208HDlŤL1mg93ϜHV0۰Z3L`(]RM"0&| F=fO0َV< @y1 ɗx\ e/A.W6{' 7h'4h/XR$l.9}Е7=~/G&RC믩:XmA&M`j5X{&E`PkT&x-A >毵-S<?5ʶ 8uQn~Y#w !!!Zd4ͩ!M6_S\$4E& F =H˹O&σaGVh`m9u୲_۷|wpiVrlp\yRb L0-RfKH+nD5'LwUe+'WF/%iu}mB rY!=YVpY؁y!ʿGer~:A;Rb' yv{u:$wY&g7\}2Ie#qfbћG 0=L.."@Y7oMXڨoJ(aq}i4qk!!pul&v-/|s4໋(HӞ? Hg(GdvCY'2]Ռ&EdPm/̸$HjTY8-_L/iX<`2څGvr~]Dwn{yI;y\^H:/Ce НkO8qKGY5:T-᷹gtUF:uCoH̋ !LaPTcyD.ܓ0F^~wqu ֺ9,0_?<xQ|KMI?P| @]Q[5]ԏH Cto}'s4 D3u?IwGÁ $.]&oB;bs('n/ ;\(mwcďE㴇CwW2!{?Xs;}$~\TL ~C +7?njR♟%JujMֿΤa'Xdmq~߇ 6Jo RRTWEEQSA> stream xڍn>_!Dwv;'9ؓXF9Ȣ"6)#)_r zjyRnBn'}Rܔw!A |.;@[`?fM!y[=T7 ۻxضrwIOG|aq%J6E/Ӆ8ei;oCˁ|f)Q=[qykR3(\[v . k~ <:^hƵOۻ,;' ^v8Z9X֟}Gr '.JvQ1e8Kglз<1I29 :3ނ^$=vg_őC!L(O%Y_ϬO100IK~gcriӏ ['E08b#Y_:Ӑ:@@[AQ]{7_!Y܏*fE/o,;8ѵ(4J0JK:OBkpJk%BEvŞѨ?Qgk4t|D\xƾ~~e cɚl'܆7+땶UѻM_@׌$x&g` a'n rXM\]0[h58PlrZ៕_UpMJХOvh^3SH8,7UM'__k3B(&Ws:7RE6%y9;) mϨt_ /fa U"2@ԣR?oFn64q t[NA uLk3OJLwR]Ie+DSFEOYm#\H;.2/ƄŜwϹE\|6k*~5!T2M5X-:-@(mw_췋yܧ9 , 8*0,A강=ⵛL@kZ@/I^BhRi.صb5*;~'Pw:+kZ5ɯkDk(/ 0A&%ZD.Np[y6]vdcdxJC&9b׉l"Tn! 7@ck(eOI* S"uu|h8E 1r,UXE5%85|[9a5\2 `5污쬐tmZ!Wb i# )_g0i2TU &"<ʑsN <-uzeNZoɦZilφ\3({No[LEU vĸ#*kJ[`5rS?`$[KCZ^WM( c!歽|rاejt9L}dM'Nٳ 灛4C%GNSRKJ4qڈZ`PxEG[MԣX+8 $r ٓ7'Ԯ{- &\z fڶp/ҍd."TXlwۢǾsSh_V;A`ɐ6 RqM|#PC =}?`0!8l*ĔЦ*Q4ZF(IIGx*҉Sv &Ki=2'HDf= mHZ^~[5s22bkuV G(J#M'<@`8'RP&=7mSI8x|'Ζ };7i_7eϱ# GwȪ:ϕ#A,ky JkB#|<vda6=Aӫh̠g2ǖh>|f<Ǐ;|OK!*$v}wVsfͰBAÄ8McU(鱋7x ȃ2Rcy>$kLZ˳\qŦ?N;'.>Dk< o{s/)-B.؃_  O7^~' `Od띯AC>M_cyJ3ܯ7ĹOzCW?7b7%Bɟ? o'B#]- endstream endobj 1155 0 obj << /Length 2970 /Filter /FlateDecode >> stream xڍَ}b' X)l>Mu0CCi"&9Շ$Nb,0쪮Ҫ &hbCw}}O?(.ӇT?dtJz:>{xlwy1Ey?Of0Nqymmgd.Tվ*x{OlrJϪ6?>_᎙ڜř [xg;<5;A8MYvҳqVlXKG~TițUS^U2n{MLKs/3v?ofL3z '[ x3O3jne򖻧|b.!NķS;-[>̾gX|I'd5.{vxc'31 AoQ=) {SyMہZeU~:hP'hSN fz' Z= x m&nSJɸW&K|b_5N†䤮p@v҉}b89pS,ȤQubNM^pj`2nv[U'3*$F ЗʘaMt % _l0cgXxfH7i9_fG~7b 2Q^ԋA4 <{7%,&ƴSzcD-pQ\ĤQYh}B/iĠ hY/ ~$EQ`eAn!XIY{SL)ƔtXȅC!7^Ն45SCBK8+ˣ %ށu#OPă_dsHVΌ";U,W7g i2A"s^,g_;i̧+_k}10 : ^ՊhۂʨZOH(\nȷW8B|&7H*+ܨv8HZG2-IǷx?ؤvB8V]A78hIKkL)+-Q ̭_YDI1֊Eqj0n%i$ j&vP!CEL q ^(FZ!lppĥJ:#H5/嵌,xgQ0@*i4=cՎ} i}$GQdB6[*=Ɔ2T:JlǞ ߃'Y9f$hq e.1PGگ%|>q.7u10f;:y n?FgRD4%`]q*^]w]ɂ]dy˸՚@yʼnW­U%bHj}c=_DrDrz!-Kia)/uN7{-ܴϖtmXs@ӯd"[|KN\&NCv7n7v!͟08X:_8jD?ɛ쪏%:p/6夞hk`  I~D~8 9iBV^5F(NąxU'""T1:3n+Ī=+ʁ9wM*L]`ۑ ?_E,Uxh΀O09' D]7$GvȖ+j/K^_4al<@rs]Y endstream endobj 1160 0 obj << /Length 3365 /Filter /FlateDecode >> stream xڍr#_%*QCIlW(TD$󠁙_~4@kvӮj݇|ǍP7 ?ۺ+}/O)ݿæe?/w6T-C^Z{`zo@o?/yVo}GxR[}kŧчvgqܠ|?pޏ~2{Ǒ?IPwy[^}@ Lmv[o&"7048sd+MvgEtOB&P-Q >HɌO6Nnl9z*j>-Y+؅=/ܗ2upw80ztўxsuU(Nj( ~zyusuS)"hpɪ*>*uzϡ++ 1y zkkudvܑWFKlW;^"_hSc"B{8e?\=\;Շػ1s5 8DY2HȔuoHD5x9<WY웥P:ޛ3oo4((: g{"^oL;Gtv?wFbTUVl :RB-a,%@R#& ooauffQ|IU\=Xx[e{2yHaۊlxV<|Kv+j G쌌23] +0xL#CF9\9ޓ=X7ܖrGF!Tٲeభ,SXV;}vz{+TvmÈft06+Ȟu}B? .Q 092Cr]Z¼D:wBI! J;M2H/qq65'`OkÔ.Tّa@SpC<21ozuZĺlj|6Xv⸏2,gt-_ŀ>*ûYdm8\舶f8l:p7e\ Rd| hPd vBch!tN&Ptp',pHdc|ĝYD" [_종N8s^?q |shNa *%lv t }$u^%w>_{!KW8 #S|A/3|T8!`7&T5R!`Ur'"KX}qaRP4T 8o$Ƃ%פP6 eff(1Jts /.b e;pgk:[XĐAeS:HŌpiX8&OɯF2>Ij`c/ԟ)5 idɮb 7ѭRD`:(Y{)‰k[0("ޖ54IDiһ.JfϙR*L a\WP,0/5~&/A* endstream endobj 1164 0 obj << /Length 3229 /Filter /FlateDecode >> stream xڍZs6_K7{sZ%xl( 8HH_Ai2],~ $8_pgY]QvVOgxx&Kt$߮.Ij/Uڜۻ>/Sͦz9Ȼ^5J5su]ܾJt r?Y섒0JgoEt:+?e08EsXLfzYu9MՕWMѷ<^M˶Om{iz؈ߝ#~'lѺ'tkp/Jgt.І` xZWhEj2fF%-8FmD1h5msyψѻo+=jӎM+wZ0HIg?ˢ_YIN 3f47TH ^_QuG^;p׾@!!f_W :$dg S'+ @3Q?)Ħe"[fYJZ/2)XLUz3̊-tr't*h=tU:F!vCWRvKC=XDX{AF;&Y_ȔHe0mNAcNds։P_~sƢ쫯5dьAM 2#i6µ SEh^|'j)LGSDstVJPӪ=9 Ö̃-`5j=  0,bG 1I̛dh g? ̭r+ ~iTY Tx+ћp ǃL)ȮqCxʏG@h[ J M}ιILd "`BW-ܲX±Nl D;9$2n`PCg_b¾ID9d+8l'$4@HVh t4q*G.F$&"gOf5M `N3% }?#Wpfw-L5py`N9ܺA͵@!fzA"WҦ+%͂ӅX AI"g8g⪺xE+iU,qi?DF(Z:"EF3wJ\9[ɞ٭9_0*`r[0Ą] T% . iSV. /;p:lWY620Q( D$#Gu 9FHu-V/{;Uj u_4u2-TK^=I?x}'.pecS\)K fֵ*̘[^ 7Ù5ҁ.ro {̏ p%\`7id.٤*_˷Z8h)?{ڦa>1%ƩzL ($鷄[2$4ǡ 1t|N%ŏZm5c`JVZʌo<,vdcC;Ai#t72w p-@kӓeaaw0`QB&lq8BVaJdQLc1=r\Nz]kF龜eĀu &8:֐i;xIb(0+nAIċO'}b vf ۷"UO80\a`ibMCvN)k͈MX" u/# ^]?TK6*nrvZGN}5^SNMÁ€$*r,0cȶ1]vBx@*JNGQz`YvxҤTҘx}@y|R!Q,EO4f+ Cvo2b,AAz/G5o6Ādwa 6k%f=uWf(hY fʨv/QpFʠaB;Wl.L xTG_,}d1}|AD$KdN O(4tzҽn+oCEj ,7\)FTusU[ LM/[VBd8'@.(`Ǔܯ `.^ \8BTq$.mq! Epm:ީ(\8Z'.ҹ)k2PXÅ~bY"q"9>1 dSoQp֬^^GpܟC-</pwňfF{M-nrxfO(Ƥ8 l \7>)ڰ/=}\abDl|(_Z}2L=8265bFIs ҉&缲aY 5|f/'n%a" qFnvdC0MMԊ1L3L=ȏu˘4+*.FS8Ω fzff{b rO ?Rȫ/HS 7!m~8snqaJ<Dh; 3iS1t|;+ *ær^r[:@ Uʐ?^n$h9+xu?uz'YmImuIz(IyIMTL9Ai|hJ9c&AҒ킀a-"F &pnf[kx8`5Ef!U BczъV/; f}#][o5_JwaHr%S2ϹKt;a90]0&b9&8LfKDoUW L=. on~_>,#ӟ΃ V1j|?y?]}n%ˇ78X-81T7^]2&銻ȿ.W|ąͣ||N|)?8 endstream endobj 1169 0 obj << /Length 2820 /Filter /FlateDecode >> stream xڵY[oH~?"'#%p;DIC!hghF '~YVꪯƺjßuճz};[7Kn@&yv{\YmsXWM]b}c߷n쾡uu81χ xPʣ[+ X^[.[Tuqh.  ~tve'Gl >&ceAt|; "!签k V1'g]l$79xqc9ձج`R}r!~ 3_l`K˲l;N̚ݳp*y/V#y7!UE"4 ^r QYt&ȱרMtZ7DɣpA<'>kwx(L)8$o "i ez 3yD"]dOn6Xs1g2P~_LD3{4DZW'IΖb1_zZfwwcP) wтR j>d>Fp*WfpxH 7SfAvͦ&aZ.l5mqMLĻ8KYGa8z8|b")ۇg!N(x/!=q  '" oW X.3)с0(贿X!`?p=?pe(_;S?|-`BkAt#HGN', eH$Rƒ,8pw'c2` I7<*2 ^N Oʒţ0ܶ%X^/tye=Hp[Z7| }bUY2,",&%+hWޱ5{@xVYw`g&VŹ*t\}X-Xe,.Q3}ܚ]<$v7Y!U 44wQp>ȒCX>6St.(I?b!|AE,WYr[8y{0PqHU,gT^W3]:>Jc7YebRh]m2b ln嚎۵u m-I4!C=n/ԑr,s0H=f-\A2[qŒ50Oυ_ 9ʣ]w9i L0QxVX*#GJrq:'(:S Orq3d=<x3|Et*}=_7e'ɸ@oq !3Z6VhrIN۠gM|&M٦d6mXH9yod$WXdQ)$Z@Ь4tM-O1c x_6'8 ɒ$vE@ExEL:I+Rӱц$vuV(k N$pp:tBY_9ͧ(R]$Jo_tmu=m]ݢbBK:&w>F15߷d/,ĩ:aXp zźVlHCPB07gҵpw7ݮe>9T#! !ȊSD-ՆIb H;sBLvv*S\emȶa=-TQ~i6&:[Ǿ}#:nlۖ&EC&#RTG@U4B1Cf~I{r.q8?@:XXUtϓ45M7O)0"N*q پ*B8ƉǛ= .ڦW߁Q^xojՐG}K>G׈>y}֏K|$$ӆAѕGW NTC6ws%kxSx_uꋁ,hh\QXkIŽ~!N|W}wD?lu wj{|Q[>ZI *!/D<6H~|ay؊қ+ /f'B:~S%$Z f;nU'W%"~@2[+.]jCÓ2/=z6,ǩϣf驇kJ_c)pzf}!p endstream endobj 1176 0 obj << /Length 1321 /Filter /FlateDecode >> stream xڕVmo8 _Kv,{[Cz\[Iٖ!+GnH/b3~l4 ,LgesZh|Ŭ Dny3{r55f;]7wm%~0 ۏȹ-WEMܧ{-JZ?=,O}' ,؋7KA,$}/XnD?GuSrR67eo+hQq]ښѻ{?gF vRJ7DmEZ@WJZ;B@lۊ[ %W݇[ Α0`O3 ekQ99d-up-JL'd ` p25̢K pɍ0Hr+|MvMt~#B>H"(Ma/:HNB[FW(ݓ\  $!bPc%FpOp-F$m1zs7eVdQW^l\? ln-u4$ěBxḰ$RFy}.s^yH!\6c߭!0HnˠP㍅QA^ɭ&%QCAutBL ɢ%\.xQseΛbu$OĀRK+0'Q} oO1EK^XCc!+eg̱mu!Bqar3.%Bq x <݉Nsji_X(Il endstream endobj 1291 0 obj << /Length 5046 /Filter /FlateDecode >> stream x]w۸~_GkM޷n&g${AZYr)9HRgko4 tVL.9)ܽ(OY?|Aq p䫏/~3Z/3IQ\>.f9+>ޒdHa{%QMbۯ)ozeB1{EA2v&\uǾcTJA6p!U/)G-VRX7ZG0IKb0K"/) [IHӒ< ]mZ lg>](r`oG/): [e ɀ]&J*rtɧ?g9JH 8K*f7o~hZ؛MZ) Kňs1N $(w"Ȗ=&I!Dzi=婸wKc0K"I^Ѡ4|Xsl1]P t |I;l6Li^n'73R=$q|80/ր/)G  q>/5rjV-/gs \*(%%dDPuj}O>xȁ@oK dKDϫ]3n˛ NWav=|S^PJGRa-=ޚ4=[1[|anȻ#Zj5OPw1d=ni\7)@|IQ_ODN~'aL'.: :Q&%E'd^_]VmSqW`W$ %Ezz/fD)W /w^ͷX^?:!׋v-TVu&u&ӕ,Еc&pSjr}۱6w\䂂TMe`#(:}I9 (OWE_&^[z._.M%:I RG6p cP3tQ,%EBd[]Sn6k-OH W k`` w `/) [P2zyhn‹ c'<$'З#Ȗ˗ٹ:݋yck[ta,eB>91Wu1/1 #?RQ DDbg&뛥];3QM.gS B ]I`5li5B+q@9= X/Q=ݵc.>p! 8#xSS}ok_sIʒ̛_>>0#N5:}IR IVDHא\6|n8''g7Y&p"e2#'<$%e^P kH}h:/O? ޘ(crbRt:i?fiէ(dEA8}/`O-S#OL"A3Ew~ܕ UwI$;? ̘0 eApGǑ'& uYwe=bt%  M"APG\ qGv*58$_熠/cL@,N B_Gm Jµ%e-Uz@ޤFI`#Ȟ`IMy~wp+DӭG_:: Iu_RA ?c[iE/_\"Qm_RAh k-H;`sJ'N> B>%'VDxS*^~k+uz(*\<2ISx |IQ9i:'Y|mW7{E{qkkȂT\͸2^Oߗ? z$SufQ ,WD%\#r02 M/=K"n$ڿ]vfswgzy3o׽P #(.? |A%J*"^n[7AOQXpO</%U_j_JyWa?s 1˾C1A@W(5E_KS7ɝia*UF\⏼@_RDA"ҶE'S^7Y`G?# H>@_RtAP<ۥ|RB/. %E`̸0ۧ MͨdJүܗnji^nmC/`|V}D2wL|R pP>7 xs:ON˨G,!Д6@`Kcnzdg 􏽿䃝/.%(= %EJd/%H%)5Wm^Dr [V+ʈSn_KV+QV+A/+c.tCbK#/ jݹ:J[6uÄg)_\ |"7poiF3Ίcj> stream xڽZMoW9; 1HCR$0\ U/;gmrwVv^׫nΩrN=TАṒJz`@A04ff J%>BO-4Хي:ԁ@d0DtXGhQT>"\l!Vm;Fk`k,ƺ^O9eJ Zu@˽@<r%f d#n5/L 4S.m~ADŬW(06j?pMS"40# $Y `)֕nN\EQńRv@&s A$]A# 0ۮ*6hAthPqGKQXϲZ:j[PsKA4x2IТG:B:svz13)bj=ȋÑjZNArƓ}ӧOq>^^_?<(-5^#:3T9:u{dRF{z"*0K)ϋFF`)J7lCpbspy>\]> stream x]o6~_G8OIKC(npw,`)H˙hB&3C%JqVVU<}xQ?ޝu ]چ?n^g`uQPoיRr?}fZDUB}*qʈVδZZuo?(׬`X\K?usq)<_/nW,0_\wѿ}&^bq[2mNJֽ@?@@g)H~u#Up${E!)2)%j"@Ȏ"v9ȡ˵9< t(O.)I8I]RHB ;hc7G:fگb'̚350}/u@2(֑E0`Usgמfa`kF#'@}8}'-%>2.a9H4]3Glt.)!c+ 1&r&8{Toe{.З5hlSG\ReҥD#@vPLT"@ڰ~2୛ϛABb@d16kwmaejLe 93rX@ ؑLPmIB=ū1K1c ƒXuI9zʶd*g8g$2]R8C ;—fwzjX/s 3g,bxcH% K 1dGb\yfl?'/UΤ0x;3d3:5QK CdQóCvNɧ"Pn܄s q*v=?xpx\nyUwuUQ)}/t \=RH:򾳡39mo_.0<@?7,.)"a僌0SHqR,? >UIa옠5db,q{ۼn|}w؃I]s|Oshg|uIq.윫Ɗ돫nU+.zzZEq2xGA hTI! nX&/H9x浙+h.aRTUJ8)V@Qv,ds`yfwx>8[M '9v |z&=3-M}Oc(X-Mo'i1L=+*) =+L B>H1y?M᳃ wNXK(@+pܔs>-O} 9Ȃok נY%Xr xn|fEu'uɴAͧ tb m~* +M SK\uCwR14.Y*q1 ; _L(=|ߝc 66|ߘ DN1@^ Ƌ$X 2|mXGgƵNoL"cwӪN1%UqV"q1 ; 2sz ZW҆c3k9 fj6И DyҼOg]c PYto`v&~t|]lvt u' M}Kcq:uM m8vÛ`'N&X8 >SϑгpJ 9@S2:i}o}S``3 tD3K '33/>\nH)Vvj~*Jo| p@qB9E&!YވW[c+_,o ,\˷?G.U@oUw w רC.)!Cfex8Ic|5%sq؇O(D'+=zH5k1FY/ go1 B]R5Apܹ,=#8^eVU9#ˈ;s^r,9s@]8F!CӖӖ[om aa556Y})྆&SK kcBhVDŽܶe~7DYI|KďAJa+,d'}qadbo?`^ܼHg`g8|=@qiG]l|zn0JnJ#G./$hLODel12 Fcy".g!TiU _M4B( t 9} Re C7}D FR1HW4#w Ev>aնK#f@ 2B]B!T% 0jN92400o ' %0r LiXPa~n}sot͓A|.'P6Ӕၪ|եnϧ@SpX>8[>]R@ >h^pثc?4lw@u@]v$D$5BT 7!DwFȮ#}X CXPrGmN*LPo(0tA*LYKJ'"DL# QPe BS6C'"D\#QTe r, PF?IR endstream endobj 1294 0 obj << /Type /ObjStm /N 100 /First 1005 /Length 2226 /Filter /FlateDecode >> stream xڵ]ϯerQ>$Y؍qn0k_dc|xarNaVTw/4$ fG%JV*TUP%U^ҽPxv\%٘*kD^4j(-$\њeҢ^̪0'j*]K2lja>h $0Sy*SPf"5ּ/©1Փĥx[襗, fH[hI܊PR'o5Wt\z $dS MR’Z$J0b$i-$-e8fi%oQS M*2:֜a=iéc{eJdĮj27 %NΓg}$&1M%k}i-Y:ic}FS;Vc Wh]R3ڡ5t{6'vg[ M6bJzoFK}鷞 rN3{(~arv*ҧ_}9X{i-/,2|9l^݅ mqI}qšܟLZLMbǨ^=ߏݷLӿN?<KPLJӏ_o-$aafO88}^Jw:w= L0k)]t9c֢y44SNf-<|'5G`Ŕ;Z 0;6+s D7`ٷ }4ˆMu6V蘑 3fn1\c|/RRM;q22+IJz &>6Ee6Zdmmyt>ෘ}a~Wf n>ෘ{`Fb~|ȷԲS fD-&chf[ud`L}yۂ,pzci C2׉;ٰBeqgU"IT2L!Ҳm*VG#CO_ Z( =+ya3N`{IJz1wb6I2.3݅9ufil[bu ;=L,QWL>X&;f om6xfrmm'rvΝ&R{۔ɆLY޵x3c{`rziCLF^ͼBzl%ZYqC I20nYNCx-tIYLfu̬SCg5ƒԆt^I3υ,H,wZ)DFVf |r-<组̰s$8,yq[bN冝;1tǡ/fN@M":}:\tOO~/%Gzzo^&/aT:}&?>~l~O<>|o_>?N>˧;b:cx}=ן+K ޭ靄KE_ #ꌨ3ΘsE( 5 FТУ5k(P\Cr 5k(s(s(s(s(s(s(s(s(s(s(K(K(K(K(K(K(K(K(K(K(k(k(k(k(k(k(k(k(k(k([([([([([([([([([([({t#`厸q{Fb;BGiG"M r'r>#HE2y}{c g(9fx Z,zqu6{7#zq~|+3UG䒁TéUb[z}de[p M܂Oǎ3-̼܂o2u[ybzxF^7;43Ã6J;1izpԃ"Й(ga^y+fFvD Lj e 7^r;1[˺Lc^i\VVݎebК?>R H" mDŽs8pF61̽f7TdJY9yN\ /7{U  37K[څ+#u`/ )A2?/ǂ7 endstream endobj 1394 0 obj << /Length1 1558 /Length2 7763 /Length3 0 /Length 8801 /Filter /FlateDecode >> 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 1396 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 1398 0 obj << /Length1 2708 /Length2 23828 /Length3 0 /Length 25338 /Filter /FlateDecode >> 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 1400 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 1402 0 obj << /Length1 2231 /Length2 17884 /Length3 0 /Length 19207 /Filter /FlateDecode >> stream xڌPҀ NppwwwX !@p]-\>}LEI(mvfbcfH(`cr0#QQimYG::Аp8I8)*ځ.667??++?vI s"3@ tBwwYZ9'֌9@23MoLlvf rvgaquue6ubscj@'g9௔J&ƌDа9Kngj-؀̀`79.lKÿ.m#oc33;[{;l ݜ&`MlM>lLL޺ @ZL`s2s;;1;lʑ/7oeKNHO4{;˿l Yab rpI[m Ϛ% :nfV,p-dk-oO{;{[@og Od 0ZH--or豾~uG̢,/%#+sx2qعXllb>a+kouϖ?h= tdֹ@Fgb5{6ym#iR؂lֹ.oSh6 *A.W*l6 b`˷fc2I4W9Yiq*vN.+͘%֙o#afv;7߈ 6@{ s~3 sD\,b-,"x,"_aH!v[?AEP/EPCo[?AECo>uK|o2O9YQyےz37cFoW ? E~o*V?-/[baҰFڿux{-Yo\_G-dӟjE?zSwz*EaqroY9&.|mf`oo5S7O@q5sqt|{Vf?; ͐?W2펳s\_#hH|S|(X>+ak6.WZ?R};OFIL#.t9斸gjCע3txs2͕wVg4(PQ(Pb5b3rN' i\e4CT{CnBI NS,u{u ,K,zש|46me;qgw8-js0ʷuZ#E?^94A{q #~ bo^2>=.X2BT¶#X1\utPvۄ)c  QJQ18("-dȺG5s u](L9)VR8P7T̾6)D;>Piu+d'ï?Z :.>=jMn.t%?G4g-Obyh=ywe{xTZm8"TM}9E[Qx9խm}_ŦFcʠE+k`փɚ;Voe#L,d5nw9BFVWQ4/ٜ?gxV_GxTyVHG>;ddܮжtqz2b3XfR_Ԭ:KaAnѮ!ڦƽC1{[篫­kD|O1_]iiAJαH6p;~ٻj>YخȢ KF b˿K #B؄؟9 ;tܹMD4B _syspc4"'#ʘ&cyϜpoD" b\^> 85I̽!? %,*a,$hgFFB+x0Dtf@ isYsIiY*ЅG_WNQ&?Pֹ~J4u h0,.,Qu˅C-("RA^^$b!̯鯐N,,Clj킠%go{vz;Kkv)˦c4ZIC(뜜LMf2Ŷ< d=ηR )ތ:%$?4GQ<B^dsզ߈\dZP߷|pׯ3T_6|6Q ?b؟=@,d硹؎|%*72] 9>p0 حlIY!;âB[6tx2_GHQ4UZUm҇C ǠS#₶3uXfX<j_jP7[D?-=yUKޠNk 3OO:b>*o~ 'n׺''HI''sEH17Z;3xT}/X} ]0NMtUS拋[hhc]+:nܞ%f ͔omߤ5gӔNI92$<ֻg=;DGpvC+<shݓ5)ciSNץLJ&SJ=lIUWh\(ROEQ~E[-31{H\8up>e[(J~م2@H :Q>^ZVdM3!H~NlYQ3tG֯%U=K(oB)rB%Ge߁XLO?IpA0LH-hutQtnl(qR!['b?FΥ,y8pZ/$wn1N2ֶ'q q̳_@!*A5p<2mw.:;ƫtZ%Xm?3^!GEC-oBs.}JO\g]KdTB6QQn0۲~;=7EyRzguQD}Mh;R*ix JDQMxi\[U&" i.Cvq,5Sq%pB 26Y?4³MKZʽCV3H<,ԍ6.&4mzkSTH_>>nx֣ڸmF_h8xm K,H ZGr?T$!McW#Ot5PMT-Y̵P\3 {r|}vlAt%y§Vlj}΀nJL=RtM/^ `jf8 '{ގ`cސ9Dv_UjR97͊Gt3+x% U'UA6LG̞ KV؉ ˌ4T|G>_nzt{7U\GUJ`pė-pq]~Ed 1*<0)%=,O4'D/E\xɻ(`8Gx[.!ݤ? Y[:Y eQ[>>J'ca KXkc._wW<-"r@Z/w@H!![LhZp!M|Ϝմ:gFHJcЏ, &03/"}lAw;~eqNN؃UQfwV3&YnP]"DӬ e$I56T6kWf".;  H?ը~ag φ3 Uh$J[wrZOVo|ʵNVYq`F3\feщu>, b)Ef_^%%1 ̵}q6:\õ,|~vqvk\-)0GQdM*o9h~2q ٠Gy-hnl='ln%Ta#sC.դ*/Y8=R_e?8/ݗBLR Tb8JI)UYS~?3RQ6P1%z`(CZc1wS\w,/9D>Y6Sht 4]qJH/EK9g' MfjH+*4WA]fvf'MɣLɂ x1|wx;M"< #"C+aH0j+m;{tEYt&k""'ӽYl`l8U ͈|:ZOAX. 87>ć& Lڊ l8)ខvVA缢Or<X?^Cw+ˋ6d -+a \^' bkb5CS$}n2>2#()SPc/ֹ Oi$lEs=f+j姇S6Օ.fve^Jr͍\HS⡳:zL1ұb)[*9m?[s2pDj'[W3Hsf&yPI˪;'糔[1EAj4$v2`R#a4= ݸv:ݧQF9e*e9=_Ub>|+݇yW`aPԸ{ v,<~k;qvH dW0j^y۾Y-)= ĨV\:cPaՎOE7\d!Ay愓XcݹD? L֝l7e%gL 6T D'LGkx!~s9L½IN;vͣ`oQ4+R Z 1'? ֶ0d|>PcAП {ݿ\I_kSjV3,z5jK1CfxJL w).@tf~A󔗮䢯0S4z{e-?+-1ZX|lӵӠIM)8o.剙nbM?A]lWsexD2'PLw_Bd8;?"wýn88V\,RoIƧz9 }0y֪%,W G"ЏO-AB[ tǐXVfc(13 w G hURW5g\yꚚLԝ+I)81_j-'6-~/qDlK>? +c)\<4hS:lYY!Coj' UJaTŘȮ*4*}Yz)(†m~k*SY1;gbȇLw~|=ҷP)㤪T@9*\@& 5;#|$ TU3 K9m.RB@z2ezØ%Ɋ.Mb8Ċ,i>?V~gblcv,O =j[$#No*ERĮI-aDeV^2E^"6u(Hb'2뺂#-#dn_Z+-h=h$WHO8Cc0Z1+'5GAwB""䌖m6p#J=/5~EgdKeRhSiI]| d^r_q TB|JCy'Մ>wv;U9Qaѥ6ti Y|71[VJ1+} PԵx &gX5"˘+ph:^d>\҄qaƧσ6kۅ7n30/gH7ivl9c5śKdX6;5S`H|IKB|){ؐfQWQIH%-< T!F*, ,Uq1MZE2)kVeJCM.-'cVxKgRYߴ:_mV$!pXDQp(* ?Scg)E'$H#6nPdOD"T3npu?ڄb sm- ;ajzV%_/|!` amD3SCw{^ skD8InQ,15г烚7EU:9졐bΓhvTje,nEV߾avHy[%Ut|Q ߆W9HC>B/~ gbjS\yO6 ډ z%`9sN)vw%?ڙ7;D2^FֺETOI;xaUM=Jcz~} _@a癇IX;nKqa$ w܌4vMd1dhhKekIѫn&D̪hduGK{dXUZ J|91fy `J;4fxVX:(ƪ ;>,YLo4=lA~VTs-oPPxPjgA//MWG_?|'_\^ml=8suؓ'mJ=q+웢-WGh 8IϹ䏽p0~zCSAė/M)}ؘ'3~VW[wHJ2{fK'rSKV=g OPR0\jpPFZx9zW Q+y:|'o.wYpE?L/@4G5#X DB2rhl6eiwwc"٣V9ھ' #OYMsp)&4Ai,JSC?cz)M>r܋='1{wc5^XȔϕx?1I{B+'txL ujس%A5XƘ36ςHw̔}O=*5rpCtIET,Y`U{xXÊ"vazy<͐Gack%r>ѝ1L/p[-w tOq&z 6͏wb'içJO6bs,)LX7_Q슢.MHbc,b&S ~ȾhE.AYOSLqI {w?603(CgXc5'&}DLS$y0W=b__nClMD g*"c\O [ZeH%A(çQ=xŏCWFUG$jMI? ⫛O>e;?#;7$+ߢ2=Cp&"|Q+0mSmelW YgFK vC yaN^M˔ k?+M+m]QBcTYԮ約F-^^9 hL0jԲ` dɰUW SY3Ĩ|wR&Aq➔s8x 8+ {, B| m:&؇vLnӪx$d_ĦFP)ܴU}zvbd)R 2b"6`s*w8Zt^ r%Z9Ub2[eH` ˷`sc(8,2Wy^ԳNfe^Btu:%8p@P'cF30 $O9@_ҌI V%]ɛV2uW{+?WVLXL[" x5uS 6Bd|N3OxYkaH'-ϲ\6GzY{`Z%YbD)WNqBcX}=lb%T!:UUǯ02IBN  PU-y^gHSR[/>}јXĠ8jA)jEf-D򲬞SWuG ٿe-[} @S[{!D5X]EU/ %nэO W/?N6˓$⛐3~gbƟhH--hRrp?Tڧr0H?dhAAP[ *b$Fn\ؑ>hOi $Bgpx C#ONx<#6!F~wn' |v)DëS*4|y,#KGoLz6fGdl@dFĿRޜ-UbnåGkaIgecV=뀓GjЇr 3Ӓ¼ ~E(W>OBpt{;w_RkM|v /p>eVcQ  I\H&,`.N2lTlJ >j %G}phD7!he9Uø'N8FH@S~Xdؙt-Z6٘v^g^ _B{AH*"kq;nY* RB"E[)5ߑg9u_ʌ݉}i2i{y+7\(]ތhwz!7K0[X6=+&ފS&aFyV0ZoOkm;8 rqMzpfcaܱ˥ H 6x5c^Qü"Hm5S4DAv|uFہqHh6wc>xs!J;Vv*32֪a/,|lM7m&FmݳH@1ӳJzFg&H!޷5xWzNN_LEK~jeۧ_>nji%d]j+&W̭j+Ї%V{QdTdш[VLj' a2Mm^ϜWC; au%4AYIXeBX%Gy^%z-Tx򵶣eϨ[$C-ѴG~9$pHvqKCX5h kaO֪7RF5Vx5b)] '?A(o(e 6ӕ9DR8oF%;4ͳG(,u#IdWx[͆M#, Q+b'f= {"=&c/F/޿_+~P–]ߚz9@{lp<MQU3!5wcFu`HdyvSalql_[4T>Tə j6l}풄[&Ulo]I\ẕh1kM$nDR1Eՙd, -G~w۹TQs2^H29HH&q]ӣr>)%1qD))ֺ;s_؊p˗!2՟b&n͍S6γ'͂V5#er}̈i>Onu+G{ƥd{ ɓR8uJ W{q|SCO6%?5>qc4_~l"7z`SxtSheU"ac8\|xL7Ywt"6NܠZK(?fߒZg̑Jhͯ{h)ZDPUXU;WC NSj2 kWò` 9h©vO (ql{_.pzNf* 1͜P~AvpŠx`Ec@XLQLl!rOTeq ';)NqltLR-jۧ{R-{#P13BIFCK41}uK/Jiy! ˜/t6;=g]?W'0x5gBNEjHh7H2'A,^ [Cۅ}WThFZFYó8x/ zED~OB`$_]B^I\SUb:W+<"\SQJۈtq$ʘ IJ m-ucTaWfz G v^KdWXSzK3*gxUm( iI7&1$:vx%!鈵?V7L2>yU}L 9^,lw@?н}zO nŜ =0V@] A &JHmt G]euhh. @-r|@d=Ѧ߭=ͮ2L/Xkrߖq'KcPc=uU1ҁdU mǁ0?hd׵+/5h&F5s;,N0nPInm4Lf{N]R1mچGEQߵA(݂ Q/NƐ*,J ]5 Bw!7ػ@QWj9u^yJ҃vV&p*2:b@ȼҕ"D95oSpO f yTܶ5(R|oFL;>?|Aoܣ(Wp,UN#}S5 n(j39H^ =LM]hK!=B);ZQΔz@ b}Nv(ox>W+W`܇;t ֎\ _ʰэ-tkPMu} )J*xCs:0Owr.Q !Pޫb  M,DL9.bEP4T_K}ZNOp(;`ݎ&k! 7ʂ ˠ,ΕeD.\*'+x_[cm&VAVa R%M]M~/ (2^jϦK%ΨB-@WN &冶.lB޴F֠z3!XB^U3Ϙfti])G(\sϓjΒHW:G1k{;!#Q6'^Yh7E-h2>DTVau;N|[sp5+x E ]_*؅4We C#N[_$ X{s!{.I)s|$lfȽmx&Uy [RJmD)/[˪2Li^GH?ۻY\FEUːj'?]5)3vr ;#%Y .?pXбSP dh,]}kYKS.6!ƫsw#r5ԀR-d|D>IQ* JNT{/8P!ۨZzn>`>!!3ٗ.B_& %.\QP ֣Nd'k}d"A^++\+d졲h?μBR2MTшI:dW[bJˠ+2+/Mk=:֣f㯶THHNF=3Et"k! p]^y,J{ 'Qک8JQX.rһ/1B˾/FNa-[H?17-i*>\J?vӦNIr@ﻊ@?Q!*2>zvt|>+/X{š)rѝ GLZxYӨ!y6nħtL 7|ŷ:tUP=xrb3V;c,u +7;4̈́+`i8[mliW󑵏EJq1h1Wjuܘl03qm~eC<;N`H1+o 松hn ~#׏8#I^ < ]L1B3ęV=8*igDğ4P/a* A,h v/!l#%}iNVu !=k. usHb.~0_Zb"EDNf-v^*0Ѡ-CBrj I0t>҈gyxSvEoSGRk3s3|k3!p#wH`*H9&պ*BnIͨ&AJX)E Y}"WQ֠6;?u.@bXlڜrT\%:jpT'$.[P%z@.Rh &k3wŸRܶNj4,b⒆٧14a#t؋bUu5h#]>e, `G *uFD_/⻉\hY?~kw3Ն?#dTjWYPqӫL,sIfUpG*|w&+j}.N|ѫHӊCT7 gE@?6r,\3He3jJJ.l;ҕ/9ԾNYkE_t~hyp +1RZFܤZ C(BN~yIwS~ڱ!ܳq]U׿%tI}KT\R??oUU&g>;nv4Pܫ.+pkrw̻T%9@$?)] w'׳R@QtOt8` >tN]*FX,Eq^AgdKGְ VMV_ PAa'Rjhi7G_lWb%cjH+䉢blEmGgs IPUٳvr=+/QJ# '++6my`yf;ZΘ.Ϋ!2" 2h lZȻEIo3c˵Bw~$[a`}5!A M썲Z.Vexî˾ +xZ?jyOI17ҿD:T_ C0UYBU{19/AN 媳qF-%!+6=S%w", endstream endobj 1404 0 obj << /Length1 1977 /Length2 11979 /Length3 0 /Length 13174 /Filter /FlateDecode >> stream xڍeT\q.;wAwNp A;wu9$ hZjsUoJRe5FS{c #+ @LAM^]†@Inb=@lioG4&n UȺX\||,,6;č,M LY{;3 h|ИXyyZ:Y\,Mlj&@JAŁݝ֙\nbP:܀_F1!P-,R7sq7r@6&@;g"W;S?@MF;X?`eb7?%k9Pgrpaٙ 4q7r312U@RD`Bg'Kg&gK_*-W}N@{2/)v@@Ć.NЃ:&̿6Qt5k`4!x;.N@?'XY&.ca r@dBV˯|fjog;NQ\MT_N{Xl.Vn/)YSKe :hZRw=NZ2,~ߚ$]mlOadkiO ®.vP5jbʸBdmF^&-%-=ʖ.&a_mgciTwuYYXgk&֠οV]%LM'd*6NN7+9MdgZ);!z\f_CY7q~/Y_f0K&vo0+&:@MHo4MHDwd6Y?TA'dJAUZ2m@PԞv *?ToQ}@b oE.@g˿<; $ pA]@?$ p˄ A6?o4AX7 n!pggҸ}u%@fQĵ.#ȻIW҅T#v`EA?aȇtG3yҋs(9 }FZqM)(6jGtC@\QP t0Oˋ3 P8U`X*lWbFe|(2lKݹ1v7_XO9N EW ECw N*_"=Iclm72Jt|HiVfE?bˎfirЧ,G wr?͓[Ќ0?im>}ߕoЀ4ea_]]>) RI{PH$Mȁ<.O;kG6bIߴy* )V2-?b v@J/ " x?/fdi](X[ǧgH3>:`"4PU&LLt1MW#QRy 'XʖXn׏ȱ?Pǟ.IVCM`CFid…ݛ@ycOѡV/ )J)e^\M u>1}w*u*;YE;,^]Q璾.Xi\)./&xRZM:"P]m^AQf}聬OE/i)1S5uZL38|:^[gel bZ^iIbGk;'nN(g4'&s0T80)Qw_6TFj)hnGzK4k8fe(A-_.]%Tz_# 55XOOc{XLվ|`%؃!]}܁)X^N"hfl gFz2jY. lS"uE-k Za Dg>HwJ(|jʦl8cJ힣o8pkc:pxI|Z)eY~HG_"CQ致 Vult'{3bX5ƅF/nϪ <;vµ,~sOvHuS2dKt+1 rKh^ Jz(A+,.Fbj ՙaUɐ?sbԵ'֏Ct30^6snМ=SWOiD\v\e!Ϳ+_P,fk3'}hB@!@jd2+VlI o¹> =F)Oy Ji$tcbɒ֥غy5$H7*U^']9Hhn,$un˲D,Px$&U 8?l5S!BP&W&S> CPxH4. >AB9j̄ {53ghM͢3馗̺gaň>z'ϝwɶ''DCYH2ϲn B韷V]Z}kVO-諹0v.ĭme ɚ_[ldknfM?66&| =F5ٙ4 `I,uMՆ-$Q'%3 :7F\W*m$c mP }XE:\ #׏ + RZ%W v&8daHv*ӍTn*[9H"VuXCq*l^P2QpALͅ7'`fFdHc1/9A00HH 09h[%/_)LK!7i;g\" =sEy7ɜҬӅHWt"kq##\)dą5.(Dn>[d0|*@X9G Z(ЩO =!ؓuP{720-Qd-k`6tp&51+>ĿTH%Lf/qƼ#Yڍ ^!A۝3dhnϴb Z܃# NY 5h\ 7*~r-ן(4uԵa 3F9۳ZD[ÈEqLWA4-!z S(O B֏ q E-@zjT94-}=NuQ{A'"|ʜ tnTޚN'5݀4d!ē8_sS{$4K%#}B9Clrpɓ")< h)ZOr՛Fru-_:Kp9a,֡6H=߉p}eŽV3t(p񸠤R *st|4 |[5@;+* `Qf܉ͣ1y/n1a˅d߽6p9%$sª\P bIZ(ҏ~i!Qf{jL2IEggKaVԋ2w>?<vM6J_01fcSOw Ĺ\$R#PMk7nCa[ kZG[q@[j.Hjow\8nf\礼$%H ܰ-ÂeZmYK6yb`c3ݼ*qO۠@q_ b|U5xiϾmz°ͯ y0&+0i's)N^cMIQܦߪ6ؼ|eUd+XeZW4[r}~#zFvMf\ :z6(fucW5&EUԞU2D=Mzd Ww=\o=: ^ǫ0e~,#rGDz<ǰl_1B 8y(1^ѱ$=0;N6gujݲyP. n!mDl\*kiT:;|P[.ebKҭ>B풯\~m}%(0>$5*A0~nRPEg39K;n;!l04dD4T=N d3g$)Q LJFՒڐœC5z)%nUaXK ajP] p0ݽŰ2KL]uPj:NUZr>z0}dɝ 9++gqktu#@A> YEA֧ :^Y Ek+ߗ`loY `ڍ$l32":%tc8n<֨ч m5tx: \͟&>#0nq<uЯ67ڇgY/2*b0v{[T+HS2 \H7 3A)ӜemT Iy\ě绨b(͚jhDB41 ǹxiT5Ojz8q߮fj\bwN@ ({ђW-mq= E`Ϟ'M}ZKy:_JA&[A9sҁWf̑e2[hO9lx!r̞ J($Q"JT|T+x!hS?םal&brNFwD6ɦ ش_>BN3wHڝ O7ȱ0?nm/⍆zl=6tnaZ?O6kJD D*q|K/i,QK̔3Vtl*Gg|9Ϟ<#>( ͫjg?J` alX8 č՘%F鹦.(!kYwgS$HKC5B'j5  v$?{}>VXYV,Q ⏇|XS CʮիT#%v5P@h6"HeoL \q 7Ő׃ꄜ % X̠kCðZz! $yT(}ٮ|q$_%>Qd+[Kk@"̞ވ $Eq+"]sby^uOa4UecȊ7eõ*E:RO$hJA2[x~JzɈmFh xgtW-!I'm-GN7,/MӶw#~R`%} &X?3\!&''<7OoVvx" U8̍k!b+/D&Gz,t9 ,7hNrPqȖ*)sL8cϤ%>I~_W BɺNVlRUav)f ZIMPir*/W/z/A2r #W-,3% ri]n0N0Pnd {n"}EF}"S(p. ,(JpzOx8%9uѽF^X`ZdCpqLJ?1/]]sW:L?F.%١ӯA.JS9oJ3ϵ٭5[r(&lNeUaLU'ܱ%ގ6̋Ӊu-8߸0@RC~Yr SeК5@.*Ms҇~bYÿśd@c4GDn})\1t8YI2 u{/֐etYjBqV|r#Nf.{UՎJ$۽\jh@-qܡ2VȤ(Vlf g1r.Vg<>g%1B}Ef W9_7Q's{9_Dµ6 -vLtw''S]pW]G'X'"A\ ®P}.ШӰs68Zp\^S JfMo8ȼՓOI }MS#ؓNƜM犞ͷ4{<N?@lF[Navx M[7&1pyb109a\9O{r=)=[_55Fu_lOǨs&˓5U2q/k}x;珞y4#&ZcJ7&ջi"l )>hթхCn0b'V`#QE֖xW~_؃F$<2g:?_̆D1 ׀~e|kc2 Ꙑ\*T%"}L2*OU ~h֒%5c<Ցnn2(d5^vo*-gG2cF;b^H=" rR يxRh%_up26kyz6wVҷ2 樂&fcˋcF>$~'"IE4좛N74}0vGUxO8QrhjϝȪ>=JF+ӢmltJzkmeBhoQ뚳@ 0<.9xm&5AiNqBL0o DŽ0Y;=yOTRʵTVj3/n FУ kM%Blu K>Awԙ?=1-WWUn@< y|!jvUiwFPf/Qjr.aa0O5e&sb!6]>9U '3k,*A4MFa.L(,\Su3#jVBTWLlmytcC.rzJOo ,MMs6BtQ/dT֪h*cVْP0` ,SJo!dQ7+//-2JćW ^_59mcdh}s:u;˽LjSI%g3oiHM# A6VyHt>ï]D f#I4FifJ[d؂a6e,VcJ7<OqNC=iqʽ]PTxVOg6+$;bjBr6-5ƂƴrS^7ދY[4)`&Q>dkvB~0Y>a m)ڳstO 8[ . U\uQ>5zOf9ߺk3)lW]D4K'}07Y,O27OkX .YN5Y!x7d xK 7UΣ,/s}*nx8 c]=y/[ycr{;(ZP" I?PuBQ:D?] ȗL҉qR?`KES2.y,WGܢN:;J/D,Yu)c!' eheQJ0^|뛰/#y.zt"=}6FɶHm.h=~<-,T a)&FK^ƈt!f!]˙%ܺI ͥ@5OE(SX{c/S@?L5lCu,(m`ZYҚAzW9&cNTfjm!TdBJʥfG O *2_H|)Kwʼn gqJw,QA8V̾- vAfrO/A q4,*_8qPJ;oSr1YqnX׈Oڒ,aT qOd{V?&ftՆ ip)kfij^d[hN5ak<̪_'y׿R NWc60>TIx׃oi]# +}Ÿ*vSZj#;HPk @Ķ_E#d疐E_{䆒nY06dc }bAEqrP}rY' u'xeUtAS4ݟR-LK<חt5#7߂ G+0$1w7 9NO]PlcuZdW!C<zbs0QcCHT5LD|fx;K?yLNA%ؽuZ\ՊW>ѹ]8эX WdxfnEM5rL|,RJxtxTFXpO, J"4m ^%wV>Th!n{Ӆft bAr{,q]!+(Z3~LhI,]B3ɖ2˜^d\ڄШA+4\5z];fޔ:EGXۗTiCEڌ1ȖϑMc yoeз) 4K[:3愑 s52[bXgAZmHDRF"?G6Z ;tEOO(I6 볓,*gM6=SȠ>`S3 Df]޼LUɳqVN8BQ3,;-ͣn6O&ϲqʯoJӊ 0dv z{20X$QU!<´V[\DБafin 6G!}ZNQ‡B |4f;" ܥۀ'ʹb.﯅ORq3k"2 sSM0y.f*w ɌЇnȁoX9/tH#,<6nz񺨪GT"/n%=a2s.$0$ÜwMs\XNe:)&5Stg(B#j|c2: _Y] A !:Ee˄f7ţ.Yan¹zd8S|]gR].bq R{ƕ_א.2ݚSq2ʙX~j^$x~HPǪCgxo*94= Fԗ8L0=;L~bn\ȋ1->6W*:-IJկ͛> 4Z{ꨗg:#^[C؛lsɄ~-ۺ!wqІ۪e65"=Wyxsu ֜ź+' W~K-Yr3IgjtJ,DS~AFr\p7EOVP+71 ymY-tp_ΆlSoǸ(ljo1g=ŋPDUY>zW A;'W0 Pe܋1ŵ[F'bF>dQ|urw&X8З^#9~莴Jq/eLl;5ZIUnݸʔKrZmP>j)tŚJS.|̍߾^?c!/v\χjI\oO(h/T:جQQ 6*Jrw9_uOdxϚmxt+{ɡP /N&o>'EH{ܺꙏ&.A' (b4.7D*B9HNJnٷV:ߏ_4x_C*,:Vklmx3ij-#SOrqJ"JӎddREѣiif=[iq!}j]a7)zv-կP1om1ƫ #l/jRU]eHLvZ=4A7d ټw%2Vb̜K|qf. Ncz5 $B@Wy"!ljqѭ I&3Eʝ?p*f dH?F*ZRa8_gڤ,i@i115 ^=P;^C *<>NPq/Q,.=u>kBZZJT#="p[e, s_dEkr*(r4>ͼR![ɥpnt) NceA endstream endobj 1406 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 1408 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 1412 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 1414 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 1416 0 obj << /Length1 1684 /Length2 1200 /Length3 0 /Length 2222 /Filter /FlateDecode >> stream xڵTyTFF+ϊ-*-lfeGDYž$lܐ0'HDw\pC彧KBAu-'X *>'\» Nd~]%l9Hf9aTHȔZbO4I鹟x2A*pB`NAUs# |A&G["dJ.ڨg̈t5 L+]B@SZcwr\F#ѣa xrp<٣JPI3szhU*1X EhT 5qZ'_ʇHTA;sxN~O$3m*$kt5]beh3肈Aq0?P2W1D"0="pq|$|9%Q Pk )sW )3v@ ̜ef\KhLѸ]ߟ C#;}Z0GKN݁ /c@&1a͌1Pe+ e (jy|[7&Xn-;]4m s2bʱ֊-Gϝݎe2'D./5g U{r}Qu:]۬J+VrڂR}k 7}o,6c?84.*^mm0u͹1CKfͳ(=4WmkcbЇ#.؋5d&㴝 y:|b\vt߶{Hh)"{ sjA:wk77jG{WoU%3bڐ!amuw彊J7S/Yk[ J[-QYgR&>;4cLK|׃͂օk 4'_D˩IO6\z=u9E{B:zul+k*٪;?ہc՛*sTLә{iÓmwݣh]}y>%RHh򯺼&}Wdk}s".kt/bynJa{IE\5i{mԝSzqEw7omzeoȣ']|z!\ߪ=,"ŤJKuM͝ ߛpc]jܳ 37btozhy]'{Njb~2Ū)>Ue@^jӖvY۞Rv>P7/F6dwo ^vuskny(۠̒M1>Ip >+̸pJfs˅m?Z>/9`:bUӊ[9KVWOZ}81_P Sv M1?Bˮs,u򻥢&GT?; C4yU,~= endstream endobj 1418 0 obj << /Length1 1684 /Length2 1200 /Length3 0 /Length 2226 /Filter /FlateDecode >> stream xڵTyTv(*\=Bv[d$"1$7H (qЊ Tq{R7@x*Bq}pLHRO0=rCBt Wkhf*1پ)4}20B 9aN!#\H$A UR0Dd@)s2NGRRw/ 8Her_ _ALzX\"_2{|Rzi;t |RUbj\44r8j搔Ӛ5T2@o jDt8P9+ LR 9LAT$dځppP 7FF 'hH`mЃD =P<?E1=޻?ڼKk3'}G ޶$T@k!^ϜNlaGH)'3B @BG zC?xI* 'd) '*7S 0]2>Ԑ<S4*4\I9Ϙ%Y:RTVpD/V[ M`Vǎ+(qDeDH0sw $@ U,n8I#q537WA R˟;4K?$.2]I*@8 <`(%!Z|O( xi"Y g.7 !*  "fG`\,V& 1 5(,C D FC4J:T$bC :Hᤒd$;d.0ZFSd2(pB W NQ/id -b)e T $&"߯1u h]ͻG9*m%J;xmIך{m;)eknqWTg'XNw;[|:6+Tw,X{tΑuUSzͧJo֨ڃ4VvFrYUsy.J>"iCwmOo|G,i3&n Wdό8,_ Лu>͎vzz#~4;秐^Yoz{-=c=p+6^$!;aOx]r =,gΒN7~oڡ.6reb;=cRO=zyq9O {BE[ ,gGä^~cK<k2C|nCϛGDVJ.^V|ٲ|͌YCWqo+~gqf ,_eQf4x^6C|q:\!}%8X2gXIиFMșYV"vs{v'2}tݘMKE{~ڮ8? } endstream endobj 1420 0 obj << /Length1 1678 /Length2 1203 /Length3 0 /Length 2226 /Filter /FlateDecode >> stream xڵTy\WX[QA(Wלu@AH$萼d&L*"D x"Rծ`QÃz,j Zu|2;g;5XHK Wx 3Ws('8$$=Е3P )B9B~Aqz(iL 7Q8Q7( prJl`h2F@/d 2$@$`Z5 @ÀB3_9PaA'Xer K>~ }!GR9}P #Ã}|v@VBٶ}!d#4Hp0ރϏEhGRQ<քOiCR})&b h`Op@  $_ǩCT$dg`ؚڞp@CثM@ P@c 4XfT@Ql.6{hgx,a^ 7$ "j\ Y4{f8a>297i2hX\E.@8:!TޤNP> xbH*y}Gd aN5N zW} 2q>ڢ 0V᳍MaB֌7I=PcZj># 0# TAGc1U'$p1#$\ irD#" mPA5/%$ kj:|׾wxE %)i_<qF顸SILDi! y'WQGNI]K8{!UM@Nn&DaAy?^IXBIp" \\FQXG!rqF!Ҽ ƚy̺_;q:Y eqqKr Nx`ە{w91ʂ⼭;l昭/0c9rM ì滳Ĺ d*lu vOg43͢IJ!q\Hko"[);o(9Ӣo9'wfb5 /KcވRNFNo^ފvu4j/1uƙ6iχ?혿*o5UͿF!Ðxo6u'{?-)y_n|ac%Tpq7TnyU㫾]{;:l7EoCXO|u~AӚ]"m5}7LS՗HԻitoޡ_4іc2"-)(>9iV{ό ;$Z. ]xg󜶍۩ endstream endobj 1422 0 obj << /Length1 1717 /Length2 1781 /Length3 0 /Length 2842 /Filter /FlateDecode >> stream xڵT{DrLU[3u7Y89R ?1I_m1Gp!"Uqՙ!q YQITFvJBXl; N=Q;&q}'%ҿ8S߅*A CP$^x| "M/6LXɏ23Tf))RL S!L(8B&S]QsѡB $'AX0iDYc+Pq"B =#HyXnXr8pwHW00X"I 0  JX6} WT$aGe1ĉIiT8kF8lLf}@T}qBWWI1Ӟ Jؐ"aۃd~Ti(F!@*'RQT'Ͱcz4_RZ$0dc:0_uCȷ$Ts֟.8KȰ88 W.Ndr (i'~S0|)L6Y. 3>HM2k՘V|JGwZ˱Tϝ7*Fi鹄nQtT=&]+Oڅ{;.M_ 7[3Yݓ7 R9:%UŜs&}KJk.>>s~0QUIDũ;;F+v8>I&lّ֠I9YE׎-Qz ',{_EAÜ7S/n)`ӅU_?Вƻg:6hm[& ,6Ivwc/:ZgݪM=9oogZE2/MMN-b"ZfPWEb^e 6}mEx,I8]iy>+uG/Vkv1\[7%%UK7g4~mٓ)9v}[+Isɿ5lcF fhzܩUA+)oG2S,"Jw z\j^s]?omx5i*h!qOSZ/n67$I?'URZ'-oMq3ꌧFcсvZL3} L]7s6K]yңv]ם{}ے yO>bnzڜF9iAmT+3¢ J|sSOJh8ި1x?]%nmWcԷS[8|U/Ռv o;F獥U9S7Il3MI纲`Bv6b왢ٜ9`\OqcBJŴhQR.USPHckAxE%gscii1cu46^ N#a׻r!Rl¾,OdYexTՋ<Lbuz?`AB,ew"U?U2Hk"^Sﶞ}|ի6Yv";^/V.;p ơ40ȶ-w?ZT[auRޫVvf,]& }ћ#Kq7`[zwBINDΪ,vϽ´?K=ϪZZ8Oyzd*f} Dj;lk-W4N=uٹGY#@n~7jee+eޟXLL gi>Ξ):|nJE(sN6\~3o5xB|E k iM&3PP|pm\EJBËᠾkɷp?O=Jf U'E\lcP.9:[ҫ-!Ʈv+E G쀱N˵^F&ҟŹcR_ endstream endobj 1376 0 obj << /Type /ObjStm /N 100 /First 1000 /Length 3649 /Filter /FlateDecode >> stream x[[SG~WRߪ\61vl 62A!I$NtYn sεGB(3 %E&̤4QҎ&:VdCyW|d\|G(I aODNJgF \ܢp鵧6i3=ɪB&CXAOhI-F5$֙t&>,fs -A$RTByx,Q1"Se#3eC\J^e3HUeL&P_ K Q6>HixX#~VdiǴ7pOXBF͌qeP>3VXKX9yzb3Y.,`FPZM&2%QNGݼΜdso2nf.D\`nd\4#|ȼHΉ2%'29VBsO`jNn) G h]RÚbP ZDOqXPH\7-YIk XBI$ ,Y*pjSs Cc2:w)V$PC-e- dG+!l0?L pu[_&θfvp8ӻx}Fb}d?b}Џ<<Cnӌfl_~Mr"tS#j2,WuRװ:xxr )t.rBuS[r!r#ԹQk햲ȚY8ihXz\K;Z8ox:kiitCJč~$-*Mi~ 59u4P*49uMr闧 -;) u)Er-tZy@w-B?6j(d%LSWQ̚q)) 8t:--Y(@Q(‡:P 0QYZΚg+li-NH&GI5%u<;jjkxb}prP=C񇡆wjh8Q|~HS^ؗ>]qf<8- nf:"CO;!lNQ*M9^<9mU@z6Y.'iL[SaʱdҾ v6c[4&^sUi%\Ǒ<޳3ϣ&q_K\ħqO$I%iL๒zGqS,H |$.g4vb5;}:h3PeNR H'c/T8b#a;!:~ϳJ ZnV1H^PwעGA:ړF)SiL+.tq?m%w"Ro"_ړV,t0̙#)KؔhEp6FҦ(¯E\elnqBYo)ݱw~"߾ph~38BAUzNjd}ɦ|I7 )[JlI]5\ҏyWrjTRf X qEfPA.5KiM yItCx=9oٖ:[B7hUD%"\^JxRT-W8ӜDsw}8?zENl1Nf׺E!cI%Y@\#]']d+=m<)OM hw S5N֙3h7xXi}^%s8/D ,iihKQ"_}iuƴڐOJͽPSU /&t4N/9^np$ik Px"cP AHZ&pJ={ֻ}Qq#.tGޠ;ȟNw=v^>(ޘޛ7vX}.,˴v1`6b}Nz3i'޽$υ\Q=}T+e{ 9{د%;f"*o[vch"¾৏ e]oŐٿٟ@ ٰ?,--%لMw&Mz\lψݱ?+SGsM?;;:'|O}o+V{j^J%Zu&602$ u7qcuƫf=-&' o_읜?,݁ց;8;$gXt^ yo[|=~z|o RmP#@$ܛ$7!g9~ 6 n+v߽?ۍh[RSh¶3pe r潃u]xE(akqlJ/ ӕ)s@5"M|HRXݞ,˶smTw_9x ڝN:V't ~3$c_dne󷿝98%VN^nV^}}6:r {^"\M;P/r_ͻոbIS,w7!bjQ'p; VɴyF]\\)6Lo=]hEG`K[{н:yJ殒g+q0V̦f,R97J8>ɳeSaQ`ۈolL<96;=?ǯ^IWwxEOwnJJSq ŬEhf*nTH_}FŰ^CYHC7Pn>=-5RDZf*} -XMZr> stream xڥXѪ$7}-K! @^6$!۲]f&K9eZL-Wt$՝b!44£VC41RL1h,Xj:-EcƟ D72[*kH Y"n3 %cW4ӱ{@n9ް:%J!¡j XxL`/ f,r:+c2VPV[J;ECPW @V@ЊEBN)P~D 7 J[* 0++Oz8%СFB" %)EJZo ^%"4$"aTŰPŖ1EN_EJc*S"4vć,**xa l[` D3̰#34yd;)wRhhRAS P G>F  4r@"AbG8 >,P+8V H?+r!$z/ `#*`#wmB{At׷7/O 7ܿ~2b!R9/5޾||ȽTd~mIErOүyO/$gX~~K')ϐ]wezi*ڟ׮g#]I`1ErXQ1XqZڅt+İ+?bu/',c)bsX²ujѺZ5iW},QO)$W}fm)/ڼlfM͚֏⵵V1ŊkմVUjZa8bâ5i]ue}l]W 5yr^#:_ru5bJ+,1zj +9,^afK֢j:j3ӸՔM#o5q5)nRULUٍߚtr> stream x}Y͎45 SIlGBHBTzl)gk2((R=xTkI925N< ^K2攉WImʫz؜ipǫY 5MML%wCKfJ" eȁ:&wNE^"m2&7CÜ>(:B Q!=F>r?{Oa }*7VzbUb VD(*O3 *V.^],+3[,<4mW}%y/KXΆ|g%{eȻyXb'֙EU?%Vdp<4X2bqxeab4Xa)r`yGW, 5<X`5>ʤwe҇b VD(zeWVUyb9-mixU鍂c0Xb>gYfEs>b>gI(2}N^*BWyUPOYuCg>slt=g}t>;y9C,\W˧;]>Dnh_Yu61su@^dӫ:6۶Tslwf~oavî<V3+φ}4owo4C̡~ ˑ|IkL˗/M/M_}Hy{|Ry?"8 24DWSiKht*V0X^^%Իu.ꦫ9,|5htvކ!uҐK>hsa{gy˸$ uk;ٌ"gmg3RF?۱RF?۱;yԟv,sxԟ6,g6fA?#֖nvk[Ƨ֌AHoh!EhwRnHoڈb'_2|9:7ڜ UFWjjQھj&2` endstream endobj 1458 0 obj << /Producer (pdfTeX-1.40.22) /Creator (TeX) /CreationDate (D:20220116125202Z) /ModDate (D:20220116125202Z) /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.141592653-2.6-1.40.22 (TeX Live 2021) kpathsea version 6.3.3) >> endobj 1431 0 obj << /Type /ObjStm /N 34 /First 318 /Length 1452 /Filter /FlateDecode >> stream xڥXMs6 WîFkㇳK(^ś5tcmUHƎڛAդ-QBI[taή"GLy!1l{mg)Bs,~+勽2 _u—a'd+'<;\b/'r,gP;*i8Z2,wǻ/.Թ);BcpR9웂 Jp3 \igcL!jOsP$XA @${K%,2V8hDBEDR+T|QіT@ *T;mQ!ڣB%=ĸh#J)9 G)9dׅ -3H%T)Pa\qYD*TآQ!~3~m"%M,ma!9"h1ah#P9SNr)PZ9Jaރhѐo7!#pJ?zb HeH JF'S#-uRC%V +ŇGVܸW! - *R'Žp".nQ]ؖK :'#=PrJ!s@u043"q,7 $xݶMc=sAQ_vCݴh3m]p򛸼MқC:>q-z}zyy}hfnn6ǫ͹{+*}ge,nʾm <1366F0B90035CF511DF20F4EF1006A80>] /Length 3384 /Filter /FlateDecode >> stream x%YlW}o$>v'v;Ď8qb{xߗ$q"@H > QTaUC/<@->D5!҇!$*PU*RG !?w<̙(YUEe_Dn6DQbYb`Ӣ(cR2kmA֢Y\.ei&ʮG@%p T08@=8 h$h@38 Z @;8 ΁% @ zA7QenzeL6D%Ȃ2Ԁzp. pp !0 F(6`̂90"X`56& ` * "^_|* e7J kC`w K`l{U{ҀE X4`рE X4`рE X4`рE X4`рE X4`рE X4`рE t?`рE X4`рE X4`рE  W 86؀ X*` X*` *[٬d,)d@uh@;8.]) X4`рE X4`рE X4`рE X4`рE X4`рE X4`рE X4`ѠcрEC%2dA3 [E\Ӹ77򑐏nH(1RB4E E4E%D#Q4.Fr&"Q*:P"Q*sB*3Q"Q 0B ,Jm(MQti C)u=Q!eAקTN4ʂnFRNZeAweseAÄe8 w&ʂ+'GQ?Q b(u(b(ZF 0$K $k2 H6(0"9?щP?e3̟(̟<,z2R{Jߏ=/}@/C })J!k?>(uj j̯˨2_\0u `h$/ޡl$ &@mT3 >.|mLW.bo.b:1\ ^E] fjrxu x t7YP,A@90 ,jx5B<d!Bd!.d!Dx~4M+ m.,:n,c(YuU:4d!-3d!Bۜtj I{ТmG@E|BapYk:Q %Oc}GnEls*sݢw< =oOZt<gӲH7?/G/_VyZ{*wnEo\W9 -zI7WE2-US`Ң›*gE>rY\^= y,{TluR|5Wjz( ƿ\m4`f:k!k^]*@YoT:߬{YZUfQI 5f*Yt*1q:x^e#hMm;΀Ӗ|FZ@;ẖk[8Zim;"`.Yfun.[f&Wxh\z\ƄvA? `10bЛd̀Y0XK`Uw=plm Qj!L\0 rL jc*^Ǫc`s~t̚AsW8F1q,E8&10w,68f-9cZs v 11tK )+9釻 ykI|YL0+ fn0]pw2[?ۊ̗߰T:fn0{p3pL2`XsL(p̚&8^עc<`r2tAt}O=t}OC=t}O=t}O=t}O=t}O=t}O=t}O=t}O=t}O=t}O=t}OǢƏ[ &UJU2[xl᱅[xl᱅[xl᱅nySӑG-ϤƬd@jJ>m+y1#5aY{\jҲ=Hݱ”Ԕe?ԴeԌ2CRxKjrRk"`m)-7^4/WsZM<YnAA^K Ub|1>s @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 VERSION 0.8.0 @set COPYRIGHT_DATE 2018-2022 @c @afourwide @c %*** End of the HEADER @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{http://octave.sourceforge.net/arduino/}. @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:: Arduino 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 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. If the toolkit can not find the IDE, run the IDE manually, close it and retry programming the Arduino.} @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 Raspberry Pi Pico @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 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 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 pf 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 MYADDON_INIT: @{ cnt = 0; sendResponseMsg(cmdID, 0,0); break; @} case MYADDON_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 @section Sensor Overview @cindex Sensor 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. @section Available Sensors @cindex Available Sensors The functions for each sensor is listed in the function reference and is 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.8.0/doc/functions.texi0000644000000000000000000032162114171012362015020 0ustar0000000000000000@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 attempt to find the binary itself. @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 (@var{maxCount}) @deftypefnx {} {@var{retval} =} scanForArduinos (@var{"debug"}) @deftypefnx {} {@var{retval} =} scanForArduinos (@var{maxCount}, @var{type}) Scan system for programmed 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. @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}]*) 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. 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 in turned on @item port (read only) the communications port the board is connected to. @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/display @c ----------------------------------------- @subsection @@arduino/display @cindex display @deftypefn {} {} display (@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/display @c ----------------------------------------- @subsection @@device/display @cindex display @deftypefn {} {} display (@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/display @c ----------------------------------------- @subsection @@i2cdev/display @cindex display @deftypefn {} {} display (@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/display @c ----------------------------------------- @subsection @@rotaryEncoder/display @cindex display @deftypefn {} {@var{retval} =} display (@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/display @c ----------------------------------------- @subsection @@servo/display @cindex display @deftypefn {} {} display (@var{dev}) Display servo object. @subsubheading Inputs @var{dev} - 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/display @c ----------------------------------------- @subsection @@shiftRegister/display @cindex display @deftypefn {} {@var{retval} =} display (@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/display @c ----------------------------------------- @subsection @@device/display @cindex display @deftypefn {} {} display (@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/display @c ----------------------------------------- @subsection @@spidev/display @cindex display @deftypefn {} {} display (@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/display @c ----------------------------------------- @subsection @@device/display @cindex display @deftypefn {} {} display (@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/display @c ----------------------------------------- @subsection @@device/display @cindex display @deftypefn {} {} display (@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/display @c ----------------------------------------- @subsection @@ultrasonic/display @cindex display @deftypefn {} {} display (@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.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 {} {} display () 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 {} {} display () 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 Compatability Classes @section Matlab Compatability Classes @cindex Matlab Compatability Classes @c Matlab Compatability 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 {} {} display () Display the addon in a verbose way. @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.8.0/doc/gpl.texi0000644000000000000000000010433014171012362013566 0ustar0000000000000000@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.8.0/doc/macros.texi0000644000000000000000000000624114171012362014272 0ustar0000000000000000@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.8.0/inst/0000755000000000000000000000000014171012362012320 5ustar0000000000000000arduino-0.8.0/inst/+arduinoio/0000755000000000000000000000000014171012362014364 5ustar0000000000000000arduino-0.8.0/inst/+arduinoio/+config/0000755000000000000000000000000014171012362015704 5ustar0000000000000000arduino-0.8.0/inst/+arduinoio/+config/config_due.m0000644000000000000000000002061514171012362020170 0ustar0000000000000000## 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.board = ''; 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.8.0/inst/+arduinoio/+config/config_leonardo.m0000644000000000000000000000671314171012362021221 0ustar0000000000000000## 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.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.8.0/inst/+arduinoio/+config/config_lilypad.m0000644000000000000000000000412614171012362021050 0ustar0000000000000000# 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.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.8.0/inst/+arduinoio/+config/config_mega2560.m0000644000000000000000000001563514171012362020647 0ustar0000000000000000## 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.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.8.0/inst/+arduinoio/+config/config_micro.m0000644000000000000000000000653714171012362020533 0ustar0000000000000000## 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.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.8.0/inst/+arduinoio/+config/config_mkr1000.m0000644000000000000000000000574514171012362020514 0ustar0000000000000000# 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.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.8.0/inst/+arduinoio/+config/config_mkrzero.m0000644000000000000000000000720414171012362021103 0ustar0000000000000000## 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.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.8.0/inst/+arduinoio/+config/config_nano.m0000644000000000000000000000625614171012362020353 0ustar0000000000000000## 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.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.8.0/inst/+arduinoio/+config/config_nano_33_ble.m0000644000000000000000000000601514171012362021473 0ustar0000000000000000# 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.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.8.0/inst/+arduinoio/+config/config_nano_every.m0000644000000000000000000000615214171012362021560 0ustar0000000000000000## 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.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.8.0/inst/+arduinoio/+config/config_nano_rp2040_connect.m0000644000000000000000000000645414171012362023073 0ustar0000000000000000# 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.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.8.0/inst/+arduinoio/+config/config_promicro.m0000644000000000000000000000703614171012362021247 0ustar0000000000000000## 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.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.8.0/inst/+arduinoio/+config/config_promini.m0000644000000000000000000000662414171012362021074 0ustar0000000000000000## 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.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.8.0/inst/+arduinoio/+config/config_raspi_pico.m0000644000000000000000000000547014171012362021545 0ustar0000000000000000# 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.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.8.0/inst/+arduinoio/+config/config_sparkfunsamd21.m0000644000000000000000000000724214171012362022255 0ustar0000000000000000## 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.board = ''; 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.8.0/inst/+arduinoio/+config/config_uno.m0000644000000000000000000000634614171012362020221 0ustar0000000000000000## 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.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.8.0/inst/+arduinoio/+config/config_uno_wifi_r2.m0000644000000000000000000001056014171012362021633 0ustar0000000000000000## 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.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.8.0/inst/+arduinoio/+config/pin_info.m0000644000000000000000000000174414171012362017671 0ustar0000000000000000## 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.8.0/inst/+arduinoio/AddonBase.m0000644000000000000000000000350414171012362016364 0ustar0000000000000000## 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 {} {} display () ## 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 display(this) printf("%s = \n", inputname(1)); endfunction endmethods endclassdef arduino-0.8.0/inst/+arduinoio/FilePath.m0000644000000000000000000000215614171012362016242 0ustar0000000000000000## 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.8.0/inst/+arduinoio/LibFiles.m0000644000000000000000000000234014171012362016232 0ustar0000000000000000## 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.8.0/inst/+arduinoio/LibraryBase.m0000644000000000000000000001022614171012362016742 0ustar0000000000000000## 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 {} {} display () ## 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 display(this) printf("%s = \n", inputname(1)); 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.8.0/inst/+arduinoio/boardTypeString.m0000644000000000000000000000370514171012362017667 0ustar0000000000000000## 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"; 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.8.0/inst/+arduinoio/getBoardConfig.m0000644000000000000000000000260214171012362017417 0ustar0000000000000000## 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) config = eval(sprintf("arduinoio.config.config_%s", board)); endfunction %!test %! c = arduinoio.getBoardConfig("uno"); %! assert(c.board, "uno"); arduino-0.8.0/inst/+arduinoio/lib/0000755000000000000000000000000014171012362015132 5ustar0000000000000000arduino-0.8.0/inst/+arduinoio/lib/LibraryBase.cpp0000644000000000000000000001415514171012362020043 0ustar0000000000000000/* * 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 #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 // 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) { 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 (); } 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; } void OctaveArduinoClass::init () { OCTAVE_COMMS_PORT.begin (9600); for (int i=0; isetup (); } } void OctaveArduinoClass::runLoop() { int ch; if (OCTAVE_COMMS_PORT.available()) { ch = OCTAVE_COMMS_PORT.read(); 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.8.0/inst/+arduinoio/lib/LibraryBase.h0000644000000000000000000000564214171012362017511 0ustar0000000000000000/* * Octave arduino library interface * 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 . */ #ifndef OCTAVE_LIBRARY_BASE_H #define OCTAVE_LIBRARY_BASE_H #include #define VERSION_MAJOR 0 #define VERSION_MINOR 7 #define VERSION_PATCH 0 #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 #else # define OCTAVE_COMMS_PORT SERIAL_PORT_MONITOR #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.8.0/inst/+arduinoio/lib/OctaveCoreLibrary.cpp0000644000000000000000000002303514171012362021220 0ustar0000000000000000/* * 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" #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 #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 OUTPUT, // 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) void reset () { // processor software reset NVIC_SystemReset (); } #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.8.0/inst/+arduinoio/lib/OctaveCoreLibrary.h0000644000000000000000000000174114171012362020665 0ustar0000000000000000/* * 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.8.0/inst/+arduinoio/lib/OctaveI2CLibrary.cpp0000644000000000000000000002631314171012362020707 0ustar0000000000000000/* * 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 # define WIRE_INTERFACES_COUNT 1 # endif #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(data[0] == 0) Wire.end (); #if WIRE_INTERFACES_COUNT > 1 if(data[0] == 1) Wire1.end (); #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) { #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 (data[0] == 0) Wire.end (); #if WIRE_INTERFACES_COUNT > 1 if (data[0] == 1) Wire1.end (); #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.8.0/inst/+arduinoio/lib/OctaveI2CLibrary.h0000644000000000000000000000167714171012362020362 0ustar0000000000000000/* * 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.8.0/inst/+arduinoio/lib/OctaveRotaryEncoderLibrary.cpp0000644000000000000000000001536214171012362023114 0ustar0000000000000000/* * 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.8.0/inst/+arduinoio/lib/OctaveRotaryEncoderLibrary.h0000644000000000000000000000176714171012362022565 0ustar0000000000000000/* * 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.8.0/inst/+arduinoio/lib/OctaveSPILibrary.cpp0000644000000000000000000001140714171012362020763 0ustar0000000000000000/* * 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.8.0/inst/+arduinoio/lib/OctaveSPILibrary.h0000644000000000000000000000167714171012362020440 0ustar0000000000000000/* * 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.8.0/inst/+arduinoio/lib/OctaveSerialLibrary.cpp0000644000000000000000000002047014171012362021547 0ustar0000000000000000/* * 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.8.0/inst/+arduinoio/lib/OctaveSerialLibrary.h0000644000000000000000000000173114171012362021213 0ustar0000000000000000/* * 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.8.0/inst/+arduinoio/lib/OctaveServoLibrary.cpp0000644000000000000000000000447314171012362021433 0ustar0000000000000000/* * 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' #include 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.8.0/inst/+arduinoio/lib/OctaveServoLibrary.h0000644000000000000000000000170514171012362021073 0ustar0000000000000000/* * 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.8.0/inst/+arduinoio/lib/OctaveShiftRegisterLibrary.cpp0000644000000000000000000002506314171012362023115 0ustar0000000000000000/* * 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.8.0/inst/+arduinoio/lib/OctaveShiftRegisterLibrary.h0000644000000000000000000000173614171012362022563 0ustar0000000000000000/* * 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.8.0/inst/+arduinoio/lib/OctaveUltrasonicLibrary.cpp0000644000000000000000000001077114171012362022456 0ustar0000000000000000/* * 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.8.0/inst/+arduinoio/lib/OctaveUltrasonicLibrary.h0000644000000000000000000000173014171012362022116 0ustar0000000000000000/* * 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.8.0/inst/+arduinoio/lib/octave.ino0000644000000000000000000000411114171012362017117 0ustar0000000000000000/* * Octave arduino 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 "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.8.0/inst/+arduinoioaddons/0000755000000000000000000000000014171012362015555 5ustar0000000000000000arduino-0.8.0/inst/+arduinoioaddons/+EEPRomAddon/0000755000000000000000000000000014171012362017665 5ustar0000000000000000arduino-0.8.0/inst/+arduinoioaddons/+EEPRomAddon/EEPRom.m0000644000000000000000000001306114171012362021133 0ustar0000000000000000## 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 display (obj) printf("%s = \n", inputname(1)); printf(" %s with properties\n", class(obj)); printf(" length = %d\n", obj.len); endfunction endmethods endclassdef arduino-0.8.0/inst/+arduinoioaddons/+EEPRomAddon/EEPRomAddon.h0000644000000000000000000000434114171012362022075 0ustar0000000000000000/* * 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.8.0/inst/+arduinoioaddons/+ExampleAddon/src/0000755000000000000000000000000014171012362020760 5ustar0000000000000000arduino-0.8.0/inst/+arduinoioaddons/+ExampleAddon/src/Echo.h0000644000000000000000000000250014171012362022004 0ustar0000000000000000/* * 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.8.0/inst/+arduinoioaddons/+ExampleLCD/0000755000000000000000000000000014171012362017546 5ustar0000000000000000arduino-0.8.0/inst/+arduinoioaddons/+ExampleLCD/LCD.m0000644000000000000000000001513714171012362020335 0ustar0000000000000000## 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.8.0/inst/+arduinoioaddons/+ExampleLCD/LCDAddon.h0000644000000000000000000000553714171012362021301 0ustar0000000000000000/* * 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.8.0/inst/+arduinoioaddons/+RTCAddon/0000755000000000000000000000000014171012362017226 5ustar0000000000000000arduino-0.8.0/inst/+arduinoioaddons/+RTCAddon/DS1307.m0000644000000000000000000001745414171012362020240 0ustar0000000000000000## 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 display(this) printf("%s = \n", inputname(1)); 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.8.0/inst/+arduinoioaddons/+RTCAddon/DS1307Addon.h0000644000000000000000000000234214171012362021167 0ustar0000000000000000/* * 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.8.0/inst/+arduinoioaddons/+adafruit/0000755000000000000000000000000014171012362017427 5ustar0000000000000000arduino-0.8.0/inst/+arduinoioaddons/+adafruit/dcmotorv2.m0000644000000000000000000001205214171012362021524 0ustar0000000000000000## 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 display(this) printf("%s = \n", inputname(1)); 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.8.0/inst/+arduinoioaddons/+adafruit/motorshieldv2.h0000644000000000000000000001643714171012362022414 0ustar0000000000000000/* * 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.8.0/inst/+arduinoioaddons/+adafruit/motorshieldv2.m0000644000000000000000000001636614171012362022422 0ustar0000000000000000## 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 display(this) printf("%s = \n", inputname(1)); 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.8.0/inst/+arduinoioaddons/+adafruit/stepper.m0000644000000000000000000001552414171012362021276 0ustar0000000000000000## 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 display(this) printf("%s = \n", inputname(1)); 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.8.0/inst/+arduinosensor/0000755000000000000000000000000014171012362015266 5ustar0000000000000000arduino-0.8.0/inst/+arduinosensor/DS1307.m0000644000000000000000000001610614171012362016271 0ustar0000000000000000## 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 display(this) printf("%s = \n", inputname(1)); 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.8.0/inst/+arduinosensor/GUVAS12SD.m0000644000000000000000000000744614171012362016736 0ustar0000000000000000## 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 display(this) printf("%s = \n", inputname(1)); printf(" %s with properties\n", class(this)); printf(" Pin = %s\n", this.Pin); endfunction endmethods endclassdef arduino-0.8.0/inst/+arduinosensor/MPC3002.m0000644000000000000000000001026714171012362016376 0ustar0000000000000000## 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 display(this) printf("%s = \n", inputname(1)); 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.8.0/inst/+arduinosensor/SI7021.m0000644000000000000000000001365114171012362016277 0ustar0000000000000000## 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 display(this) printf("%s = \n", inputname(1)); 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.8.0/inst/+matlabshared/0000755000000000000000000000000014171012362015022 5ustar0000000000000000arduino-0.8.0/inst/+matlabshared/+addon/0000755000000000000000000000000014171012362016162 5ustar0000000000000000arduino-0.8.0/inst/+matlabshared/+addon/LibraryBase.m0000644000000000000000000000460714171012362020546 0ustar0000000000000000## 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 {} {} display () ## Display the addon in a verbose way. ## @end deftypefn endclassdef arduino-0.8.0/inst/@arduino/0000755000000000000000000000000014171012362014061 5ustar0000000000000000arduino-0.8.0/inst/@arduino/__freeArduino__.m0000644000000000000000000000160214171012362017275 0ustar0000000000000000## 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(obj.connected) fclose(obj.connected); obj.connected = []; endif retval = obj; endfunction arduino-0.8.0/inst/@arduino/__initArduino__.m0000644000000000000000000000637714171012362017335 0ustar0000000000000000## 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} =} __initArduino__ (@var{obj}, @var{port}, @var{board}) ## Private function ## @end deftypefn function retval = __initArduino__ (obj, port, board) % send command and get back reponse ARDUINO_INIT = 1; ARDUINO_GETLIB = 8; ok = false; if !isempty(port) || !ischar(port) obj.connected = serial (port, 9600, 2); # need wait for aduino to potentially startup pause(2); [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) && (board != boardtype) warning("connected %s arduino does not match requested board type %s", boardtype, obj.board) endif obj.config = arduinoio.getBoardConfig(boardtype); # update values that could change obj.config.port = port; obj.config.board = boardtype; obj.config.voltref = voltref; obj.config.flags = flags; if ! isempty(mcu) obj.config.mcu = mcu; elseif isempty(obj.config.mcu) obj.config.mcu = "unknown"; endif obj.config.libs = {}; # query libs 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 else error ("__initArduino__: expected a valid port"); endif retval = obj; endfunction arduino-0.8.0/inst/@arduino/arduino.m0000644000000000000000000003210614171012362015702 0ustar0000000000000000## 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}]*) ## 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. ## ## 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 in turned on ## @item port (read only) ## the communications port the board is connected to. ## @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 = ""; 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"; this = __initArduino__ (this, arduinos{1}.port, arduinos{1}.board); 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, ""); 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; 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; 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,"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,"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); # check have requested libs reprogram = false; for i = 1:numel (requiredlibs) lib = requiredlibs{i}; id = this.get_lib (lib); if id < 0 availablelibs = listArduinoLibraries (); 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 if reprogram printf("starting reprogram process ....\n") # free arduino resources, reprom and then reinit this = __freeArduino__(this); if !arduinosetup ('libraries', requiredlibs); error ("arduinosetup returned a failure, so did not reprogram") endif this = __initArduino__ (this, port, board); 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 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.8.0/inst/@arduino/checkI2CAddress.m0000644000000000000000000000470314171012362017124 0ustar0000000000000000## 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.8.0/inst/@arduino/configurePin.m0000644000000000000000000001014614171012362016671 0ustar0000000000000000## 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.8.0/inst/@arduino/configurePinResource.m0000644000000000000000000001010414171012362020373 0ustar0000000000000000## 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.8.0/inst/@arduino/decrementResourceCount.m0000644000000000000000000000340314171012362020726 0ustar0000000000000000## 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.8.0/inst/@arduino/delete.m0000644000000000000000000000155514171012362015507 0ustar0000000000000000## 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.8.0/inst/@arduino/display.m0000644000000000000000000000450714171012362015712 0ustar0000000000000000## 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 {} {} display (@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 display (ar) printf ("%s = \n", inputname (1)); if isobject(ar.connected) printf (" arduino object with fields of: \n"); 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.8.0/inst/@arduino/getEndian.m0000644000000000000000000000226414171012362016141 0ustar0000000000000000## 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.8.0/inst/@arduino/getI2CTerminals.m0000644000000000000000000000301614171012362017173 0ustar0000000000000000## 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.8.0/inst/@arduino/getInterruptTerminals.m0000644000000000000000000000226314171012362020615 0ustar0000000000000000## 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.8.0/inst/@arduino/getLEDTerminals.m0000644000000000000000000000217414171012362017226 0ustar0000000000000000## 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.8.0/inst/@arduino/getMCU.m0000644000000000000000000000213514171012362015364 0ustar0000000000000000## 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.8.0/inst/@arduino/getPWMTerminals.m0000644000000000000000000000220414171012362017257 0ustar0000000000000000## 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.8.0/inst/@arduino/getPinAlias.m0000644000000000000000000000263114171012362016441 0ustar0000000000000000## 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.8.0/inst/@arduino/getPinInfo.m0000644000000000000000000000711014171012362016300 0ustar0000000000000000## 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.8.0/inst/@arduino/getPinsFromTerminals.m0000644000000000000000000000426514171012362020362 0ustar0000000000000000## 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.8.0/inst/@arduino/getResourceCount.m0000644000000000000000000000253114171012362017540 0ustar0000000000000000## 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.8.0/inst/@arduino/getResourceOwner.m0000644000000000000000000000276514171012362017553 0ustar0000000000000000## 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.8.0/inst/@arduino/getSPITerminals.m0000644000000000000000000000202314171012362017246 0ustar0000000000000000## 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.8.0/inst/@arduino/getServoTerminals.m0000644000000000000000000000205314171012362017714 0ustar0000000000000000## 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.8.0/inst/@arduino/getSharedResourceProperty.m0000644000000000000000000000323014171012362021420 0ustar0000000000000000## 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.8.0/inst/@arduino/getTerminalMode.m0000644000000000000000000000270314171012362017321 0ustar0000000000000000## 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.8.0/inst/@arduino/getTerminalsFromPins.m0000644000000000000000000000317114171012362020355 0ustar0000000000000000## 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.8.0/inst/@arduino/incrementResourceCount.m0000644000000000000000000000315314171012362020746 0ustar0000000000000000## 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.8.0/inst/@arduino/isTerminalAnalog.m0000644000000000000000000000332614171012362017474 0ustar0000000000000000## 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.8.0/inst/@arduino/isTerminalDigital.m0000644000000000000000000000342214171012362017645 0ustar0000000000000000## 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.8.0/inst/@arduino/playTone.m0000644000000000000000000000560114171012362016034 0ustar0000000000000000## 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 = bitand(freq/256, hex2dec('FF')); freql = bitand(freq, hex2dec('FF')); duration = uint16(duration*10); durh = bitand(duration/256, hex2dec('FF')); 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.8.0/inst/@arduino/private/0000755000000000000000000000000014171012362015533 5ustar0000000000000000arduino-0.8.0/inst/@arduino/private/__digitalPin__.m0000644000000000000000000000332014171012362020567 0ustar0000000000000000## 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.8.0/inst/@arduino/private/__recvResponse__.m0000644000000000000000000000577314171012362021177 0ustar0000000000000000## 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. see ## . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} __recvResponse__ (@var{obj}, @var{lib}, @var{cmd}, @var{timeout}) ## Private function ## @end deftypefn function [dataOut, errcode] = __recvResponse__ (obj, libid, cmd, timeout) dataOut = []; errcode = 0; set(obj.connected, "timeout", timeout*10); # 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] = srl_read (obj.connected, 4); if (obj.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 (obj.debug) printf("* wait for response\n"); endif set(obj.connected, "timeout", -1); [tmpdataOut, tmpdataSize] = srl_read (obj.connected, 4); if (obj.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] = srl_read (obj.connected, expectlen); if (obj.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 obj.debug s = char(dataOut); printf("DEBUG: %s\n", s); endif [dataOut, errcode] = __recvResponse__ (obj, libid, cmd, timeout); else errcode = 0; # all is good endif endif endfunction arduino-0.8.0/inst/@arduino/private/__sendCommand__.m0000644000000000000000000000360114171012362020735 0ustar0000000000000000## 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} =} __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_serial") 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 set(obj.connected, "timeout", timeout*10); hdr = uint8([ hex2dec("A5") libid cmd numel(data)]); len = srl_write(obj.connected, [hdr data]); if (obj.debug) printf(">> "); printf("%d ", [hdr data]); printf("\n"); endif [dataOut, errcode] = __recvResponse__ (obj, libid, cmd, timeout); endfunction arduino-0.8.0/inst/@arduino/private/getTypeTerminals.m0000644000000000000000000000217514171012362021216 0ustar0000000000000000## 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.8.0/inst/@arduino/private/pinStateMode.m0000644000000000000000000000442714171012362020314 0ustar0000000000000000## 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.8.0/inst/@arduino/readAnalogPin.m0000644000000000000000000000462214171012362016747 0ustar0000000000000000## 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.8.0/inst/@arduino/readDigitalPin.m0000644000000000000000000000343114171012362017120 0ustar0000000000000000## 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.8.0/inst/@arduino/readVoltage.m0000644000000000000000000000371614171012362016503 0ustar0000000000000000## 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.8.0/inst/@arduino/reset.m0000644000000000000000000000235214171012362015363 0ustar0000000000000000## 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.8.0/inst/@arduino/sendCommand.m0000644000000000000000000000575314171012362016501 0ustar0000000000000000## 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.8.0/inst/@arduino/setSharedResourceProperty.m0000644000000000000000000000474114171012362021444 0ustar0000000000000000## 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.8.0/inst/@arduino/uptime.m0000644000000000000000000000340314171012362015542 0ustar0000000000000000## 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.8.0/inst/@arduino/validatePin.m0000644000000000000000000000411314171012362016476 0ustar0000000000000000## 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.8.0/inst/@arduino/version.m0000644000000000000000000000304314171012362015724 0ustar0000000000000000## 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.8.0/inst/@arduino/writeDigitalPin.m0000644000000000000000000000413114171012362017335 0ustar0000000000000000## 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.8.0/inst/@arduino/writePWMDutyCycle.m0000644000000000000000000000505414171012362017607 0ustar0000000000000000## 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.8.0/inst/@arduino/writePWMVoltage.m0000644000000000000000000000411214171012362017275 0ustar0000000000000000## 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.8.0/inst/@device/0000755000000000000000000000000014171012362013657 5ustar0000000000000000arduino-0.8.0/inst/@device/delete.m0000644000000000000000000000434414171012362015304 0ustar0000000000000000## 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.8.0/inst/@device/device.m0000644000000000000000000004344414171012362015305 0ustar0000000000000000## 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.8.0/inst/@device/display.m0000644000000000000000000000410414171012362015501 0ustar0000000000000000## 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 {} {} display (@var{dev}) ## Display device object. ## ## @subsubheading Inputs ## @var{dev} - device object to display ## ## @seealso{device} ## @end deftypefn function display (this) printf ("%s = \n", inputname (1)); 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.8.0/inst/@device/flush.m0000644000000000000000000000332014171012362015154 0ustar0000000000000000## 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.8.0/inst/@device/private/0000755000000000000000000000000014171012362015331 5ustar0000000000000000arduino-0.8.0/inst/@device/private/__getBytesAvailable__.m0000644000000000000000000000176014171012362021676 0ustar0000000000000000## 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.8.0/inst/@device/read.m0000644000000000000000000000566514171012362014764 0ustar0000000000000000## 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.8.0/inst/@device/readRegister.m0000644000000000000000000000654314171012362016465 0ustar0000000000000000## 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.8.0/inst/@device/subsasgn.m0000644000000000000000000000254314171012362015666 0ustar0000000000000000## 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.8.0/inst/@device/subsref.m0000644000000000000000000000760714171012362015520 0ustar0000000000000000## 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.8.0/inst/@device/write.m0000644000000000000000000000556314171012362015200 0ustar0000000000000000## 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.8.0/inst/@device/writeRead.m0000644000000000000000000000373414171012362015772 0ustar0000000000000000## 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.8.0/inst/@device/writeRegister.m0000644000000000000000000000621414171012362016677 0ustar0000000000000000## 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.8.0/inst/@i2cdev/0000755000000000000000000000000014171012362013574 5ustar0000000000000000arduino-0.8.0/inst/@i2cdev/delete.m0000644000000000000000000000147214171012362015220 0ustar0000000000000000## 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.8.0/inst/@i2cdev/display.m0000644000000000000000000000230014171012362015412 0ustar0000000000000000## 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 {} {} display (@var{dev}) ## Display i2cdev object. ## ## @subsubheading Inputs ## @var{dev} - i2cdev object ## ## @seealso{i2cdev} ## @end deftypefn function display (p) printf ("%s = \n", inputname (1)); 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.8.0/inst/@i2cdev/i2cdev.m0000644000000000000000000001277714171012362015144 0ustar0000000000000000## 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.8.0/inst/@i2cdev/read.m0000644000000000000000000000515114171012362014667 0ustar0000000000000000## 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.8.0/inst/@i2cdev/readRegister.m0000644000000000000000000000671014171012362016376 0ustar0000000000000000## 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.8.0/inst/@i2cdev/subsref.m0000644000000000000000000000267114171012362015431 0ustar0000000000000000## 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.8.0/inst/@i2cdev/write.m0000644000000000000000000000522414171012362015107 0ustar0000000000000000## 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.8.0/inst/@i2cdev/writeRegister.m0000644000000000000000000000624414171012362016617 0ustar0000000000000000## 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.8.0/inst/@rotaryEncoder/0000755000000000000000000000000014171012362015240 5ustar0000000000000000arduino-0.8.0/inst/@rotaryEncoder/delete.m0000644000000000000000000000226414171012362016664 0ustar0000000000000000## 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.8.0/inst/@rotaryEncoder/display.m0000644000000000000000000000220214171012362017057 0ustar0000000000000000## 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} =} display (@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 = display (obj) printf ("%s = \n", inputname (1)); 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.8.0/inst/@rotaryEncoder/readCount.m0000644000000000000000000000501314171012362017341 0ustar0000000000000000## 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.8.0/inst/@rotaryEncoder/readSpeed.m0000644000000000000000000000315514171012362017316 0ustar0000000000000000## 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.8.0/inst/@rotaryEncoder/resetCount.m0000644000000000000000000000305214171012362017551 0ustar0000000000000000## 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.8.0/inst/@rotaryEncoder/rotaryEncoder.m0000644000000000000000000001114214171012362020235 0ustar0000000000000000## 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.8.0/inst/@rotaryEncoder/subsref.m0000644000000000000000000000277414171012362017101 0ustar0000000000000000## 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.8.0/inst/@servo/0000755000000000000000000000000014171012362013556 5ustar0000000000000000arduino-0.8.0/inst/@servo/delete.m0000644000000000000000000000215114171012362015175 0ustar0000000000000000## 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.8.0/inst/@servo/display.m0000644000000000000000000000206614171012362015405 0ustar0000000000000000## 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 {} {} display (@var{dev}) ## Display servo object. ## ## @subsubheading Inputs ## @var{dev} - device to display ## ## @seealso{servo} ## @end deftypefn function display (this) printf ("%s = \n", inputname (1)); 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.8.0/inst/@servo/private/0000755000000000000000000000000014171012362015230 5ustar0000000000000000arduino-0.8.0/inst/@servo/private/__servoPosition__.m0000644000000000000000000000321714171012362021070 0ustar0000000000000000## 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.8.0/inst/@servo/readPosition.m0000644000000000000000000000252414171012362016377 0ustar0000000000000000## 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.8.0/inst/@servo/servo.m0000644000000000000000000001077214171012362015101 0ustar0000000000000000## 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.8.0/inst/@servo/subsref.m0000644000000000000000000000315414171012362015410 0ustar0000000000000000## 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.8.0/inst/@servo/writePosition.m0000644000000000000000000000270014171012362016612 0ustar0000000000000000## 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.8.0/inst/@shiftRegister/0000755000000000000000000000000014171012362015242 5ustar0000000000000000arduino-0.8.0/inst/@shiftRegister/delete.m0000644000000000000000000000227214171012362016665 0ustar0000000000000000## 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.8.0/inst/@shiftRegister/display.m0000644000000000000000000000222114171012362017062 0ustar0000000000000000## 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} =} display (@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 retval = display (register) printf ("%s = \n", inputname (1)); 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.8.0/inst/@shiftRegister/read.m0000644000000000000000000000461414171012362016340 0ustar0000000000000000## 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.8.0/inst/@shiftRegister/reset.m0000644000000000000000000000224414171012362016544 0ustar0000000000000000## 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.8.0/inst/@shiftRegister/shiftRegister.m0000644000000000000000000001462014171012362020245 0ustar0000000000000000## 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.8.0/inst/@shiftRegister/subsref.m0000644000000000000000000000301614171012362017071 0ustar0000000000000000## 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.8.0/inst/@shiftRegister/write.m0000644000000000000000000000512014171012362016550 0ustar0000000000000000## 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.8.0/inst/@spidev/0000755000000000000000000000000014171012362013712 5ustar0000000000000000arduino-0.8.0/inst/@spidev/delete.m0000644000000000000000000000335514171012362015340 0ustar0000000000000000## 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.8.0/inst/@spidev/display.m0000644000000000000000000000236614171012362015544 0ustar0000000000000000## 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 {} {} display (@var{dev}) ## Display spidev object. ## ## @subsubheading Inputs ## @var{dev} - spidev object to display ## ## @seealso{spidev} ## @end deftypefn function display (this) printf ("%s = \n", inputname (1)); 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.8.0/inst/@spidev/spidev.m0000644000000000000000000001777714171012362015405 0ustar0000000000000000## 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.8.0/inst/@spidev/subsref.m0000644000000000000000000000325614171012362015547 0ustar0000000000000000## 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.8.0/inst/@spidev/writeRead.m0000644000000000000000000000343314171012362016021 0ustar0000000000000000## 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.8.0/inst/@ultrasonic/0000755000000000000000000000000014171012362014603 5ustar0000000000000000arduino-0.8.0/inst/@ultrasonic/delete.m0000644000000000000000000000223314171012362016223 0ustar0000000000000000## 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.8.0/inst/@ultrasonic/display.m0000644000000000000000000000205314171012362016426 0ustar0000000000000000## 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 {} {} display (@var{dev}) ## Display ultrasonic object. ## ## @subsubheading Inputs ## @var{dev} - ultrasonic object to display ## ## @seealso{ultrasonic} ## @end deftypefn function display (this) printf ("%s = \n", inputname (1)); 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.8.0/inst/@ultrasonic/readDistance.m0000644000000000000000000000315014171012362017346 0ustar0000000000000000## 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.8.0/inst/@ultrasonic/readEchoTime.m0000644000000000000000000000317214171012362017315 0ustar0000000000000000## 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.8.0/inst/@ultrasonic/subsref.m0000644000000000000000000000317014171012362016433 0ustar0000000000000000## 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.8.0/inst/@ultrasonic/ultrasonic.m0000644000000000000000000001251314171012362017146 0ustar0000000000000000## 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.8.0/inst/addon.m0000644000000000000000000000605014171012362013564 0ustar0000000000000000## 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.8.0/inst/arduino_bistsetup.m0000644000000000000000000000704614171012362016250 0ustar0000000000000000## 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.8.0/inst/arduinosetup.m0000644000000000000000000001700314171012362015221 0ustar0000000000000000## 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 attempt to find the binary itself. ## @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; 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, "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, "// 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 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__ (); 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.8.0/inst/examples/0000755000000000000000000000000014171012362014136 5ustar0000000000000000arduino-0.8.0/inst/examples/example_blink.m0000644000000000000000000000206614171012362017132 0ustar0000000000000000## 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.8.0/inst/examples/example_i2c_eeprom.m0000644000000000000000000000536214171012362020061 0ustar0000000000000000## 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.8.0/inst/examples/example_i2c_tempsensor.m0000644000000000000000000000636614171012362020776 0ustar0000000000000000## 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.8.0/inst/examples/example_i2c_tempsensor_plot.m0000644000000000000000000001000114171012362022011 0ustar0000000000000000## 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.8.0/inst/examples/example_lcd_plugin.m0000644000000000000000000000250014171012362020144 0ustar0000000000000000## 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.8.0/inst/examples/example_shiftreg_595.m0000644000000000000000000000251514171012362020247 0ustar0000000000000000## 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.8.0/inst/examples/example_spi_mcp3002.m0000644000000000000000000000412614171012362017771 0ustar0000000000000000## 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.8.0/inst/examples/example_sweep_servo.m0000644000000000000000000000257614171012362020402 0ustar0000000000000000## 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.8.0/inst/isarduino.m0000644000000000000000000000264714171012362014504 0ustar0000000000000000## 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.8.0/inst/listArduinoLibraries.m0000644000000000000000000000557314171012362016642 0ustar0000000000000000## 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.8.0/inst/private/0000755000000000000000000000000014171012362013772 5ustar0000000000000000arduino-0.8.0/inst/private/__addons__.m0000644000000000000000000000715414171012362016223 0ustar0000000000000000## 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) 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 endfunction arduino-0.8.0/inst/private/__arduino_binary__.m0000644000000000000000000000706714171012362017763 0ustar0000000000000000## 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; endif retval = arduino_binary; endfunction function arduino_binary = find_arduino_binary () # use arduino_debug.exe in windoze ? binary_name = "arduino"; arduino_binary = ""; 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 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"); endif endfunction arduino-0.8.0/inst/scanForArduinos.m0000644000000000000000000001251514171012362015602 0ustar0000000000000000## 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 (@var{maxCount}) ## @deftypefnx {} {@var{retval} =} scanForArduinos (@var{"debug"}) ## @deftypefnx {} {@var{retval} =} scanForArduinos (@var{maxCount}, @var{type}) ## Scan system for programmed 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. ## ## @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 (maxCount, typestr) arduinos = {}; ARDUINO_INIT_COMMAND = 1; debug_flag = false; if nargin > 2 print_usage (); elseif nargin == 1 typestr = ""; elseif nargin == 0 maxCount = 0; typestr = ""; endif if ischar (maxCount) && strcmpi(maxCount, "debug") if nargin > 1 error ("scanForArduinos allows no additional arguments for 'debug'"); endif maxCount = 0; debug_flag = true; endif if ! isnumeric (maxCount) 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 # get list of serial ports to try ports = instrhwinfo ('serial'); for i = 1:numel (ports) try s = {}; unwind_protect if isunix portname = ports{i}; if portname(1) != "/" portname = ["/dev/" ports{i}]; endif elseif ispc # use extended port name portname = [ "\\\\.\\" ports{i}]; else portname = ports{i}; endif if debug_flag printf("* trying comport %s\n", portname); endif s = serial (portname, 9600, 1); pause(2); hdr = uint8 ([ hex2dec("A5") 0 ARDUINO_INIT_COMMAND 0]); if debug_flag printf(" >> "); printf("%02X ", hdr); printf("\n"); endif len = srl_write (s, hdr); [tmpdataOut, tmpdataSize] = srl_read (s, 4); if debug_flag printf(" << "); printf("%02X ", tmpdataOut); printf("\n"); endif if tmpdataSize == 4 && tmpdataOut(1) == hex2dec("A5") && tmpdataOut(2) == 0 && tmpdataOut(3) == ARDUINO_INIT_COMMAND && tmpdataOut(4) >= 5 expectlen = tmpdataOut(4); [dataout, datasize] = srl_read (s, expectlen); if debug_flag printf(" << "); printf("%02X ", dataout); printf("\n"); endif if datasize == expectlen # init returns the following info sig = (uint32 (dataout(1))*256*256) + (uint32 (dataout(2))*256) + uint32 (dataout(3)); board = dataout(4); voltref = double (dataout(5))/10.0; if isempty (typestr) || strcmpi(arduinoio.boardTypeString (board), typestr) info = {}; info.port = portname; info.board = arduinoio.boardTypeString (board); arduinos{end+1} = info; if debug_flag printf(" ** found board %s\n", info.board); endif if numel (arduinos) == maxCount break; endif endif endif endif unwind_protect_cleanup if !isempty (s) srl_close (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 %! arduinos = scanForArduinos(1, "madeuparduinoname"); %! assert(isempty(arduinos)); arduino-0.8.0/inst/scanI2Cbus.m0000644000000000000000000000432114171012362014432 0ustar0000000000000000## 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.8.0/octave-arduino.metainfo.xml0000644000000000000000000000225414171012362016611 0ustar0000000000000000 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.8.0/test/0000755000000000000000000000000014171012362012322 5ustar0000000000000000arduino-0.8.0/test/make_conf.m0000644000000000000000000001350314171012362014424 0ustar0000000000000000## 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.board = '';\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.8.0/test/test_exampleplugin.m0000644000000000000000000000152214171012362016411 0ustar0000000000000000## 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.8.0/test/test_jig.m0000644000000000000000000002354114171012362014315 0ustar0000000000000000## 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