From f0ca8c4da4bebdb83c60dc57ce02d0831eec6a7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Laboissi=C3=A8re?= Date: Fri, 7 May 2021 14:11:32 -0300 Subject: Import octave-arduino_0.7.0.orig.tar.gz [dgit import orig octave-arduino_0.7.0.orig.tar.gz] --- COPYING | 674 ++++ DESCRIPTION | 14 + INDEX | 143 + NEWS | 141 + README.md | 124 + doc/arduino.pdf | Bin 0 -> 368502 bytes doc/arduino.texi | 1036 ++++++ doc/functions.texi | 3605 ++++++++++++++++++++ doc/gpl.texi | 718 ++++ doc/macros.texi | 117 + inst/+arduinoio/+config/config_due.m | 123 + inst/+arduinoio/+config/config_leonardo.m | 68 + inst/+arduinoio/+config/config_lilypad.m | 38 + inst/+arduinoio/+config/config_mega2560.m | 108 + inst/+arduinoio/+config/config_micro.m | 66 + inst/+arduinoio/+config/config_mkrzero.m | 66 + inst/+arduinoio/+config/config_nano.m | 60 + inst/+arduinoio/+config/config_nano_33_ble.m | 52 + inst/+arduinoio/+config/config_nano_every.m | 59 + inst/+arduinoio/+config/config_promicro.m | 70 + inst/+arduinoio/+config/config_promini.m | 81 + inst/+arduinoio/+config/config_sparkfunsamd21.m | 64 + inst/+arduinoio/+config/config_uno.m | 80 + inst/+arduinoio/+config/config_uno_wifi_r2.m | 104 + inst/+arduinoio/+config/pin_info.m | 31 + inst/+arduinoio/AddonBase.m | 57 + inst/+arduinoio/FilePath.m | 30 + inst/+arduinoio/LibFiles.m | 32 + inst/+arduinoio/LibraryBase.m | 137 + inst/+arduinoio/boardTypeString.m | 72 + inst/+arduinoio/getBoardConfig.m | 37 + inst/+arduinoio/lib/LibraryBase.cpp | 257 ++ inst/+arduinoio/lib/LibraryBase.h | 100 + inst/+arduinoio/lib/OctaveCoreLibrary.cpp | 355 ++ inst/+arduinoio/lib/OctaveCoreLibrary.h | 28 + inst/+arduinoio/lib/OctaveI2CLibrary.cpp | 407 +++ inst/+arduinoio/lib/OctaveI2CLibrary.h | 27 + inst/+arduinoio/lib/OctaveRotaryEncoderLibrary.cpp | 318 ++ inst/+arduinoio/lib/OctaveRotaryEncoderLibrary.h | 29 + inst/+arduinoio/lib/OctaveSPILibrary.cpp | 230 ++ inst/+arduinoio/lib/OctaveSPILibrary.h | 27 + inst/+arduinoio/lib/OctaveSerialLibrary.cpp | 296 ++ inst/+arduinoio/lib/OctaveSerialLibrary.h | 28 + inst/+arduinoio/lib/OctaveServoLibrary.cpp | 85 + inst/+arduinoio/lib/OctaveServoLibrary.h | 27 + inst/+arduinoio/lib/OctaveShiftRegisterLibrary.cpp | 451 +++ inst/+arduinoio/lib/OctaveShiftRegisterLibrary.h | 27 + inst/+arduinoio/lib/OctaveUltrasonicLibrary.cpp | 206 ++ inst/+arduinoio/lib/OctaveUltrasonicLibrary.h | 27 + inst/+arduinoio/lib/octave.ino | 89 + inst/+arduinoioaddons/+EEPRomAddon/EEPRom.m | 173 + inst/+arduinoioaddons/+EEPRomAddon/EEPRomAddon.h | 100 + inst/+arduinoioaddons/+ExampleAddon/Echo.m | 82 + inst/+arduinoioaddons/+ExampleAddon/src/Echo.h | 50 + inst/+arduinoioaddons/+ExampleLCD/LCD.m | 229 ++ inst/+arduinoioaddons/+ExampleLCD/LCDAddon.h | 139 + inst/+arduinoioaddons/+RTCAddon/DS1307.m | 276 ++ inst/+arduinoioaddons/+RTCAddon/DS1307Addon.h | 47 + inst/+arduinoioaddons/+adafruit/dcmotorv2.m | 172 + inst/+arduinoioaddons/+adafruit/motorshieldv2.h | 303 ++ inst/+arduinoioaddons/+adafruit/motorshieldv2.m | 238 ++ inst/+arduinoioaddons/+adafruit/stepper.m | 223 ++ inst/+arduinosensor/DS1307.m | 262 ++ inst/+arduinosensor/GUVAS12SD.m | 139 + inst/+arduinosensor/MPC3002.m | 144 + inst/+arduinosensor/SI7021.m | 217 ++ inst/@arduino/__freeArduino__.m | 28 + inst/@arduino/__initArduino__.m | 101 + inst/@arduino/arduino.m | 436 +++ inst/@arduino/checkI2CAddress.m | 84 + inst/@arduino/configurePin.m | 140 + inst/@arduino/configurePinResource.m | 126 + inst/@arduino/decrementResourceCount.m | 56 + inst/@arduino/delete.m | 29 + inst/@arduino/display.m | 83 + inst/@arduino/getI2CTerminals.m | 52 + inst/@arduino/getInterruptTerminals.m | 40 + inst/@arduino/getLEDTerminals.m | 39 + inst/@arduino/getMCU.m | 35 + inst/@arduino/getPWMTerminals.m | 41 + inst/@arduino/getPinAlias.m | 54 + inst/@arduino/getPinInfo.m | 141 + inst/@arduino/getPinsFromTerminals.m | 72 + inst/@arduino/getResourceCount.m | 45 + inst/@arduino/getResourceOwner.m | 49 + inst/@arduino/getSPITerminals.m | 34 + inst/@arduino/getServoTerminals.m | 34 + inst/@arduino/getSharedResourceProperty.m | 52 + inst/@arduino/getTerminalMode.m | 46 + inst/@arduino/getTerminalsFromPins.m | 51 + inst/@arduino/incrementResourceCount.m | 51 + inst/@arduino/isTerminalAnalog.m | 59 + inst/@arduino/isTerminalDigital.m | 60 + inst/@arduino/playTone.m | 97 + inst/@arduino/private/__digitalPin__.m | 68 + inst/@arduino/private/__recvResponse__.m | 96 + inst/@arduino/private/__sendCommand__.m | 64 + inst/@arduino/private/getTypeTerminals.m | 36 + inst/@arduino/private/pinStateMode.m | 74 + inst/@arduino/readAnalogPin.m | 90 + inst/@arduino/readDigitalPin.m | 61 + inst/@arduino/readVoltage.m | 71 + inst/@arduino/reset.m | 42 + inst/@arduino/sendCommand.m | 97 + inst/@arduino/setSharedResourceProperty.m | 80 + inst/@arduino/uptime.m | 59 + inst/@arduino/validatePin.m | 80 + inst/@arduino/version.m | 52 + inst/@arduino/writeDigitalPin.m | 69 + inst/@arduino/writePWMDutyCycle.m | 93 + inst/@arduino/writePWMVoltage.m | 73 + inst/@device/delete.m | 80 + inst/@device/device.m | 528 +++ inst/@device/display.m | 56 + inst/@device/flush.m | 56 + inst/@device/private/__getBytesAvailable__.m | 28 + inst/@device/read.m | 93 + inst/@device/readRegister.m | 111 + inst/@device/subsasgn.m | 44 + inst/@device/subsref.m | 150 + inst/@device/write.m | 86 + inst/@device/writeRead.m | 72 + inst/@device/writeRegister.m | 96 + inst/@i2cdev/delete.m | 25 + inst/@i2cdev/display.m | 36 + inst/@i2cdev/i2cdev.m | 191 ++ inst/@i2cdev/read.m | 82 + inst/@i2cdev/readRegister.m | 107 + inst/@i2cdev/subsref.m | 55 + inst/@i2cdev/write.m | 78 + inst/@i2cdev/writeRegister.m | 92 + inst/@rotaryEncoder/delete.m | 43 + inst/@rotaryEncoder/display.m | 33 + inst/@rotaryEncoder/readCount.m | 77 + inst/@rotaryEncoder/readSpeed.m | 48 + inst/@rotaryEncoder/resetCount.m | 51 + inst/@rotaryEncoder/rotaryEncoder.m | 167 + inst/@rotaryEncoder/subsref.m | 57 + inst/@servo/delete.m | 38 + inst/@servo/display.m | 29 + inst/@servo/private/__servoPosition__.m | 49 + inst/@servo/readPosition.m | 45 + inst/@servo/servo.m | 157 + inst/@servo/subsref.m | 62 + inst/@servo/writePosition.m | 51 + inst/@shiftRegister/delete.m | 42 + inst/@shiftRegister/display.m | 33 + inst/@shiftRegister/read.m | 74 + inst/@shiftRegister/reset.m | 31 + inst/@shiftRegister/shiftRegister.m | 204 ++ inst/@shiftRegister/subsref.m | 57 + inst/@shiftRegister/write.m | 86 + inst/@spidev/delete.m | 57 + inst/@spidev/display.m | 36 + inst/@spidev/spidev.m | 263 ++ inst/@spidev/subsref.m | 65 + inst/@spidev/writeRead.m | 64 + inst/@ultrasonic/delete.m | 40 + inst/@ultrasonic/display.m | 31 + inst/@ultrasonic/readDistance.m | 54 + inst/@ultrasonic/readEchoTime.m | 53 + inst/@ultrasonic/subsref.m | 64 + inst/@ultrasonic/ultrasonic.m | 179 + inst/addon.m | 94 + inst/arduino_bistsetup.m | 111 + inst/arduinosetup.m | 244 ++ inst/examples/example_blink.m | 34 + inst/examples/example_i2c_eeprom.m | 105 + inst/examples/example_i2c_tempsensor.m | 118 + inst/examples/example_i2c_tempsensor_plot.m | 154 + inst/examples/example_lcd_plugin.m | 40 + inst/examples/example_shiftreg_595.m | 38 + inst/examples/example_spi_mcp3002.m | 67 + inst/examples/example_sweep_servo.m | 50 + inst/isarduino.m | 49 + inst/listArduinoLibraries.m | 92 + inst/private/__addons__.m | 91 + inst/private/__arduino_binary__.m | 118 + inst/scanForArduinos.m | 177 + inst/scanI2Cbus.m | 81 + octave-arduino.metainfo.xml | 31 + test/make_conf.m | 203 ++ test/test_exampleplugin.m | 21 + test/test_jig.m | 392 +++ 184 files changed, 23871 insertions(+) create mode 100644 COPYING create mode 100644 DESCRIPTION create mode 100644 INDEX create mode 100644 NEWS create mode 100644 README.md create mode 100644 doc/arduino.pdf create mode 100644 doc/arduino.texi create mode 100644 doc/functions.texi create mode 100644 doc/gpl.texi create mode 100644 doc/macros.texi create mode 100644 inst/+arduinoio/+config/config_due.m create mode 100644 inst/+arduinoio/+config/config_leonardo.m create mode 100644 inst/+arduinoio/+config/config_lilypad.m create mode 100644 inst/+arduinoio/+config/config_mega2560.m create mode 100644 inst/+arduinoio/+config/config_micro.m create mode 100644 inst/+arduinoio/+config/config_mkrzero.m create mode 100644 inst/+arduinoio/+config/config_nano.m create mode 100644 inst/+arduinoio/+config/config_nano_33_ble.m create mode 100644 inst/+arduinoio/+config/config_nano_every.m create mode 100644 inst/+arduinoio/+config/config_promicro.m create mode 100644 inst/+arduinoio/+config/config_promini.m create mode 100644 inst/+arduinoio/+config/config_sparkfunsamd21.m create mode 100644 inst/+arduinoio/+config/config_uno.m create mode 100644 inst/+arduinoio/+config/config_uno_wifi_r2.m create mode 100644 inst/+arduinoio/+config/pin_info.m create mode 100644 inst/+arduinoio/AddonBase.m create mode 100644 inst/+arduinoio/FilePath.m create mode 100644 inst/+arduinoio/LibFiles.m create mode 100644 inst/+arduinoio/LibraryBase.m create mode 100644 inst/+arduinoio/boardTypeString.m create mode 100644 inst/+arduinoio/getBoardConfig.m create mode 100644 inst/+arduinoio/lib/LibraryBase.cpp create mode 100644 inst/+arduinoio/lib/LibraryBase.h create mode 100644 inst/+arduinoio/lib/OctaveCoreLibrary.cpp create mode 100644 inst/+arduinoio/lib/OctaveCoreLibrary.h create mode 100644 inst/+arduinoio/lib/OctaveI2CLibrary.cpp create mode 100644 inst/+arduinoio/lib/OctaveI2CLibrary.h create mode 100644 inst/+arduinoio/lib/OctaveRotaryEncoderLibrary.cpp create mode 100644 inst/+arduinoio/lib/OctaveRotaryEncoderLibrary.h create mode 100644 inst/+arduinoio/lib/OctaveSPILibrary.cpp create mode 100644 inst/+arduinoio/lib/OctaveSPILibrary.h create mode 100644 inst/+arduinoio/lib/OctaveSerialLibrary.cpp create mode 100644 inst/+arduinoio/lib/OctaveSerialLibrary.h create mode 100644 inst/+arduinoio/lib/OctaveServoLibrary.cpp create mode 100644 inst/+arduinoio/lib/OctaveServoLibrary.h create mode 100644 inst/+arduinoio/lib/OctaveShiftRegisterLibrary.cpp create mode 100644 inst/+arduinoio/lib/OctaveShiftRegisterLibrary.h create mode 100644 inst/+arduinoio/lib/OctaveUltrasonicLibrary.cpp create mode 100644 inst/+arduinoio/lib/OctaveUltrasonicLibrary.h create mode 100644 inst/+arduinoio/lib/octave.ino create mode 100644 inst/+arduinoioaddons/+EEPRomAddon/EEPRom.m create mode 100644 inst/+arduinoioaddons/+EEPRomAddon/EEPRomAddon.h create mode 100644 inst/+arduinoioaddons/+ExampleAddon/Echo.m create mode 100644 inst/+arduinoioaddons/+ExampleAddon/src/Echo.h create mode 100644 inst/+arduinoioaddons/+ExampleLCD/LCD.m create mode 100644 inst/+arduinoioaddons/+ExampleLCD/LCDAddon.h create mode 100644 inst/+arduinoioaddons/+RTCAddon/DS1307.m create mode 100644 inst/+arduinoioaddons/+RTCAddon/DS1307Addon.h create mode 100644 inst/+arduinoioaddons/+adafruit/dcmotorv2.m create mode 100644 inst/+arduinoioaddons/+adafruit/motorshieldv2.h create mode 100644 inst/+arduinoioaddons/+adafruit/motorshieldv2.m create mode 100644 inst/+arduinoioaddons/+adafruit/stepper.m create mode 100644 inst/+arduinosensor/DS1307.m create mode 100644 inst/+arduinosensor/GUVAS12SD.m create mode 100644 inst/+arduinosensor/MPC3002.m create mode 100644 inst/+arduinosensor/SI7021.m create mode 100644 inst/@arduino/__freeArduino__.m create mode 100644 inst/@arduino/__initArduino__.m create mode 100644 inst/@arduino/arduino.m create mode 100644 inst/@arduino/checkI2CAddress.m create mode 100644 inst/@arduino/configurePin.m create mode 100644 inst/@arduino/configurePinResource.m create mode 100644 inst/@arduino/decrementResourceCount.m create mode 100644 inst/@arduino/delete.m create mode 100644 inst/@arduino/display.m create mode 100644 inst/@arduino/getI2CTerminals.m create mode 100644 inst/@arduino/getInterruptTerminals.m create mode 100644 inst/@arduino/getLEDTerminals.m create mode 100644 inst/@arduino/getMCU.m create mode 100644 inst/@arduino/getPWMTerminals.m create mode 100644 inst/@arduino/getPinAlias.m create mode 100644 inst/@arduino/getPinInfo.m create mode 100644 inst/@arduino/getPinsFromTerminals.m create mode 100644 inst/@arduino/getResourceCount.m create mode 100644 inst/@arduino/getResourceOwner.m create mode 100644 inst/@arduino/getSPITerminals.m create mode 100644 inst/@arduino/getServoTerminals.m create mode 100644 inst/@arduino/getSharedResourceProperty.m create mode 100644 inst/@arduino/getTerminalMode.m create mode 100644 inst/@arduino/getTerminalsFromPins.m create mode 100644 inst/@arduino/incrementResourceCount.m create mode 100644 inst/@arduino/isTerminalAnalog.m create mode 100644 inst/@arduino/isTerminalDigital.m create mode 100644 inst/@arduino/playTone.m create mode 100644 inst/@arduino/private/__digitalPin__.m create mode 100644 inst/@arduino/private/__recvResponse__.m create mode 100644 inst/@arduino/private/__sendCommand__.m create mode 100644 inst/@arduino/private/getTypeTerminals.m create mode 100644 inst/@arduino/private/pinStateMode.m create mode 100644 inst/@arduino/readAnalogPin.m create mode 100644 inst/@arduino/readDigitalPin.m create mode 100644 inst/@arduino/readVoltage.m create mode 100644 inst/@arduino/reset.m create mode 100644 inst/@arduino/sendCommand.m create mode 100644 inst/@arduino/setSharedResourceProperty.m create mode 100644 inst/@arduino/uptime.m create mode 100644 inst/@arduino/validatePin.m create mode 100644 inst/@arduino/version.m create mode 100644 inst/@arduino/writeDigitalPin.m create mode 100644 inst/@arduino/writePWMDutyCycle.m create mode 100644 inst/@arduino/writePWMVoltage.m create mode 100644 inst/@device/delete.m create mode 100644 inst/@device/device.m create mode 100644 inst/@device/display.m create mode 100644 inst/@device/flush.m create mode 100644 inst/@device/private/__getBytesAvailable__.m create mode 100644 inst/@device/read.m create mode 100644 inst/@device/readRegister.m create mode 100644 inst/@device/subsasgn.m create mode 100644 inst/@device/subsref.m create mode 100644 inst/@device/write.m create mode 100644 inst/@device/writeRead.m create mode 100644 inst/@device/writeRegister.m create mode 100644 inst/@i2cdev/delete.m create mode 100644 inst/@i2cdev/display.m create mode 100644 inst/@i2cdev/i2cdev.m create mode 100644 inst/@i2cdev/read.m create mode 100644 inst/@i2cdev/readRegister.m create mode 100644 inst/@i2cdev/subsref.m create mode 100644 inst/@i2cdev/write.m create mode 100644 inst/@i2cdev/writeRegister.m create mode 100644 inst/@rotaryEncoder/delete.m create mode 100644 inst/@rotaryEncoder/display.m create mode 100644 inst/@rotaryEncoder/readCount.m create mode 100644 inst/@rotaryEncoder/readSpeed.m create mode 100644 inst/@rotaryEncoder/resetCount.m create mode 100644 inst/@rotaryEncoder/rotaryEncoder.m create mode 100644 inst/@rotaryEncoder/subsref.m create mode 100644 inst/@servo/delete.m create mode 100644 inst/@servo/display.m create mode 100644 inst/@servo/private/__servoPosition__.m create mode 100644 inst/@servo/readPosition.m create mode 100644 inst/@servo/servo.m create mode 100644 inst/@servo/subsref.m create mode 100644 inst/@servo/writePosition.m create mode 100644 inst/@shiftRegister/delete.m create mode 100644 inst/@shiftRegister/display.m create mode 100644 inst/@shiftRegister/read.m create mode 100644 inst/@shiftRegister/reset.m create mode 100644 inst/@shiftRegister/shiftRegister.m create mode 100644 inst/@shiftRegister/subsref.m create mode 100644 inst/@shiftRegister/write.m create mode 100644 inst/@spidev/delete.m create mode 100644 inst/@spidev/display.m create mode 100644 inst/@spidev/spidev.m create mode 100644 inst/@spidev/subsref.m create mode 100644 inst/@spidev/writeRead.m create mode 100644 inst/@ultrasonic/delete.m create mode 100644 inst/@ultrasonic/display.m create mode 100644 inst/@ultrasonic/readDistance.m create mode 100644 inst/@ultrasonic/readEchoTime.m create mode 100644 inst/@ultrasonic/subsref.m create mode 100644 inst/@ultrasonic/ultrasonic.m create mode 100644 inst/addon.m create mode 100644 inst/arduino_bistsetup.m create mode 100644 inst/arduinosetup.m create mode 100644 inst/examples/example_blink.m create mode 100644 inst/examples/example_i2c_eeprom.m create mode 100644 inst/examples/example_i2c_tempsensor.m create mode 100644 inst/examples/example_i2c_tempsensor_plot.m create mode 100644 inst/examples/example_lcd_plugin.m create mode 100644 inst/examples/example_shiftreg_595.m create mode 100644 inst/examples/example_spi_mcp3002.m create mode 100644 inst/examples/example_sweep_servo.m create mode 100644 inst/isarduino.m create mode 100644 inst/listArduinoLibraries.m create mode 100644 inst/private/__addons__.m create mode 100644 inst/private/__arduino_binary__.m create mode 100644 inst/scanForArduinos.m create mode 100644 inst/scanI2Cbus.m create mode 100644 octave-arduino.metainfo.xml create mode 100644 test/make_conf.m create mode 100644 test/test_exampleplugin.m create mode 100644 test/test_jig.m diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/COPYING @@ -0,0 +1,674 @@ + 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 +. diff --git a/DESCRIPTION b/DESCRIPTION new file mode 100644 index 0000000..4808e4e --- /dev/null +++ b/DESCRIPTION @@ -0,0 +1,14 @@ +Name: arduino +Version: 0.7.0 +Date: 2021-04-28 +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/ diff --git a/INDEX b/INDEX new file mode 100644 index 0000000..8fb890a --- /dev/null +++ b/INDEX @@ -0,0 +1,143 @@ +arduino >> Arduino Toolkit +General Functions + arduinosetup + isarduino + listArduinoLibraries + scanForArduinos +Arduino Functions + @arduino/checkI2CAddress + @arduino/configurePin + @arduino/configurePinResource + @arduino/decrementResourceCount + @arduino/delete + @arduino/display + @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 +Test Functions + arduino_bistsetup diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..4e2b4e6 --- /dev/null +++ b/NEWS @@ -0,0 +1,141 @@ +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 + diff --git a/README.md b/README.md new file mode 100644 index 0000000..b5319f4 --- /dev/null +++ b/README.md @@ -0,0 +1,124 @@ +
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 + +* nano + +* nano every + +* nano 33 ble + +* promini + +* promicro + +* 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. diff --git a/doc/arduino.pdf b/doc/arduino.pdf new file mode 100644 index 0000000..9538a19 Binary files /dev/null and b/doc/arduino.pdf differ diff --git a/doc/arduino.texi b/doc/arduino.texi new file mode 100644 index 0000000..f6f30d4 --- /dev/null +++ b/doc/arduino.texi @@ -0,0 +1,1036 @@ +\input texinfo @c -*-texinfo-*- +@c Copyright (c) 2018-2021, John Donoghue +@c Octave Arduino - a somewhat Matlab compatible Arduino toolkit for GNU octave. + +@c For manually generating the documentation use +@c LANGUAGE=en makeinfo --html --no-split arduino.texi + +@c %*** Start of HEADER +@setfilename arduino.info +@settitle Arduino Toolkit - a somewhat Matlab compatible arduino toolkit for GNU octave. +@afourpaper +@paragraphindent 0 +@finalout +@set VERSION 0.7.0 +@set COPYRIGHT_DATE 2018-2021 +@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 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.} + +@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 Pro/Pro Mini +@item +Arduino Pro Micro +@item +Arduino Leonardo +@item +Arduino Micro +@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} +@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 diff --git a/doc/functions.texi b/doc/functions.texi new file mode 100644 index 0000000..a059960 --- /dev/null +++ b/doc/functions.texi @@ -0,0 +1,3605 @@ +@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/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 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 diff --git a/doc/gpl.texi b/doc/gpl.texi new file mode 100644 index 0000000..7afdb76 --- /dev/null +++ b/doc/gpl.texi @@ -0,0 +1,718 @@ +@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}. diff --git a/doc/macros.texi b/doc/macros.texi new file mode 100644 index 0000000..291bcc4 --- /dev/null +++ b/doc/macros.texi @@ -0,0 +1,117 @@ +@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 diff --git a/inst/+arduinoio/+config/config_due.m b/inst/+arduinoio/+config/config_due.m new file mode 100644 index 0000000..e3cf167 --- /dev/null +++ b/inst/+arduinoio/+config/config_due.m @@ -0,0 +1,123 @@ +## 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 diff --git a/inst/+arduinoio/+config/config_leonardo.m b/inst/+arduinoio/+config/config_leonardo.m new file mode 100644 index 0000000..e22eff7 --- /dev/null +++ b/inst/+arduinoio/+config/config_leonardo.m @@ -0,0 +1,68 @@ +## 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 diff --git a/inst/+arduinoio/+config/config_lilypad.m b/inst/+arduinoio/+config/config_lilypad.m new file mode 100644 index 0000000..4ed4751 --- /dev/null +++ b/inst/+arduinoio/+config/config_lilypad.m @@ -0,0 +1,38 @@ +# 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 diff --git a/inst/+arduinoio/+config/config_mega2560.m b/inst/+arduinoio/+config/config_mega2560.m new file mode 100644 index 0000000..caf43a0 --- /dev/null +++ b/inst/+arduinoio/+config/config_mega2560.m @@ -0,0 +1,108 @@ +## 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 diff --git a/inst/+arduinoio/+config/config_micro.m b/inst/+arduinoio/+config/config_micro.m new file mode 100644 index 0000000..fd24cb4 --- /dev/null +++ b/inst/+arduinoio/+config/config_micro.m @@ -0,0 +1,66 @@ +## 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 diff --git a/inst/+arduinoio/+config/config_mkrzero.m b/inst/+arduinoio/+config/config_mkrzero.m new file mode 100644 index 0000000..5802ff0 --- /dev/null +++ b/inst/+arduinoio/+config/config_mkrzero.m @@ -0,0 +1,66 @@ +## 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 diff --git a/inst/+arduinoio/+config/config_nano.m b/inst/+arduinoio/+config/config_nano.m new file mode 100644 index 0000000..8c349bb --- /dev/null +++ b/inst/+arduinoio/+config/config_nano.m @@ -0,0 +1,60 @@ +## 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 diff --git a/inst/+arduinoio/+config/config_nano_33_ble.m b/inst/+arduinoio/+config/config_nano_33_ble.m new file mode 100644 index 0000000..276defb --- /dev/null +++ b/inst/+arduinoio/+config/config_nano_33_ble.m @@ -0,0 +1,52 @@ +# 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 diff --git a/inst/+arduinoio/+config/config_nano_every.m b/inst/+arduinoio/+config/config_nano_every.m new file mode 100644 index 0000000..d6ba3b9 --- /dev/null +++ b/inst/+arduinoio/+config/config_nano_every.m @@ -0,0 +1,59 @@ +## 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 diff --git a/inst/+arduinoio/+config/config_promicro.m b/inst/+arduinoio/+config/config_promicro.m new file mode 100644 index 0000000..a1773f4 --- /dev/null +++ b/inst/+arduinoio/+config/config_promicro.m @@ -0,0 +1,70 @@ +## 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 diff --git a/inst/+arduinoio/+config/config_promini.m b/inst/+arduinoio/+config/config_promini.m new file mode 100644 index 0000000..8d7f2a8 --- /dev/null +++ b/inst/+arduinoio/+config/config_promini.m @@ -0,0 +1,81 @@ +## 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 diff --git a/inst/+arduinoio/+config/config_sparkfunsamd21.m b/inst/+arduinoio/+config/config_sparkfunsamd21.m new file mode 100644 index 0000000..e596a25 --- /dev/null +++ b/inst/+arduinoio/+config/config_sparkfunsamd21.m @@ -0,0 +1,64 @@ +## 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 diff --git a/inst/+arduinoio/+config/config_uno.m b/inst/+arduinoio/+config/config_uno.m new file mode 100644 index 0000000..a542ad4 --- /dev/null +++ b/inst/+arduinoio/+config/config_uno.m @@ -0,0 +1,80 @@ +## 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 diff --git a/inst/+arduinoio/+config/config_uno_wifi_r2.m b/inst/+arduinoio/+config/config_uno_wifi_r2.m new file mode 100644 index 0000000..24fedc5 --- /dev/null +++ b/inst/+arduinoio/+config/config_uno_wifi_r2.m @@ -0,0 +1,104 @@ +## 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 diff --git a/inst/+arduinoio/+config/pin_info.m b/inst/+arduinoio/+config/pin_info.m new file mode 100644 index 0000000..2ba37e1 --- /dev/null +++ b/inst/+arduinoio/+config/pin_info.m @@ -0,0 +1,31 @@ +## 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 diff --git a/inst/+arduinoio/AddonBase.m b/inst/+arduinoio/AddonBase.m new file mode 100644 index 0000000..b02f65e --- /dev/null +++ b/inst/+arduinoio/AddonBase.m @@ -0,0 +1,57 @@ +## 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 diff --git a/inst/+arduinoio/FilePath.m b/inst/+arduinoio/FilePath.m new file mode 100644 index 0000000..0c49130 --- /dev/null +++ b/inst/+arduinoio/FilePath.m @@ -0,0 +1,30 @@ +## 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 diff --git a/inst/+arduinoio/LibFiles.m b/inst/+arduinoio/LibFiles.m new file mode 100644 index 0000000..1bbeb7f --- /dev/null +++ b/inst/+arduinoio/LibFiles.m @@ -0,0 +1,32 @@ +## 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 diff --git a/inst/+arduinoio/LibraryBase.m b/inst/+arduinoio/LibraryBase.m new file mode 100644 index 0000000..48137fd --- /dev/null +++ b/inst/+arduinoio/LibraryBase.m @@ -0,0 +1,137 @@ +## 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 diff --git a/inst/+arduinoio/boardTypeString.m b/inst/+arduinoio/boardTypeString.m new file mode 100644 index 0000000..c5a0939 --- /dev/null +++ b/inst/+arduinoio/boardTypeString.m @@ -0,0 +1,72 @@ +## 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. 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 60 + retval = "nano_33_ble"; + 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") diff --git a/inst/+arduinoio/getBoardConfig.m b/inst/+arduinoio/getBoardConfig.m new file mode 100644 index 0000000..fbcd2b8 --- /dev/null +++ b/inst/+arduinoio/getBoardConfig.m @@ -0,0 +1,37 @@ +## 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"); diff --git a/inst/+arduinoio/lib/LibraryBase.cpp b/inst/+arduinoio/lib/LibraryBase.cpp new file mode 100644 index 0000000..5eb29a8 --- /dev/null +++ b/inst/+arduinoio/lib/LibraryBase.cpp @@ -0,0 +1,257 @@ +/* + * 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 + +const char ERRORMSG_INVALID_NUMBER_OF_ARGS[] PROGMEM = "Invalid number of args"; +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::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); + } + 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;i= 0 && idx < libcount) + { + return libs[idx]->libName.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 < 0 || libid >= MAX_ARDUINO_LIBS || libs[libid] == 0) + { + // error, send reply + } + else + { + libs[libid]->commandHandler(cmd, data,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(); + } +} + diff --git a/inst/+arduinoio/lib/LibraryBase.h b/inst/+arduinoio/lib/LibraryBase.h new file mode 100644 index 0000000..a210bfe --- /dev/null +++ b/inst/+arduinoio/lib/LibraryBase.h @@ -0,0 +1,100 @@ +/* + * 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) = 0; + 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 diff --git a/inst/+arduinoio/lib/OctaveCoreLibrary.cpp b/inst/+arduinoio/lib/OctaveCoreLibrary.cpp new file mode 100644 index 0000000..6cbb707 --- /dev/null +++ b/inst/+arduinoio/lib/OctaveCoreLibrary.cpp @@ -0,0 +1,355 @@ +/* + * 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 + +// 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_ARDUINO_NANO33BLE) + #define BOARD_ID 60 + #define NUM_TOTAL_PINS 34 +#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) + #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 + +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_UNIMPLEMENTED[] PROGMEM = "Unimplemented feature"; +const char ERRORMSG_INVALID_DEVICE[] PROGMEM = "Invalid device id"; + +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(int m) +{ + if (m >= 0 && 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) +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(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] >= 0 && 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; + } +} diff --git a/inst/+arduinoio/lib/OctaveCoreLibrary.h b/inst/+arduinoio/lib/OctaveCoreLibrary.h new file mode 100644 index 0000000..95ec6fc --- /dev/null +++ b/inst/+arduinoio/lib/OctaveCoreLibrary.h @@ -0,0 +1,28 @@ +/* + * 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); +}; + + diff --git a/inst/+arduinoio/lib/OctaveI2CLibrary.cpp b/inst/+arduinoio/lib/OctaveI2CLibrary.cpp new file mode 100644 index 0000000..ff4f6bd --- /dev/null +++ b/inst/+arduinoio/lib/OctaveI2CLibrary.cpp @@ -0,0 +1,407 @@ +/* + * 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; + // 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) + // 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; + } +} diff --git a/inst/+arduinoio/lib/OctaveI2CLibrary.h b/inst/+arduinoio/lib/OctaveI2CLibrary.h new file mode 100644 index 0000000..cb3dfd2 --- /dev/null +++ b/inst/+arduinoio/lib/OctaveI2CLibrary.h @@ -0,0 +1,27 @@ +/* + * 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); +}; + + diff --git a/inst/+arduinoio/lib/OctaveRotaryEncoderLibrary.cpp b/inst/+arduinoio/lib/OctaveRotaryEncoderLibrary.cpp new file mode 100644 index 0000000..1014153 --- /dev/null +++ b/inst/+arduinoio/lib/OctaveRotaryEncoderLibrary.cpp @@ -0,0 +1,318 @@ +/* + * 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 + +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}; + +#ifdef USE_ROTARYENCODER + +#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 +} diff --git a/inst/+arduinoio/lib/OctaveRotaryEncoderLibrary.h b/inst/+arduinoio/lib/OctaveRotaryEncoderLibrary.h new file mode 100644 index 0000000..2d7605c --- /dev/null +++ b/inst/+arduinoio/lib/OctaveRotaryEncoderLibrary.h @@ -0,0 +1,29 @@ +/* + * 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(); +}; + + diff --git a/inst/+arduinoio/lib/OctaveSPILibrary.cpp b/inst/+arduinoio/lib/OctaveSPILibrary.cpp new file mode 100644 index 0000000..6efe06b --- /dev/null +++ b/inst/+arduinoio/lib/OctaveSPILibrary.cpp @@ -0,0 +1,230 @@ +/* + * 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; + } +} diff --git a/inst/+arduinoio/lib/OctaveSPILibrary.h b/inst/+arduinoio/lib/OctaveSPILibrary.h new file mode 100644 index 0000000..f4a8d88 --- /dev/null +++ b/inst/+arduinoio/lib/OctaveSPILibrary.h @@ -0,0 +1,27 @@ +/* + * 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); +}; + + diff --git a/inst/+arduinoio/lib/OctaveSerialLibrary.cpp b/inst/+arduinoio/lib/OctaveSerialLibrary.cpp new file mode 100644 index 0000000..af88e5d --- /dev/null +++ b/inst/+arduinoio/lib/OctaveSerialLibrary.cpp @@ -0,0 +1,296 @@ +/* + * 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) +{ + int val; + + 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) + 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; + } +} diff --git a/inst/+arduinoio/lib/OctaveSerialLibrary.h b/inst/+arduinoio/lib/OctaveSerialLibrary.h new file mode 100644 index 0000000..57550f7 --- /dev/null +++ b/inst/+arduinoio/lib/OctaveSerialLibrary.h @@ -0,0 +1,28 @@ +/* + * 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); +}; + + diff --git a/inst/+arduinoio/lib/OctaveServoLibrary.cpp b/inst/+arduinoio/lib/OctaveServoLibrary.cpp new file mode 100644 index 0000000..6cde862 --- /dev/null +++ b/inst/+arduinoio/lib/OctaveServoLibrary.cpp @@ -0,0 +1,85 @@ +/* + * 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; + } +} diff --git a/inst/+arduinoio/lib/OctaveServoLibrary.h b/inst/+arduinoio/lib/OctaveServoLibrary.h new file mode 100644 index 0000000..e1b9275 --- /dev/null +++ b/inst/+arduinoio/lib/OctaveServoLibrary.h @@ -0,0 +1,27 @@ +/* + * 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); +}; + + diff --git a/inst/+arduinoio/lib/OctaveShiftRegisterLibrary.cpp b/inst/+arduinoio/lib/OctaveShiftRegisterLibrary.cpp new file mode 100644 index 0000000..ee670a4 --- /dev/null +++ b/inst/+arduinoio/lib/OctaveShiftRegisterLibrary.cpp @@ -0,0 +1,451 @@ +/* + * 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; + } +} diff --git a/inst/+arduinoio/lib/OctaveShiftRegisterLibrary.h b/inst/+arduinoio/lib/OctaveShiftRegisterLibrary.h new file mode 100644 index 0000000..54432af --- /dev/null +++ b/inst/+arduinoio/lib/OctaveShiftRegisterLibrary.h @@ -0,0 +1,27 @@ +/* + * 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); +}; + + diff --git a/inst/+arduinoio/lib/OctaveUltrasonicLibrary.cpp b/inst/+arduinoio/lib/OctaveUltrasonicLibrary.cpp new file mode 100644 index 0000000..ffe60a5 --- /dev/null +++ b/inst/+arduinoio/lib/OctaveUltrasonicLibrary.cpp @@ -0,0 +1,206 @@ +/* + * 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; + } +} + diff --git a/inst/+arduinoio/lib/OctaveUltrasonicLibrary.h b/inst/+arduinoio/lib/OctaveUltrasonicLibrary.h new file mode 100644 index 0000000..b99cf44 --- /dev/null +++ b/inst/+arduinoio/lib/OctaveUltrasonicLibrary.h @@ -0,0 +1,27 @@ +/* + * 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); +}; + + diff --git a/inst/+arduinoio/lib/octave.ino b/inst/+arduinoio/lib/octave.ino new file mode 100644 index 0000000..be449c0 --- /dev/null +++ b/inst/+arduinoio/lib/octave.ino @@ -0,0 +1,89 @@ +/* + * 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(); +} diff --git a/inst/+arduinoioaddons/+EEPRomAddon/EEPRom.m b/inst/+arduinoioaddons/+EEPRomAddon/EEPRom.m new file mode 100644 index 0000000..f01f109 --- /dev/null +++ b/inst/+arduinoioaddons/+EEPRomAddon/EEPRom.m @@ -0,0 +1,173 @@ +## 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 diff --git a/inst/+arduinoioaddons/+EEPRomAddon/EEPRomAddon.h b/inst/+arduinoioaddons/+EEPRomAddon/EEPRomAddon.h new file mode 100644 index 0000000..f4f94df --- /dev/null +++ b/inst/+arduinoioaddons/+EEPRomAddon/EEPRomAddon.h @@ -0,0 +1,100 @@ +/* + * 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 diff --git a/inst/+arduinoioaddons/+ExampleAddon/src/Echo.h b/inst/+arduinoioaddons/+ExampleAddon/src/Echo.h new file mode 100644 index 0000000..a50a40d --- /dev/null +++ b/inst/+arduinoioaddons/+ExampleAddon/src/Echo.h @@ -0,0 +1,50 @@ +/* + * 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(); + } + } + } +}; + diff --git a/inst/+arduinoioaddons/+ExampleLCD/LCD.m b/inst/+arduinoioaddons/+ExampleLCD/LCD.m new file mode 100644 index 0000000..a365a22 --- /dev/null +++ b/inst/+arduinoioaddons/+ExampleLCD/LCD.m @@ -0,0 +1,229 @@ +## 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 diff --git a/inst/+arduinoioaddons/+ExampleLCD/LCDAddon.h b/inst/+arduinoioaddons/+ExampleLCD/LCDAddon.h new file mode 100644 index 0000000..b912444 --- /dev/null +++ b/inst/+arduinoioaddons/+ExampleLCD/LCDAddon.h @@ -0,0 +1,139 @@ +/* + * 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; + } + } +}; diff --git a/inst/+arduinoioaddons/+RTCAddon/DS1307.m b/inst/+arduinoioaddons/+RTCAddon/DS1307.m new file mode 100644 index 0000000..41b6015 --- /dev/null +++ b/inst/+arduinoioaddons/+RTCAddon/DS1307.m @@ -0,0 +1,276 @@ +## 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 diff --git a/inst/+arduinoioaddons/+RTCAddon/DS1307Addon.h b/inst/+arduinoioaddons/+RTCAddon/DS1307Addon.h new file mode 100644 index 0000000..57082b5 --- /dev/null +++ b/inst/+arduinoioaddons/+RTCAddon/DS1307Addon.h @@ -0,0 +1,47 @@ +/* + * 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; + } + } +}; diff --git a/inst/+arduinoioaddons/+adafruit/dcmotorv2.m b/inst/+arduinoioaddons/+adafruit/dcmotorv2.m new file mode 100644 index 0000000..cf5f619 --- /dev/null +++ b/inst/+arduinoioaddons/+adafruit/dcmotorv2.m @@ -0,0 +1,172 @@ +## 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 + diff --git a/inst/+arduinoioaddons/+adafruit/motorshieldv2.h b/inst/+arduinoioaddons/+adafruit/motorshieldv2.h new file mode 100644 index 0000000..3c6b161 --- /dev/null +++ b/inst/+arduinoioaddons/+adafruit/motorshieldv2.h @@ -0,0 +1,303 @@ +/* + * 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; + } + } +}; diff --git a/inst/+arduinoioaddons/+adafruit/motorshieldv2.m b/inst/+arduinoioaddons/+adafruit/motorshieldv2.m new file mode 100644 index 0000000..6d51c8b --- /dev/null +++ b/inst/+arduinoioaddons/+adafruit/motorshieldv2.m @@ -0,0 +1,238 @@ +## 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 diff --git a/inst/+arduinoioaddons/+adafruit/stepper.m b/inst/+arduinoioaddons/+adafruit/stepper.m new file mode 100644 index 0000000..8c5ab65 --- /dev/null +++ b/inst/+arduinoioaddons/+adafruit/stepper.m @@ -0,0 +1,223 @@ +## 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 + diff --git a/inst/+arduinosensor/DS1307.m b/inst/+arduinosensor/DS1307.m new file mode 100644 index 0000000..916be5f --- /dev/null +++ b/inst/+arduinosensor/DS1307.m @@ -0,0 +1,262 @@ +## 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 diff --git a/inst/+arduinosensor/GUVAS12SD.m b/inst/+arduinosensor/GUVAS12SD.m new file mode 100644 index 0000000..3aea304 --- /dev/null +++ b/inst/+arduinosensor/GUVAS12SD.m @@ -0,0 +1,139 @@ +## 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 diff --git a/inst/+arduinosensor/MPC3002.m b/inst/+arduinosensor/MPC3002.m new file mode 100644 index 0000000..39b27a7 --- /dev/null +++ b/inst/+arduinosensor/MPC3002.m @@ -0,0 +1,144 @@ +## 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 diff --git a/inst/+arduinosensor/SI7021.m b/inst/+arduinosensor/SI7021.m new file mode 100644 index 0000000..b58e3ce --- /dev/null +++ b/inst/+arduinosensor/SI7021.m @@ -0,0 +1,217 @@ +## 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 diff --git a/inst/@arduino/__freeArduino__.m b/inst/@arduino/__freeArduino__.m new file mode 100644 index 0000000..4a286f4 --- /dev/null +++ b/inst/@arduino/__freeArduino__.m @@ -0,0 +1,28 @@ +## 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 diff --git a/inst/@arduino/__initArduino__.m b/inst/@arduino/__initArduino__.m new file mode 100644 index 0000000..25cf5c8 --- /dev/null +++ b/inst/@arduino/__initArduino__.m @@ -0,0 +1,101 @@ +## 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)); + + % 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; + 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 diff --git a/inst/@arduino/arduino.m b/inst/@arduino/arduino.m new file mode 100644 index 0000000..71b5cf3 --- /dev/null +++ b/inst/@arduino/arduino.m @@ -0,0 +1,436 @@ +## 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 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))) diff --git a/inst/@arduino/checkI2CAddress.m b/inst/@arduino/checkI2CAddress.m new file mode 100644 index 0000000..83ef64c --- /dev/null +++ b/inst/@arduino/checkI2CAddress.m @@ -0,0 +1,84 @@ +## 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); diff --git a/inst/@arduino/configurePin.m b/inst/@arduino/configurePin.m new file mode 100644 index 0000000..530ebb4 --- /dev/null +++ b/inst/@arduino/configurePin.m @@ -0,0 +1,140 @@ +## 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"); diff --git a/inst/@arduino/configurePinResource.m b/inst/@arduino/configurePinResource.m new file mode 100644 index 0000000..db1f4c0 --- /dev/null +++ b/inst/@arduino/configurePinResource.m @@ -0,0 +1,126 @@ +## 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"); diff --git a/inst/@arduino/decrementResourceCount.m b/inst/@arduino/decrementResourceCount.m new file mode 100644 index 0000000..47603ff --- /dev/null +++ b/inst/@arduino/decrementResourceCount.m @@ -0,0 +1,56 @@ +## 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); diff --git a/inst/@arduino/delete.m b/inst/@arduino/delete.m new file mode 100644 index 0000000..c06d2aa --- /dev/null +++ b/inst/@arduino/delete.m @@ -0,0 +1,29 @@ +## 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 diff --git a/inst/@arduino/display.m b/inst/@arduino/display.m new file mode 100644 index 0000000..15885f5 --- /dev/null +++ b/inst/@arduino/display.m @@ -0,0 +1,83 @@ +## 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 diff --git a/inst/@arduino/getI2CTerminals.m b/inst/@arduino/getI2CTerminals.m new file mode 100644 index 0000000..c6b230b --- /dev/null +++ b/inst/@arduino/getI2CTerminals.m @@ -0,0 +1,52 @@ +## 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) diff --git a/inst/@arduino/getInterruptTerminals.m b/inst/@arduino/getInterruptTerminals.m new file mode 100644 index 0000000..0417e59 --- /dev/null +++ b/inst/@arduino/getInterruptTerminals.m @@ -0,0 +1,40 @@ +## 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)); diff --git a/inst/@arduino/getLEDTerminals.m b/inst/@arduino/getLEDTerminals.m new file mode 100644 index 0000000..b10a6a5 --- /dev/null +++ b/inst/@arduino/getLEDTerminals.m @@ -0,0 +1,39 @@ +## 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); diff --git a/inst/@arduino/getMCU.m b/inst/@arduino/getMCU.m new file mode 100644 index 0000000..5bf924d --- /dev/null +++ b/inst/@arduino/getMCU.m @@ -0,0 +1,35 @@ +## 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 ()) diff --git a/inst/@arduino/getPWMTerminals.m b/inst/@arduino/getPWMTerminals.m new file mode 100644 index 0000000..e1fc4d8 --- /dev/null +++ b/inst/@arduino/getPWMTerminals.m @@ -0,0 +1,41 @@ +## 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) + diff --git a/inst/@arduino/getPinAlias.m b/inst/@arduino/getPinAlias.m new file mode 100644 index 0000000..eec60b4 --- /dev/null +++ b/inst/@arduino/getPinAlias.m @@ -0,0 +1,54 @@ +## 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 + diff --git a/inst/@arduino/getPinInfo.m b/inst/@arduino/getPinInfo.m new file mode 100644 index 0000000..64d1f2a --- /dev/null +++ b/inst/@arduino/getPinInfo.m @@ -0,0 +1,141 @@ +## 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"); + diff --git a/inst/@arduino/getPinsFromTerminals.m b/inst/@arduino/getPinsFromTerminals.m new file mode 100644 index 0000000..4195896 --- /dev/null +++ b/inst/@arduino/getPinsFromTerminals.m @@ -0,0 +1,72 @@ +## 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"); + diff --git a/inst/@arduino/getResourceCount.m b/inst/@arduino/getResourceCount.m new file mode 100644 index 0000000..db0541f --- /dev/null +++ b/inst/@arduino/getResourceCount.m @@ -0,0 +1,45 @@ +## 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); diff --git a/inst/@arduino/getResourceOwner.m b/inst/@arduino/getResourceOwner.m new file mode 100644 index 0000000..b5b3536 --- /dev/null +++ b/inst/@arduino/getResourceOwner.m @@ -0,0 +1,49 @@ +## 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"); + diff --git a/inst/@arduino/getSPITerminals.m b/inst/@arduino/getSPITerminals.m new file mode 100644 index 0000000..5d38b1f --- /dev/null +++ b/inst/@arduino/getSPITerminals.m @@ -0,0 +1,34 @@ +## 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 diff --git a/inst/@arduino/getServoTerminals.m b/inst/@arduino/getServoTerminals.m new file mode 100644 index 0000000..5ac58b7 --- /dev/null +++ b/inst/@arduino/getServoTerminals.m @@ -0,0 +1,34 @@ +## 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 diff --git a/inst/@arduino/getSharedResourceProperty.m b/inst/@arduino/getSharedResourceProperty.m new file mode 100644 index 0000000..26899cb --- /dev/null +++ b/inst/@arduino/getSharedResourceProperty.m @@ -0,0 +1,52 @@ +## 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); diff --git a/inst/@arduino/getTerminalMode.m b/inst/@arduino/getTerminalMode.m new file mode 100644 index 0000000..85683af --- /dev/null +++ b/inst/@arduino/getTerminalMode.m @@ -0,0 +1,46 @@ +## 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"); diff --git a/inst/@arduino/getTerminalsFromPins.m b/inst/@arduino/getTerminalsFromPins.m new file mode 100644 index 0000000..e669e2f --- /dev/null +++ b/inst/@arduino/getTerminalsFromPins.m @@ -0,0 +1,51 @@ +## 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 diff --git a/inst/@arduino/incrementResourceCount.m b/inst/@arduino/incrementResourceCount.m new file mode 100644 index 0000000..237ccbd --- /dev/null +++ b/inst/@arduino/incrementResourceCount.m @@ -0,0 +1,51 @@ +## 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); diff --git a/inst/@arduino/isTerminalAnalog.m b/inst/@arduino/isTerminalAnalog.m new file mode 100644 index 0000000..4874454 --- /dev/null +++ b/inst/@arduino/isTerminalAnalog.m @@ -0,0 +1,59 @@ +## 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) + +%!error isTerminalAnalog(ar, "d1", 1) + + diff --git a/inst/@arduino/isTerminalDigital.m b/inst/@arduino/isTerminalDigital.m new file mode 100644 index 0000000..56ff6ec --- /dev/null +++ b/inst/@arduino/isTerminalDigital.m @@ -0,0 +1,60 @@ +## 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) + +%!error isTerminalDigital(ar, "d1", 1) + +%!error isTerminalDigital(ar, -1) + + diff --git a/inst/@arduino/playTone.m b/inst/@arduino/playTone.m new file mode 100644 index 0000000..0a6aa11 --- /dev/null +++ b/inst/@arduino/playTone.m @@ -0,0 +1,97 @@ +## 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) diff --git a/inst/@arduino/private/__digitalPin__.m b/inst/@arduino/private/__digitalPin__.m new file mode 100644 index 0000000..551daf8 --- /dev/null +++ b/inst/@arduino/private/__digitalPin__.m @@ -0,0 +1,68 @@ +## 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 diff --git a/inst/@arduino/private/__recvResponse__.m b/inst/@arduino/private/__recvResponse__.m new file mode 100644 index 0000000..5926851 --- /dev/null +++ b/inst/@arduino/private/__recvResponse__.m @@ -0,0 +1,96 @@ +## 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 diff --git a/inst/@arduino/private/__sendCommand__.m b/inst/@arduino/private/__sendCommand__.m new file mode 100644 index 0000000..b2405ce --- /dev/null +++ b/inst/@arduino/private/__sendCommand__.m @@ -0,0 +1,64 @@ +## 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 diff --git a/inst/@arduino/private/getTypeTerminals.m b/inst/@arduino/private/getTypeTerminals.m new file mode 100644 index 0000000..b431e7e --- /dev/null +++ b/inst/@arduino/private/getTypeTerminals.m @@ -0,0 +1,36 @@ +## 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 diff --git a/inst/@arduino/private/pinStateMode.m b/inst/@arduino/private/pinStateMode.m new file mode 100644 index 0000000..ff14be6 --- /dev/null +++ b/inst/@arduino/private/pinStateMode.m @@ -0,0 +1,74 @@ +## 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 diff --git a/inst/@arduino/readAnalogPin.m b/inst/@arduino/readAnalogPin.m new file mode 100644 index 0000000..2261d92 --- /dev/null +++ b/inst/@arduino/readAnalogPin.m @@ -0,0 +1,90 @@ +## 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) + +%!error readAnalogPin(ar, "a0", 2) + +%!error readAnalogPin(ar, "nopin") diff --git a/inst/@arduino/readDigitalPin.m b/inst/@arduino/readDigitalPin.m new file mode 100644 index 0000000..723cc50 --- /dev/null +++ b/inst/@arduino/readDigitalPin.m @@ -0,0 +1,61 @@ +## 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) + +%!error readDigitalPin(ar, "d2", 2) + +%!error readDigitalPin(ar, "nopin") diff --git a/inst/@arduino/readVoltage.m b/inst/@arduino/readVoltage.m new file mode 100644 index 0000000..6af64ef --- /dev/null +++ b/inst/@arduino/readVoltage.m @@ -0,0 +1,71 @@ +## 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) + +%!error readVoltage(ar, "a0", 2) + +%!error readVoltage(ar, "nopin") diff --git a/inst/@arduino/reset.m b/inst/@arduino/reset.m new file mode 100644 index 0000000..f4f4d7a --- /dev/null +++ b/inst/@arduino/reset.m @@ -0,0 +1,42 @@ +## 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); diff --git a/inst/@arduino/sendCommand.m b/inst/@arduino/sendCommand.m new file mode 100644 index 0000000..80c8d43 --- /dev/null +++ b/inst/@arduino/sendCommand.m @@ -0,0 +1,97 @@ +## 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); diff --git a/inst/@arduino/setSharedResourceProperty.m b/inst/@arduino/setSharedResourceProperty.m new file mode 100644 index 0000000..b27589c --- /dev/null +++ b/inst/@arduino/setSharedResourceProperty.m @@ -0,0 +1,80 @@ +## 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"), []); diff --git a/inst/@arduino/uptime.m b/inst/@arduino/uptime.m new file mode 100644 index 0000000..a9239e6 --- /dev/null +++ b/inst/@arduino/uptime.m @@ -0,0 +1,59 @@ +## 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); + diff --git a/inst/@arduino/validatePin.m b/inst/@arduino/validatePin.m new file mode 100644 index 0000000..0c4edc9 --- /dev/null +++ b/inst/@arduino/validatePin.m @@ -0,0 +1,80 @@ +## 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") + diff --git a/inst/@arduino/version.m b/inst/@arduino/version.m new file mode 100644 index 0000000..8078648 --- /dev/null +++ b/inst/@arduino/version.m @@ -0,0 +1,52 @@ +## 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))); diff --git a/inst/@arduino/writeDigitalPin.m b/inst/@arduino/writeDigitalPin.m new file mode 100644 index 0000000..bcd91a3 --- /dev/null +++ b/inst/@arduino/writeDigitalPin.m @@ -0,0 +1,69 @@ +## 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) + +%!error writeDigitalPin(ar, "d2", 1, 1) + +%!error writeDigitalPin(ar, "nopin", 1) diff --git a/inst/@arduino/writePWMDutyCycle.m b/inst/@arduino/writePWMDutyCycle.m new file mode 100644 index 0000000..33402fb --- /dev/null +++ b/inst/@arduino/writePWMDutyCycle.m @@ -0,0 +1,93 @@ +## 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); diff --git a/inst/@arduino/writePWMVoltage.m b/inst/@arduino/writePWMVoltage.m new file mode 100644 index 0000000..b78b5ec --- /dev/null +++ b/inst/@arduino/writePWMVoltage.m @@ -0,0 +1,73 @@ +## 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); diff --git a/inst/@device/delete.m b/inst/@device/delete.m new file mode 100644 index 0000000..26992c0 --- /dev/null +++ b/inst/@device/delete.m @@ -0,0 +1,80 @@ +## 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 diff --git a/inst/@device/device.m b/inst/@device/device.m new file mode 100644 index 0000000..3f36957 --- /dev/null +++ b/inst/@device/device.m @@ -0,0 +1,528 @@ +## 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) diff --git a/inst/@device/display.m b/inst/@device/display.m new file mode 100644 index 0000000..ed20a32 --- /dev/null +++ b/inst/@device/display.m @@ -0,0 +1,56 @@ +## 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 diff --git a/inst/@device/flush.m b/inst/@device/flush.m new file mode 100644 index 0000000..cfed18b --- /dev/null +++ b/inst/@device/flush.m @@ -0,0 +1,56 @@ +## 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 diff --git a/inst/@device/private/__getBytesAvailable__.m b/inst/@device/private/__getBytesAvailable__.m new file mode 100644 index 0000000..39a3281 --- /dev/null +++ b/inst/@device/private/__getBytesAvailable__.m @@ -0,0 +1,28 @@ +## 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 diff --git a/inst/@device/read.m b/inst/@device/read.m new file mode 100644 index 0000000..1682210 --- /dev/null +++ b/inst/@device/read.m @@ -0,0 +1,93 @@ +## 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} =} 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 == 'L') + out = swapbytes (out); + endif + else + if (strcmp (precision, 'int8')) + out = int8(tmp(2:end)) + else + out = tmp(2:end); + endif + endif +endfunction diff --git a/inst/@device/readRegister.m b/inst/@device/readRegister.m new file mode 100644 index 0000000..61289f9 --- /dev/null +++ b/inst/@device/readRegister.m @@ -0,0 +1,111 @@ +## 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 == 'L') + reg = swapbytes (reg); + endif + reg = typecast (reg, 'uint8'); + regsz = 2; + elseif (strcmp (precision,'int16')) + reg = int16(reg); + if (endian == 'L') + 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 == 'L') + out = swapbytes (out); + endif + else + if (strcmp (precision, 'int8')) + out = int8(out); + else + out = uint8(out); + endif + endif + +endfunction diff --git a/inst/@device/subsasgn.m b/inst/@device/subsasgn.m new file mode 100644 index 0000000..51532aa --- /dev/null +++ b/inst/@device/subsasgn.m @@ -0,0 +1,44 @@ +## 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 + diff --git a/inst/@device/subsref.m b/inst/@device/subsref.m new file mode 100644 index 0000000..8bfcd05 --- /dev/null +++ b/inst/@device/subsref.m @@ -0,0 +1,150 @@ +## 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) diff --git a/inst/@device/write.m b/inst/@device/write.m new file mode 100644 index 0000000..bc5191f --- /dev/null +++ b/inst/@device/write.m @@ -0,0 +1,86 @@ +## 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 {} {} 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 == 'L') + datain = swapbytes (datain); + endif + datain = typecast (datain, 'uint8'); + elseif (strcmp (precision,'int16')) + datain = int16(datain); + if (endian == 'L') + 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 diff --git a/inst/@device/writeRead.m b/inst/@device/writeRead.m new file mode 100644 index 0000000..4139b90 --- /dev/null +++ b/inst/@device/writeRead.m @@ -0,0 +1,72 @@ +## 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) + diff --git a/inst/@device/writeRegister.m b/inst/@device/writeRegister.m new file mode 100644 index 0000000..bcfcc2d --- /dev/null +++ b/inst/@device/writeRegister.m @@ -0,0 +1,96 @@ +## 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 == 'L') + 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') + 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 diff --git a/inst/@i2cdev/delete.m b/inst/@i2cdev/delete.m new file mode 100644 index 0000000..a828236 --- /dev/null +++ b/inst/@i2cdev/delete.m @@ -0,0 +1,25 @@ +## 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 diff --git a/inst/@i2cdev/display.m b/inst/@i2cdev/display.m new file mode 100644 index 0000000..3f7793c --- /dev/null +++ b/inst/@i2cdev/display.m @@ -0,0 +1,36 @@ +## 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 diff --git a/inst/@i2cdev/i2cdev.m b/inst/@i2cdev/i2cdev.m new file mode 100644 index 0000000..f49e5c6 --- /dev/null +++ b/inst/@i2cdev/i2cdev.m @@ -0,0 +1,191 @@ +## 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 + diff --git a/inst/@i2cdev/read.m b/inst/@i2cdev/read.m new file mode 100644 index 0000000..b5a9ed7 --- /dev/null +++ b/inst/@i2cdev/read.m @@ -0,0 +1,82 @@ +## 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 diff --git a/inst/@i2cdev/readRegister.m b/inst/@i2cdev/readRegister.m new file mode 100644 index 0000000..c88afc7 --- /dev/null +++ b/inst/@i2cdev/readRegister.m @@ -0,0 +1,107 @@ +## 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 diff --git a/inst/@i2cdev/subsref.m b/inst/@i2cdev/subsref.m new file mode 100644 index 0000000..fd6740c --- /dev/null +++ b/inst/@i2cdev/subsref.m @@ -0,0 +1,55 @@ +## 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") diff --git a/inst/@i2cdev/write.m b/inst/@i2cdev/write.m new file mode 100644 index 0000000..6ee70d3 --- /dev/null +++ b/inst/@i2cdev/write.m @@ -0,0 +1,78 @@ +## 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 diff --git a/inst/@i2cdev/writeRegister.m b/inst/@i2cdev/writeRegister.m new file mode 100644 index 0000000..081fcab --- /dev/null +++ b/inst/@i2cdev/writeRegister.m @@ -0,0 +1,92 @@ +## 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 diff --git a/inst/@rotaryEncoder/delete.m b/inst/@rotaryEncoder/delete.m new file mode 100644 index 0000000..819cbd0 --- /dev/null +++ b/inst/@rotaryEncoder/delete.m @@ -0,0 +1,43 @@ +## 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 diff --git a/inst/@rotaryEncoder/display.m b/inst/@rotaryEncoder/display.m new file mode 100644 index 0000000..c58bc2a --- /dev/null +++ b/inst/@rotaryEncoder/display.m @@ -0,0 +1,33 @@ +## 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 diff --git a/inst/@rotaryEncoder/readCount.m b/inst/@rotaryEncoder/readCount.m new file mode 100644 index 0000000..7832aaf --- /dev/null +++ b/inst/@rotaryEncoder/readCount.m @@ -0,0 +1,77 @@ +## 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(); diff --git a/inst/@rotaryEncoder/readSpeed.m b/inst/@rotaryEncoder/readSpeed.m new file mode 100644 index 0000000..0f2e32d --- /dev/null +++ b/inst/@rotaryEncoder/readSpeed.m @@ -0,0 +1,48 @@ +## 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) diff --git a/inst/@rotaryEncoder/resetCount.m b/inst/@rotaryEncoder/resetCount.m new file mode 100644 index 0000000..6a61d56 --- /dev/null +++ b/inst/@rotaryEncoder/resetCount.m @@ -0,0 +1,51 @@ +## 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); diff --git a/inst/@rotaryEncoder/rotaryEncoder.m b/inst/@rotaryEncoder/rotaryEncoder.m new file mode 100644 index 0000000..e1a2015 --- /dev/null +++ b/inst/@rotaryEncoder/rotaryEncoder.m @@ -0,0 +1,167 @@ +## 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"); + diff --git a/inst/@rotaryEncoder/subsref.m b/inst/@rotaryEncoder/subsref.m new file mode 100644 index 0000000..8a8109e --- /dev/null +++ b/inst/@rotaryEncoder/subsref.m @@ -0,0 +1,57 @@ +## 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) diff --git a/inst/@servo/delete.m b/inst/@servo/delete.m new file mode 100644 index 0000000..5fc86fa --- /dev/null +++ b/inst/@servo/delete.m @@ -0,0 +1,38 @@ +## 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 diff --git a/inst/@servo/display.m b/inst/@servo/display.m new file mode 100644 index 0000000..11353b7 --- /dev/null +++ b/inst/@servo/display.m @@ -0,0 +1,29 @@ +## 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 diff --git a/inst/@servo/private/__servoPosition__.m b/inst/@servo/private/__servoPosition__.m new file mode 100644 index 0000000..b4aef10 --- /dev/null +++ b/inst/@servo/private/__servoPosition__.m @@ -0,0 +1,49 @@ +## 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 diff --git a/inst/@servo/readPosition.m b/inst/@servo/readPosition.m new file mode 100644 index 0000000..9e4a04c --- /dev/null +++ b/inst/@servo/readPosition.m @@ -0,0 +1,45 @@ +## 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(); + diff --git a/inst/@servo/servo.m b/inst/@servo/servo.m new file mode 100644 index 0000000..8ce292c --- /dev/null +++ b/inst/@servo/servo.m @@ -0,0 +1,157 @@ +## 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) diff --git a/inst/@servo/subsref.m b/inst/@servo/subsref.m new file mode 100644 index 0000000..0e9a07d --- /dev/null +++ b/inst/@servo/subsref.m @@ -0,0 +1,62 @@ +## 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); diff --git a/inst/@servo/writePosition.m b/inst/@servo/writePosition.m new file mode 100644 index 0000000..efe3f62 --- /dev/null +++ b/inst/@servo/writePosition.m @@ -0,0 +1,51 @@ +## 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); + diff --git a/inst/@shiftRegister/delete.m b/inst/@shiftRegister/delete.m new file mode 100644 index 0000000..bba902d --- /dev/null +++ b/inst/@shiftRegister/delete.m @@ -0,0 +1,42 @@ +## 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 diff --git a/inst/@shiftRegister/display.m b/inst/@shiftRegister/display.m new file mode 100644 index 0000000..c16dd38 --- /dev/null +++ b/inst/@shiftRegister/display.m @@ -0,0 +1,33 @@ +## 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 diff --git a/inst/@shiftRegister/read.m b/inst/@shiftRegister/read.m new file mode 100644 index 0000000..47be333 --- /dev/null +++ b/inst/@shiftRegister/read.m @@ -0,0 +1,74 @@ +## 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 diff --git a/inst/@shiftRegister/reset.m b/inst/@shiftRegister/reset.m new file mode 100644 index 0000000..3e168ca --- /dev/null +++ b/inst/@shiftRegister/reset.m @@ -0,0 +1,31 @@ +## 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 diff --git a/inst/@shiftRegister/shiftRegister.m b/inst/@shiftRegister/shiftRegister.m new file mode 100644 index 0000000..97eb01a --- /dev/null +++ b/inst/@shiftRegister/shiftRegister.m @@ -0,0 +1,204 @@ +## 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"); diff --git a/inst/@shiftRegister/subsref.m b/inst/@shiftRegister/subsref.m new file mode 100644 index 0000000..c4df8cf --- /dev/null +++ b/inst/@shiftRegister/subsref.m @@ -0,0 +1,57 @@ +## 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); diff --git a/inst/@shiftRegister/write.m b/inst/@shiftRegister/write.m new file mode 100644 index 0000000..f098f5d --- /dev/null +++ b/inst/@shiftRegister/write.m @@ -0,0 +1,86 @@ +## 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 diff --git a/inst/@spidev/delete.m b/inst/@spidev/delete.m new file mode 100644 index 0000000..d02026e --- /dev/null +++ b/inst/@spidev/delete.m @@ -0,0 +1,57 @@ +## 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 diff --git a/inst/@spidev/display.m b/inst/@spidev/display.m new file mode 100644 index 0000000..d29f26f --- /dev/null +++ b/inst/@spidev/display.m @@ -0,0 +1,36 @@ +## 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 diff --git a/inst/@spidev/spidev.m b/inst/@spidev/spidev.m new file mode 100644 index 0000000..a654b7b --- /dev/null +++ b/inst/@spidev/spidev.m @@ -0,0 +1,263 @@ +## 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); diff --git a/inst/@spidev/subsref.m b/inst/@spidev/subsref.m new file mode 100644 index 0000000..4172f9f --- /dev/null +++ b/inst/@spidev/subsref.m @@ -0,0 +1,65 @@ +## 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") diff --git a/inst/@spidev/writeRead.m b/inst/@spidev/writeRead.m new file mode 100644 index 0000000..769efea --- /dev/null +++ b/inst/@spidev/writeRead.m @@ -0,0 +1,64 @@ +## 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); + diff --git a/inst/@ultrasonic/delete.m b/inst/@ultrasonic/delete.m new file mode 100644 index 0000000..acd7af4 --- /dev/null +++ b/inst/@ultrasonic/delete.m @@ -0,0 +1,40 @@ +## 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 diff --git a/inst/@ultrasonic/display.m b/inst/@ultrasonic/display.m new file mode 100644 index 0000000..26226f9 --- /dev/null +++ b/inst/@ultrasonic/display.m @@ -0,0 +1,31 @@ +## 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 diff --git a/inst/@ultrasonic/readDistance.m b/inst/@ultrasonic/readDistance.m new file mode 100644 index 0000000..2a26c32 --- /dev/null +++ b/inst/@ultrasonic/readDistance.m @@ -0,0 +1,54 @@ +## 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() diff --git a/inst/@ultrasonic/readEchoTime.m b/inst/@ultrasonic/readEchoTime.m new file mode 100644 index 0000000..4d92d52 --- /dev/null +++ b/inst/@ultrasonic/readEchoTime.m @@ -0,0 +1,53 @@ +## 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() diff --git a/inst/@ultrasonic/subsref.m b/inst/@ultrasonic/subsref.m new file mode 100644 index 0000000..85a60a8 --- /dev/null +++ b/inst/@ultrasonic/subsref.m @@ -0,0 +1,64 @@ +## 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") diff --git a/inst/@ultrasonic/ultrasonic.m b/inst/@ultrasonic/ultrasonic.m new file mode 100644 index 0000000..48690f2 --- /dev/null +++ b/inst/@ultrasonic/ultrasonic.m @@ -0,0 +1,179 @@ +## 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') diff --git a/inst/addon.m b/inst/addon.m new file mode 100644 index 0000000..c3c547a --- /dev/null +++ b/inst/addon.m @@ -0,0 +1,94 @@ +## 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"); diff --git a/inst/arduino_bistsetup.m b/inst/arduino_bistsetup.m new file mode 100644 index 0000000..942a226 --- /dev/null +++ b/inst/arduino_bistsetup.m @@ -0,0 +1,111 @@ +## 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 diff --git a/inst/arduinosetup.m b/inst/arduinosetup.m new file mode 100644 index 0000000..c9e246b --- /dev/null +++ b/inst/arduinosetup.m @@ -0,0 +1,244 @@ +## 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 diff --git a/inst/examples/example_blink.m b/inst/examples/example_blink.m new file mode 100644 index 0000000..279fc8b --- /dev/null +++ b/inst/examples/example_blink.m @@ -0,0 +1,34 @@ +## 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 diff --git a/inst/examples/example_i2c_eeprom.m b/inst/examples/example_i2c_eeprom.m new file mode 100644 index 0000000..db72b64 --- /dev/null +++ b/inst/examples/example_i2c_eeprom.m @@ -0,0 +1,105 @@ +## 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 diff --git a/inst/examples/example_i2c_tempsensor.m b/inst/examples/example_i2c_tempsensor.m new file mode 100644 index 0000000..ac5a731 --- /dev/null +++ b/inst/examples/example_i2c_tempsensor.m @@ -0,0 +1,118 @@ +## 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 diff --git a/inst/examples/example_i2c_tempsensor_plot.m b/inst/examples/example_i2c_tempsensor_plot.m new file mode 100644 index 0000000..58b23b1 --- /dev/null +++ b/inst/examples/example_i2c_tempsensor_plot.m @@ -0,0 +1,154 @@ +## 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 diff --git a/inst/examples/example_lcd_plugin.m b/inst/examples/example_lcd_plugin.m new file mode 100644 index 0000000..61cee50 --- /dev/null +++ b/inst/examples/example_lcd_plugin.m @@ -0,0 +1,40 @@ +## 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 diff --git a/inst/examples/example_shiftreg_595.m b/inst/examples/example_shiftreg_595.m new file mode 100644 index 0000000..8c121d4 --- /dev/null +++ b/inst/examples/example_shiftreg_595.m @@ -0,0 +1,38 @@ +## 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 diff --git a/inst/examples/example_spi_mcp3002.m b/inst/examples/example_spi_mcp3002.m new file mode 100644 index 0000000..b5efec6 --- /dev/null +++ b/inst/examples/example_spi_mcp3002.m @@ -0,0 +1,67 @@ +## 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 diff --git a/inst/examples/example_sweep_servo.m b/inst/examples/example_sweep_servo.m new file mode 100644 index 0000000..9bd16ec --- /dev/null +++ b/inst/examples/example_sweep_servo.m @@ -0,0 +1,50 @@ +## 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 diff --git a/inst/isarduino.m b/inst/isarduino.m new file mode 100644 index 0000000..2049a4c --- /dev/null +++ b/inst/isarduino.m @@ -0,0 +1,49 @@ +## 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) diff --git a/inst/listArduinoLibraries.m b/inst/listArduinoLibraries.m new file mode 100644 index 0000000..5981f48 --- /dev/null +++ b/inst/listArduinoLibraries.m @@ -0,0 +1,92 @@ +## 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") diff --git a/inst/private/__addons__.m b/inst/private/__addons__.m new file mode 100644 index 0000000..500f958 --- /dev/null +++ b/inst/private/__addons__.m @@ -0,0 +1,91 @@ +## 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} =} __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) + idx = find( cellfun(@(x) strcmpi(x.Name, "arduinoio.LibraryBase"), classinfo.SuperClassList), 1); + retval = !isempty(idx); + else + retval = false; + endif +endfunction + diff --git a/inst/private/__arduino_binary__.m b/inst/private/__arduino_binary__.m new file mode 100644 index 0000000..6336dfd --- /dev/null +++ b/inst/private/__arduino_binary__.m @@ -0,0 +1,118 @@ +## 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 diff --git a/inst/scanForArduinos.m b/inst/scanForArduinos.m new file mode 100644 index 0000000..9278d8d --- /dev/null +++ b/inst/scanForArduinos.m @@ -0,0 +1,177 @@ +## 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)); diff --git a/inst/scanI2Cbus.m b/inst/scanI2Cbus.m new file mode 100644 index 0000000..f4c4857 --- /dev/null +++ b/inst/scanI2Cbus.m @@ -0,0 +1,81 @@ +## 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); diff --git a/octave-arduino.metainfo.xml b/octave-arduino.metainfo.xml new file mode 100644 index 0000000..78af3b3 --- /dev/null +++ b/octave-arduino.metainfo.xml @@ -0,0 +1,31 @@ + + + + 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 +
diff --git a/test/make_conf.m b/test/make_conf.m new file mode 100644 index 0000000..68fa6c2 --- /dev/null +++ b/test/make_conf.m @@ -0,0 +1,203 @@ +## 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 diff --git a/test/test_exampleplugin.m b/test/test_exampleplugin.m new file mode 100644 index 0000000..a481fe7 --- /dev/null +++ b/test/test_exampleplugin.m @@ -0,0 +1,21 @@ +## 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") diff --git a/test/test_jig.m b/test/test_jig.m new file mode 100644 index 0000000..1827fe8 --- /dev/null +++ b/test/test_jig.m @@ -0,0 +1,392 @@ +## 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 -- cgit v1.2.3 From baae242e618cf885122c90a45b8acec38d446b86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Laboissi=C3=A8re?= Date: Sun, 15 Aug 2021 09:34:52 -0300 Subject: Import octave-arduino_0.7.0-2.debian.tar.xz [dgit import tarball octave-arduino 0.7.0-2 octave-arduino_0.7.0-2.debian.tar.xz] --- changelog | 72 +++++++++++++++++++++++++++++++++++++++++++++++++ clean | 10 +++++++ control | 23 ++++++++++++++++ copyright | 51 +++++++++++++++++++++++++++++++++++ gbp.conf | 4 +++ octave-arduino.doc-base | 12 +++++++++ octave-arduino.docs | 2 ++ octave-arduino.info | 1 + rules | 17 ++++++++++++ source/format | 1 + source/options | 1 + tests/control | 2 ++ tests/no-test | 8 ++++++ upstream/metadata | 3 +++ watch | 2 ++ 15 files changed, 209 insertions(+) create mode 100644 changelog create mode 100644 clean create mode 100644 control create mode 100644 copyright create mode 100644 gbp.conf create mode 100644 octave-arduino.doc-base create mode 100644 octave-arduino.docs create mode 100644 octave-arduino.info create mode 100755 rules create mode 100644 source/format create mode 100644 source/options create mode 100644 tests/control create mode 100644 tests/no-test create mode 100644 upstream/metadata create mode 100644 watch diff --git a/changelog b/changelog new file mode 100644 index 0000000..3854023 --- /dev/null +++ b/changelog @@ -0,0 +1,72 @@ +octave-arduino (0.7.0-2) unstable; urgency=medium + + * Upload to unstable + * d/rules: Use target execute_before_dh_auto_build instead of + override_dh_auto_build + + -- Rafael Laboissière Sun, 15 Aug 2021 09:34:52 -0300 + +octave-arduino (0.7.0-1) experimental; urgency=medium + + * New upstream version 0.7.0 + * d/control: Bump Standards-Version to 4.5.1 (no changes needed) + * d/copyright: Reflect upstream changes + + -- Rafael Laboissière Fri, 07 May 2021 14:11:32 -0300 + +octave-arduino (0.6.0-1) unstable; urgency=medium + + * New upstream version 0.6.0 + + -- Rafael Laboissière Sat, 26 Sep 2020 09:33:27 -0300 + +octave-arduino (0.5.0-2) unstable; urgency=medium + + * d/u/metadata: New file + * d/control: Bump debhelper compatibitlity level to 13 + + -- Rafael Laboissière Mon, 20 Jul 2020 12:50:50 -0300 + +octave-arduino (0.5.0-1) unstable; urgency=medium + + * New upstream version 0.5.0 + * d/copyright: Reflect upstream changes + * d/rules: Ensure that documentation building succeeds + * d/control: + + Bump Standards-Version to 4.5.0 (no changes needed) + + Add Rules-Requires-Root: no + * d/t/{control,no-test}: Add dummy test file to prevent triggering of + autodep8 + + -- Rafael Laboissière Tue, 03 Mar 2020 11:26:06 +0100 + +octave-arduino (0.4.0-1) unstable; urgency=medium + + * New upstream version 0.4.0 + * d/copyright: + + Reflect upstream changes + + Add copyright information for octave-arduino.metainfo.xml + * d/control: Bump Standards-Version to 4.4.0 (no changes needed) + * d/p/info-dir-section.patch: Drop patch (applied upstream) + + -- Rafael Laboissiere Wed, 10 Jul 2019 08:39:51 -0300 + +octave-arduino (0.3.0-2) unstable; urgency=medium + + * d/control: Drop the Testsuite header. + The unit tests should not be exercised in the Debian CI infrastructure, + because they depend on an Arduino board connected to the system. + + -- Rafael Laboissiere Sun, 20 Jan 2019 08:47:38 -0200 + +octave-arduino (0.3.0-1) unstable; urgency=medium + + * New upstream version 0.3.0 + + -- Rafael Laboissiere Sat, 19 Jan 2019 19:13:07 -0200 + +octave-arduino (0.2.0-1) unstable; urgency=low + + * Initial release (closes: #912761) + + -- Rafael Laboissiere Fri, 04 Jan 2019 06:51:51 -0200 diff --git a/clean b/clean new file mode 100644 index 0000000..986bff2 --- /dev/null +++ b/clean @@ -0,0 +1,10 @@ +doc/arduino.html +doc/arduino.info +doc/arduino.aux +doc/arduino.cp +doc/arduino.cps +doc/arduino.fn +doc/arduino.fns +doc/arduino.log +doc/arduino.toc + diff --git a/control b/control new file mode 100644 index 0000000..378b6a2 --- /dev/null +++ b/control @@ -0,0 +1,23 @@ +Source: octave-arduino +Section: math +Priority: optional +Maintainer: Debian Octave Group +Uploaders: Rafael Laboissière +Build-Depends: debhelper-compat (= 13), + dh-octave (>= 0.6.1), + texlive +Standards-Version: 4.5.1 +Homepage: https://octave.sourceforge.io/arduino/ +Vcs-Git: https://salsa.debian.org/pkg-octave-team/octave-arduino.git +Vcs-Browser: https://salsa.debian.org/pkg-octave-team/octave-arduino +Rules-Requires-Root: no + +Package: octave-arduino +Architecture: all +Depends: ${misc:Depends}, + ${octave:Depends}, + arduino +Description: Octave Arduino Toolkit + ${octave:Upstream-Description} + . + This Octave add-on package is part of the Octave-Forge project. diff --git a/copyright b/copyright new file mode 100644 index 0000000..6924e38 --- /dev/null +++ b/copyright @@ -0,0 +1,51 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ + +Files: * +Copyright: 2018-2020 John Donoghue +License: GPL-3+ + +Files: doc/arduino.texi +Copyright: 2018-2021 John Donoghue +License: other + 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. + +Files: octave-arduino.metainfo.xml +Copyright: 2016 Colin B. Macdonald + 2018 John Donoghue +License: FSFAP + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. This file is offered as-is, + without any warranty. + +Files: debian/* +Copyright: 2018-2021 Rafael Laboissiere +License: GPL-3+ + +License: GPL-3+ + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + . + This program is distributed in the hope that it will be useful, + but WITHOUT 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 . + . + On Debian systems, the complete text of the GNU General Public + License, version 3, can be found in the file + `/usr/share/common-licenses/GPL-3'. diff --git a/gbp.conf b/gbp.conf new file mode 100644 index 0000000..6b65fe0 --- /dev/null +++ b/gbp.conf @@ -0,0 +1,4 @@ +[DEFAULT] +debian-branch = debian/latest +upstream-branch = upstream/latest +pristine-tar = True diff --git a/octave-arduino.doc-base b/octave-arduino.doc-base new file mode 100644 index 0000000..9fdbfc5 --- /dev/null +++ b/octave-arduino.doc-base @@ -0,0 +1,12 @@ +Document: octave-arduino-manual +Title: Arduino Toolbox for Octave +Author: John Donoghue +Abstract: Documentation for the Arduino Package for GNU Octave +Section: Science/Mathematics + +Format: PDF +Files: /usr/share/doc/octave-arduino/arduino.pdf.gz + +Format: HTML +Files: /usr/share/doc/octave-arduino/arduino.html +Index: /usr/share/doc/octave-arduino/arduino.html diff --git a/octave-arduino.docs b/octave-arduino.docs new file mode 100644 index 0000000..f735da5 --- /dev/null +++ b/octave-arduino.docs @@ -0,0 +1,2 @@ +doc/arduino.pdf +doc/arduino.html diff --git a/octave-arduino.info b/octave-arduino.info new file mode 100644 index 0000000..7e21e67 --- /dev/null +++ b/octave-arduino.info @@ -0,0 +1 @@ +doc/arduino.info diff --git a/rules b/rules new file mode 100755 index 0000000..348858a --- /dev/null +++ b/rules @@ -0,0 +1,17 @@ +#!/usr/bin/make -f +# -*- makefile -*- + +### Disable unit testing. The tests fail massively because most of +### them needs an Arduino system connected to the system. +export DEB_BUILD_MAINT_OPTIONS = nocheck + +%: + dh $@ --buildsystem=octave --with=octave + +ifeq (,$(filter nodoc,$(DEB_BUILD_OPTIONS))) +execute_before_dh_auto_build: + ( cd doc ; \ + makeinfo --no-split arduino.texi ; \ + makeinfo --html --no-split arduino.texi ; \ + texi2pdf arduino.texi || true ) +endif diff --git a/source/format b/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/source/options b/source/options new file mode 100644 index 0000000..27140ec --- /dev/null +++ b/source/options @@ -0,0 +1 @@ +extend-diff-ignore=doc/arduino\.pdf diff --git a/tests/control b/tests/control new file mode 100644 index 0000000..d2cbc3e --- /dev/null +++ b/tests/control @@ -0,0 +1,2 @@ +Tests: no-test +Restrictions: superficial diff --git a/tests/no-test b/tests/no-test new file mode 100644 index 0000000..1251ba1 --- /dev/null +++ b/tests/no-test @@ -0,0 +1,8 @@ +#!/bin/sh + +### The unit tests contained in the octave-arduino package needs an +### Arduino board connected to the system, in order to be run. This is +### not appropriate for the CI/autopkgtest Debian infrastructure, hence +### this empty test script. + +exit 0 diff --git a/upstream/metadata b/upstream/metadata new file mode 100644 index 0000000..7c353e6 --- /dev/null +++ b/upstream/metadata @@ -0,0 +1,3 @@ +Bug-Database: https://savannah.gnu.org/bugs/?group=octave +Bug-Submit: https://savannah.gnu.org/bugs/?func=additem&group=octave +Repository-Browse: https://octave.sourceforge.io/pkg-repository/arduino/ diff --git a/watch b/watch new file mode 100644 index 0000000..35bb2f6 --- /dev/null +++ b/watch @@ -0,0 +1,2 @@ +version=4 +http://sf.net/octave/arduino-(.+)\.tar\.gz -- cgit v1.2.3