diff --git a/.gitignore b/.gitignore index 9ac0ec3..0c70bf8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ -# Build Folders (you can keep bin if you'd like, to store dlls and pdbs) -bin -obj - -# mstest test results -TestResults \ No newline at end of file +# Build Folders (you can keep bin if you'd like, to store dlls and pdbs) +bin +obj + +# mstest test results +TestResults + +RaspberryPiDotNet.suo \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..22fbe5d --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,339 @@ +GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. 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. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE 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. + + 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 +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {description} + Copyright (C) {year} {fullname} + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision 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, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + {signature of Ty Coon}, 1 April 1989 + Ty Coon, President of Vice + +This 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. \ No newline at end of file diff --git a/README.md b/README.md index ffa276a..37a1b40 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,159 @@ RaspberryPi.Net =============== -Raspberry PI .NET library \ No newline at end of file +Introduction +------------ +The purpose of this library is to provide a Mono.NET interface to the GPIO pins +on the Raspberry Pi. All of this code was written using Visual Studio 2010 +Express but the goal is to be fully compatible with Mono. This library is +written using .NET 4.0 therefore the latest version of Mono (2.10) is +recommended. At the time of this update, the Raspbian wheezy 2012-07-15 image +installs Mono 2.10.8.1. + +The GPIO pins are best described +[here](http://elinux.org/Rpi_Low-level_peripherals#General_Purpose_Input.2FOutput_.28GPIO.29). +They can be accessed in 2 ways, either using the file-based I/O (GPIOFile.cs) +or direct memory (GPIOMem.cs) using Mike McCauley's BCM2835 library which is +available [here](http://www.open.com.au/mikem/bcm2835/index.html). There is +also a GPIODebug.cs class that can be used to test your application without a +Raspberry Pi. + +Here is a sample bit of code to blink an LED attached to pin 12 +```C# +using System; +using RaspberryPiDotNet; + +namespace Test +{ + class Program + { + static void Main(string[] args) + { + GPIOMem led = new GPIOMem(GPIOPins.V2_GPIO_12) + while(true) + { + led.Write(PinState.High); + System.Threading.Thread.Sleep(500); + led.Write(PinState.Low); + System.Threading.Thread.Sleep(500); + } + } + } +} +``` + +Installing Mono +--------------- +To install Mono on your Raspberry Pi, run the following: +```bash +$ sudo aptitude update +$ sudo aptitude install mono-runtime +``` + +My preference is for aptitude, however, apt-get can also be used. + +Using GPIOMem +------------- +The GPIOMem class uses the .NET Interop layer to expose C functions from Mike +McCauley''s BCM2835 library. This requires the use of a separate shared object +(.so) but this library is considerably faster than the GPIOFile method. + +The Makefile for his library compiles a shared object where a statically linked +library is required. To compile a statically linked binary, do the following: + +```bash +# tar -zxf bcm2835-1.3.tar.gz +# cd bcm2835-1.3/src +# make libbcm2835.a +# cc -shared bcm2835.o -o libbcm2835.so +``` + +You can also try using our own compiled file [here](https://www.dropbox.com/s/716brdf0owbx4tf/libbcm2835.so). If it doesn't work, you must compile yourself. It must be in the same folder as the application. + +Liquid Crystal Display +---------------------- +This class is a port of the MicroLiquidCrystal NetDuino library from +[here](http://microliquidcrystal.codeplex.com). It provides an interface to +address HD44780 compatible displays. + +Example code: +```C# +RaspPiGPIOMemLcdTransferProvider lcdProvider = new RaspPiGPIOMemLcdTransferProvider( + GPIOPins.Pin_P1_21, + GPIOPins.Pin_P1_18, + GPIOPins.Pin_P1_11, + GPIOPins.Pin_P1_13, + GPIOPins.Pin_P1_15, + GPIOPins.Pin_P1_19); + + +Lcd lcd = new Lcd(lcdProvider); +lcd.Begin(16, 2); +lcd.Clear(); +lcd.SetCursorPosition(0, 0); +lcd.Write("Hello World!"); +``` + +Using MCP3008 +------------- +This class is a port of a Python Script by Mikey Sklar +[here](https://raw.github.com/gist/3249416/7689f68f3ddbb74aceecda23e395c729668bd520/adafruit-cosm-temp.py). +It provides analog to digital conversion to the Raspberry Pi. + +The following example shows how to connect an analog temperature sensor to the Pi. + +Example code: +```C# +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using RaspberryPiDotNet; + +namespace RPi_Temperature +{ + class Program + { + static void Main(string[] args) + { + //# set up the SPI interface pins + //# SPI port on the ADC to the Cobbler + GPIOMem SPICLK = new GPIOMem(GPIOPins.Pin_P1_18, GPIODirection.Out); + GPIOMem SPIMISO = new GPIOMem(GPIOPins.Pin_P1_23, GPIODirection.In); + GPIOMem SPIMOSI = new GPIOMem(GPIOPins.Pin_P1_24, GPIODirection.Out); + GPIOMem SPICS = new GPIOMem(GPIOPins.Pin_P1_22, GPIODirection.Out); + + // temperature sensor connected to channel 0 of mcp3008 + int adcnum = 0; + double read_adc0 = 0.0; + + while (true) + { + MCP3008 MCP3008 = new MCP3008(adcnum, SPICLK, SPIMOSI, SPIMISO, SPICS); + // read the analog pin (temperature sensor LM35) + read_adc0 = MCP3008.AnalogToDigital; + double millivolts = Convert.ToDouble(read_adc0) * (3300.0 / 1024); + + double volts = (Convert.ToDouble(read_adc0) / 1024.0f) * 3.3f; + double temp_C = ((millivolts - 100.0) / 10.0) - 40.0; + double temp_F = (temp_C * 9.0 / 5.0) + 32; + +# if DEBUG + System.Console.WriteLine("MCP3008_Channel: " + adcnum); + System.Console.WriteLine("read_adc0: " + read_adc0); + System.Console.WriteLine("millivolts: " + (float)millivolts); + System.Console.WriteLine("tempC: " + (float)temp_C); + System.Console.WriteLine("tempF: " + (float)temp_F); + System.Console.WriteLine("volts: " + (float)volts); + //The following line makes the trick on Raspberry Pi for displaying DateTime.Now + //equivalent. + Console.WriteLine("Date time stamp: {0}/{1}/{2} {3}:{4}:{5}",now.Month,now.Day,now.Year, + now.Hour,now.Minute,now.Second); + System.Console.WriteLine("\n"); +# endif + Thread.Sleep(3000); + } + } + } +} +``` diff --git a/RaspberryPiDotNet.sln.docstates.suo b/RaspberryPiDotNet.sln.docstates.suo new file mode 100644 index 0000000..f067a31 Binary files /dev/null and b/RaspberryPiDotNet.sln.docstates.suo differ diff --git a/RaspberryPiDotNet.suo b/RaspberryPiDotNet.suo index 4e36650..8ee3d78 100644 Binary files a/RaspberryPiDotNet.suo and b/RaspberryPiDotNet.suo differ diff --git a/RaspberryPiDotNet/DS1620.cs b/RaspberryPiDotNet/DS1620.cs index 05e6c83..224c241 100644 --- a/RaspberryPiDotNet/DS1620.cs +++ b/RaspberryPiDotNet/DS1620.cs @@ -1,10 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; - -// Derived based on work done by AdamS at http://forums.netduino.com/index.php?/topic/3335-netduino-plus-and-ds1620-anyone/page__view__findpost__p__22972 +using System; +using System.Threading; + +// Derived based on work done by AdamS at http://forums.netduino.com/index.php?/topic/3335-netduino-plus-and-ds1620-anyone/page__view__findpost__p__22972 + namespace RaspberryPiDotNet { public class DS1620 @@ -37,11 +35,11 @@ public double Temperature /// The command private void SendCommand(int command) { - // Sends 8 bit command on DQ output, least sig bit first - int n, bit; + // Sends 8 bit command on DQ output, least sig bit first + int n; for (n = 0; n < 8; n++) { - bit = ((command >> n) & (0x01)); + var bit = ((command >> n) & (0x01)); _dq.Write((bit == 1)); _clk.Write(false); _clk.Write(true); @@ -53,17 +51,14 @@ private void SendCommand(int command) /// /// The temperature in half degree increments private int ReadData() - { - int bit, n; - int raw_data = 0; // go into input mode + { + int n; + var raw_data = 0; // go into input mode for (n = 0; n < 9; n++) { _clk.Write(false); - if (_dq.Read() == true) - bit = 1; - else - bit = 0; + var bit = _dq.Read() == PinState.High ? 1 : 0; _clk.Write(true); raw_data = raw_data | (bit << n); } diff --git a/RaspberryPiDotNet/GPIO.cs b/RaspberryPiDotNet/GPIO.cs index e06ec31..e75ce90 100644 --- a/RaspberryPiDotNet/GPIO.cs +++ b/RaspberryPiDotNet/GPIO.cs @@ -1,143 +1,241 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; // Author: Aaron Anderson + namespace RaspberryPiDotNet { - /// - /// Abstract class for the GPIO connector on the Pi (P1) (as found next to the yellow RCA video socket on the Rpi circuit board) - /// - public abstract class GPIO : IDisposable - { - /// - /// Refer to http://elinux.org/Rpi_Low-level_peripherals for diagram. - /// P1-01 = bottom left, P1-02 = top left - /// pi connector P1 pin = GPIOnum - /// P1-03 = GPIO0 - /// P1-05 = GPIO1 - /// P1-07 = GPIO4 - /// P1-08 = GPIO14 - alt function (UART0_TXD) on boot-up - /// P1-10 = GPIO15 - alt function (UART0_TXD) on boot-up - /// P1-11 = GPIO17 - /// P1-12 = GPIO18 - /// P1-13 = GPIO21 - /// P1-15 = GPIO22 - /// P1-16 = GPIO23 - /// P1-18 = GPIO24 - /// P1-19 = GPIO10 - /// P1-21 = GPIO9 - /// P1-22 = GPIO25 - /// P1-23 = GPIO11 - /// P1-24 = GPIO8 - /// P1-26 = GPIO7 - /// So to turn on Pin7 on the GPIO connector, pass in enumGPIOPIN.gpio4 as the pin parameter - /// - public enum GPIOPins - { - GPIO_NONE = -1, - GPIO00 = 0, - GPIO01 = 1, - GPIO04 = 4, - GPIO07 = 7, - GPIO08 = 8, - GPIO09 = 9, - GPIO10 = 10, - GPIO11 = 11, - GPIO14 = 14, - GPIO15 = 15, - GPIO17 = 17, - GPIO18 = 18, - GPIO21 = 21, - GPIO22 = 22, - GPIO23 = 23, - GPIO24 = 24, - GPIO25 = 25, - Pin03 = 0, - Pin05 = 1, - Pin07 = 4, - Pin08 = 14, - Pin10 = 15, - Pin11 = 17, - Pin12 = 18, - Pin13 = 21, - Pin15 = 22, - Pin16 = 23, - Pin18 = 24, - Pin19 = 10, - Pin21 = 9, - Pin22 = 25, - Pin23 = 11, - Pin24 = 8, - Pin26 = 7 - }; + /// + /// Abstract class for the GPIO connector on the Pi (P1) (as found next to the yellow RCA video socket on the Rpi circuit board) + /// + public abstract class GPIO : IDisposable + { + /// + /// Dictionary that stores created (exported) pins that where not disposed. + /// + private static Dictionary _exportedPins = new Dictionary(); - /// - /// Specifies the direction of the GPIO port - /// - public enum DirectionEnum { IN, OUT }; + /// + /// The currently assigned GPIO pin. Used for class methods. + /// + protected readonly GPIOPins _pin; - /// - /// Dictionary that stores whether a pin is setup or not - /// - protected static Dictionary _exportedPins = new Dictionary(); + /// + /// Variable to track the disposed state + /// + private bool _disposed = false; /// - /// The currently assigned GPIO pin. Used for class methods and not static methods. + /// Direction of the GPIO pin /// - protected GPIOPins _pin; + private GPIODirection _direction; /// - /// Access to the specified GPIO setup as an output port with an initial value of false (0) + /// GPIO pull up-down resistor /// - /// The GPIO pin - public GPIO(GPIOPins pin) - : this(pin,DirectionEnum.OUT,false) - { - } + // BCM2835_GPIO_PUD_OFF = 0b00 = 0 + // BCM2835_GPIO_PUD_DOWN = 0b01 = 1 + // BCM2835_GPIO_PUD_UP = 0b10 = 2 + public GPIOResistor _resistor = GPIOResistor.OFF; - /// - /// Access to the specified GPIO setup with the specified direction with an initial value of false (0) - /// - /// The GPIO pin - /// Direction - public GPIO(GPIOPins pin, DirectionEnum direction) - : this(pin, direction, false) - { - } + /// + /// Gets the pin that this GPIO instance represents + /// + public GPIOPins Pin { + get { + if (_disposed) + throw new ObjectDisposedException(string.Empty); + return _pin; + } + } + + /// + /// Gets the bit mask of this pin. + /// + public GPIOPinMask Mask { + get { + return (GPIOPinMask)(1 << (ushort)Pin); //Pin-Value has a low range (0-~32), so even casting to byte would be ok. + } + } + + /// + /// Gets or sets the communication direction for this pin + /// + public virtual GPIODirection PinDirection { + get { + if (_disposed) + throw new ObjectDisposedException(string.Empty); + return _direction; + } + set { + if (_disposed) + throw new ObjectDisposedException(string.Empty); + _direction = value; + } + } /// - /// Access to the specified GPIO setup with the specified direction with the specified initial value + /// Gets or sets the internal resistor value for the pin /// - /// The GPIO pin - /// Direction - /// Initial Value - public GPIO(GPIOPins pin, DirectionEnum direction, bool initialValue) + public virtual GPIOResistor Resistor { - this._pin = pin; + get + { + if (_disposed) + throw new ObjectDisposedException(string.Empty); + return _resistor; + } + set + { + if (_disposed) + throw new ObjectDisposedException(string.Empty); + _resistor = value; + } } - protected static string GetGPIONumber(GPIOPins pin) - { - return ((int)pin).ToString(); //e.g. returns 17 for enum value of gpio17 - } + /// + /// Gets the disposal state of this GPIO instance + /// + public bool IsDisposed { + get { + return _disposed; + } + } - /// - /// Write a value to the pin - /// - /// The value to write to the pin - public abstract void Write(bool value); + /// + /// Access to the specified GPIO setup with the specified direction with the specified initial value + /// + /// The GPIO pin + /// Direction + /// Initial Value + protected GPIO(GPIOPins pin, GPIODirection direction, bool initialValue) { + if (pin == GPIOPins.GPIO_NONE) throw new ArgumentException("Invalid pin"); + lock (_exportedPins) { + if (_exportedPins.ContainsKey(pin)) + throw new Exception("Cannot use pin with multiple instances. Unexport the previous instance with Dispose() first! (pin " + (uint)pin + ")"); + _exportedPins[pin] = this; - /// - /// Read a value from the pin - /// - /// The value read from the pin - public abstract bool Read(); + _pin = pin; + try { + PinDirection = direction; + Write(initialValue); + } + catch { + Dispose(); + throw; + } + } + } - /// - /// Dispose of the GPIO pin - /// - public abstract void Dispose(); - } + /// + /// Finalizer to make sure we cleanup after ourselves. + /// + ~GPIO() { + if (!_disposed) + Dispose(); + } + + /// + /// Sets a pin to output the give value. + /// + /// Creates (exports) the pin if needed, and sets it to Out direction. + /// + /// The pin who's value to set + /// The value to set + public static void Write(GPIOPins pin, bool value) { + CreatePin(pin, GPIODirection.Out).Write(value); + } + + /// + /// Gets the value of a given pin. + /// + /// Creates (exports) the pin if needed, and sets it to In direction. + /// + /// The pin who's value to get + /// The value of the pin + public static PinState Read(GPIOPins pin) { + return CreatePin(pin, GPIODirection.In).Read(); + } + + /// + /// Creates a pin if it has not already been created (exported), creates a GPIOMem if possible, otherwise falls back to GPIOFile. + /// + /// The pin to create or export + /// The direction the pin is to have + /// The GPIO instance representing the pin + public static GPIO CreatePin(GPIOPins pin, GPIODirection dir) { + lock (_exportedPins) + if (_exportedPins.ContainsKey(pin)) { + if (_exportedPins[pin].PinDirection != dir) + _exportedPins[pin].PinDirection = dir; + return _exportedPins[pin]; + } + + try { + return new GPIOMem(pin, dir); + } +#if DEBUG + catch (Exception e) { + System.Diagnostics.Debug.WriteLine("Unable to create pin " + (uint)pin + " as GPIOMem because: " + e.ToString()); + } +#else + catch //stuff like lib load problems, wrong exports, etc... + { + } +#endif + try { + return new GPIOFile(pin, dir); + } +#if DEBUG + catch (Exception e) { + System.Diagnostics.Debug.WriteLine("Unable to create pin " + (uint)pin + " as GPIOFile because: " + e.ToString()); + } +#else + catch //stuff like GPIO Sys FS does not exist or is not responding, open by another process, etc... + { + } +#endif + +#if DEBUG + System.Diagnostics.Debug.WriteLine("Using debug GPIO pin for pin number " + (uint)pin); + return new GPIODebug(pin, dir); +#else + throw new Exception("Cannot access GPIO pin " + (uint)pin + ". Make sure libbcm2835.so is accessible, or that GPIO SYSFS is working and not in use by another process"); +#endif + } + + /// + /// Write a value to the pin + /// + /// The value to write to the pin + public virtual void Write(bool value) { + if (IsDisposed) + throw new ObjectDisposedException(string.Empty); + if (_direction != GPIODirection.Out) + PinDirection = GPIODirection.Out; + } + + /// + /// Read a value from the pin + /// + /// The value read from the pin + public virtual PinState Read() { + if (IsDisposed) + throw new ObjectDisposedException(string.Empty); + return PinState.Low; + } + + /// + /// Dispose of the GPIO pin + /// + public virtual void Dispose() { + if (_disposed) + throw new ObjectDisposedException(string.Empty); + + _disposed = true; + lock (_exportedPins) { + _exportedPins.Remove(_pin); + } + } + } } diff --git a/RaspberryPiDotNet/GPIODebug.cs b/RaspberryPiDotNet/GPIODebug.cs new file mode 100644 index 0000000..f00aa0d --- /dev/null +++ b/RaspberryPiDotNet/GPIODebug.cs @@ -0,0 +1,67 @@ +namespace RaspberryPiDotNet +{ + /// + /// Raspberry Pi GPIO debug class. + /// +// ReSharper disable once InconsistentNaming + public class GPIODebug : GPIO + { + private bool _currentValue; + + #region Constructor + /// + /// Access to the specified GPIO setup as an output port with an initial value of false (0) + /// + /// The GPIO pin + public GPIODebug(GPIOPins pin) + : this(pin,GPIODirection.Out,false) + { + } + + /// + /// Access to the specified GPIO setup with the specified direction with an initial value of false (0) + /// + /// The GPIO pin + /// Direction + public GPIODebug(GPIOPins pin, GPIODirection direction) + : this(pin, direction, false) + { + } + + /// + /// Access to the specified GPIO setup with the specified direction with the specified initial value + /// + /// The GPIO pin + /// Direction + /// Initial Value + public GPIODebug(GPIOPins pin, GPIODirection direction, bool initialValue) + : base(pin, direction, initialValue) + { + } + #endregion + + #region Class Methods + /// + /// Write a value to the pin + /// + /// The value to write to the pin + public override void Write(bool value) + { + System.Diagnostics.Debug.WriteLine("GPIO pin " + _pin + " set to " + value); + base.Write(value); + _currentValue = value; + } + + /// + /// Read a value from the pin + /// + /// The value read from the pin + public override PinState Read() + { + System.Diagnostics.Debug.WriteLine("GPIO pin " + _pin + " reads as " + _currentValue); + base.Read(); + return _currentValue ? PinState.High : PinState.Low; + } + #endregion + } +} diff --git a/RaspberryPiDotNet/GPIODirection.cs b/RaspberryPiDotNet/GPIODirection.cs new file mode 100644 index 0000000..1333a17 --- /dev/null +++ b/RaspberryPiDotNet/GPIODirection.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace RaspberryPiDotNet +{ + /// + /// Specifies the direction of the GPIO port + /// + public enum GPIODirection { In, Out }; +} diff --git a/RaspberryPiDotNet/GPIOFile.cs b/RaspberryPiDotNet/GPIOFile.cs index 0f1665c..f0e0fa5 100644 --- a/RaspberryPiDotNet/GPIOFile.cs +++ b/RaspberryPiDotNet/GPIOFile.cs @@ -1,22 +1,20 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Diagnostics; -using System.IO; +using System.IO; // Author: Aaron Anderson // Based on work done by x4m and britguy (http://www.raspberrypi.org/phpBB3/viewtopic.php?f=34&t=6720) + namespace RaspberryPiDotNet { /// /// Raspberry Pi GPIO using the file-based access method. /// - public class GPIOFile : GPIO, IDisposable + // ReSharper disable once InconsistentNaming + public class GPIOFile : GPIO { /// /// The path on the Raspberry Pi for the GPIO interface /// + // ReSharper disable once InconsistentNaming private const string GPIO_PATH = "/sys/class/gpio/"; #region Constructor @@ -25,7 +23,7 @@ public class GPIOFile : GPIO, IDisposable /// /// The GPIO pin public GPIOFile(GPIOPins pin) - : base(pin,DirectionEnum.OUT,false) + : this(pin,GPIODirection.Out,false) { } @@ -34,10 +32,9 @@ public GPIOFile(GPIOPins pin) /// /// The GPIO pin /// Direction - public GPIOFile(GPIOPins pin, DirectionEnum direction) - : base(pin, direction, false) + public GPIOFile(GPIOPins pin, GPIODirection direction) + : this(pin, direction, false) { - ExportPin(pin, direction); } /// @@ -46,140 +43,68 @@ public GPIOFile(GPIOPins pin, DirectionEnum direction) /// The GPIO pin /// Direction /// Initial Value - public GPIOFile(GPIOPins pin, DirectionEnum direction, bool initialValue) + public GPIOFile(GPIOPins pin, GPIODirection direction, bool initialValue) : base(pin, direction, initialValue) { - ExportPin(pin, direction); - Write(pin, initialValue); } - ~GPIOFile() - { - UnexportPin(_pin); - } #endregion - #region Static Methods - /// - /// Export the GPIO setting the direction. This creates the /sys/class/gpio/gpioXX directory. - /// - /// The GPIO pin - /// - private static void ExportPin(GPIOPins pin, DirectionEnum direction) - { - // If the pin is already exported, check it's in the proper direction - if (_exportedPins.Keys.Contains((int)pin)) - // If the direction matches, return out of the function. If not, change the direction - if (_exportedPins[(int)pin] == direction) - return; - else - { - // Set the direction on the pin and update the exported list - File.WriteAllText(GPIO_PATH + "gpio" + GetGPIONumber(pin) + "/direction", direction.ToString().ToLower()); - _exportedPins[(int)pin] = direction; - return; - } - - if (!Directory.Exists(GPIO_PATH + "gpio" + GetGPIONumber(pin))) - { - Debug.WriteLine("Exporting " + GetGPIONumber(pin)); - //export - File.WriteAllText(GPIO_PATH + "export", GetGPIONumber(pin)); - } - - // set i/o direction - Debug.WriteLine("Setting direction on pin " + pin + "/gpio " + (int)pin + " as " + direction); - File.WriteAllText(GPIO_PATH + "gpio" + GetGPIONumber(pin) + "/direction", direction.ToString().ToLower()); - - // Update the list of exported pins - _exportedPins[(int)pin] = direction; - } - - /// - /// Unexport the GPIO. This removes the /sys/class/gpio/gpioXX directory. - /// - /// The pin to unexport - private static void UnexportPin(GPIOPins pin) - { - Debug.WriteLine("unexporting pin " + pin); - File.WriteAllText(GPIO_PATH + "unexport", GetGPIONumber(pin)); - - // Remove the pin from the list of exported pins - _exportedPins.Remove((int)pin); - } + #region Properties + + /// + /// Gets or sets the communication direction for this pin + /// + public override GPIODirection PinDirection + { + get + { + return base.PinDirection; + } + set + { + if (PinDirection != (base.PinDirection = value)) // Left to right eval ensures base class gets to check for disposed object access + { + if (!Directory.Exists(GPIO_PATH + "gpio" + (uint)_pin)) + File.WriteAllText(GPIO_PATH + "export", ((uint)_pin).ToString()); + + // set i/o direction + File.WriteAllText(GPIO_PATH + "gpio" + (uint)_pin + "/direction", value.ToString().ToLower()); + } + } + } + + #endregion + #region Class Methods /// - /// Static method to write a value to the specified pin. When using the static methods ensure you use the CleanUp() method when done. + /// Write a value to the pin /// - /// The GPIO pin /// The value to write to the pin - public static void Write(GPIOPins pin, bool value) - { - if (pin == GPIOPins.GPIO_NONE) - return; - - ExportPin(pin, DirectionEnum.OUT); - - string writeValue = value ? "1" : "0"; - File.WriteAllText(GPIO_PATH + "gpio" + GetGPIONumber(pin) + "/value", writeValue); - Debug.WriteLine("output to pin " + pin + "/gpio " + (int)pin + ", value was " + value); - } - - /// - /// Static method to read a value to the specified pin. When using the static methods ensure you use the CleanUp() method when done. - /// - /// The GPIO pin - /// The value read from the pin - public static bool Read(GPIOPins pin) - { - bool returnValue = false; - - ExportPin(pin, DirectionEnum.IN); - - string filename = GPIO_PATH + "gpio" + GetGPIONumber(pin) + "/value"; - if (File.Exists(filename)) - { - string readValue = File.ReadAllText(filename); - if (readValue.Length > 0 && readValue[0] == '1') - returnValue = true; - } - else - throw new Exception(string.Format("Cannot read from {0}. File does not exist", pin)); - - Debug.WriteLine("input from pin " + pin + "/gpio " + (int)pin + ", value was " + returnValue); - - return returnValue; - } - - public static void CleanUp() + public override void Write(bool value) { - // Loop over all exported pins and unexported them - foreach (GPIOPins pin in _exportedPins.Keys) - { - UnexportPin(pin); - } + base.Write(value); + File.WriteAllText(GPIO_PATH + "gpio" + (uint)_pin + "/value", value ? "1" : "0"); } - #endregion - #region Class Methods /// /// Write a value to the pin /// /// The value to write to the pin - public override void Write(bool value) + public void Write(PinState value) { - // Call the static method - Write(_pin, value); + Write(value == PinState.High); } /// /// Read a value from the pin /// /// The value read from the pin - public override bool Read() + public override PinState Read() { - // Call the static method - return Read(_pin); + base.Read(); + var readValue = File.ReadAllText(GPIO_PATH + "gpio" + (uint)_pin + "/value"); + return (readValue.Length > 0 && readValue[0] == '1') ? PinState.High : PinState.Low; } /// @@ -187,7 +112,8 @@ public override bool Read() /// public override void Dispose() { - UnexportPin(_pin); + base.Dispose(); + File.WriteAllText(GPIO_PATH + "unexport", ((uint)_pin).ToString()); } #endregion } diff --git a/RaspberryPiDotNet/GPIOMem.cs b/RaspberryPiDotNet/GPIOMem.cs index c39d14a..d656eb5 100644 --- a/RaspberryPiDotNet/GPIOMem.cs +++ b/RaspberryPiDotNet/GPIOMem.cs @@ -1,176 +1,176 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Runtime.InteropServices; -using System.Diagnostics; namespace RaspberryPiDotNet { - /// - /// Raspberry Pi GPIO using the direct memory access method. - /// This requires the bcm2835 GPIO library provided by - /// Mike McCauley (mikem@open.com.au) at http://www.open.com.au/mikem/bcm2835/index.html. - /// - /// To create the shared object, download the source code from the link above. The standard Makefile compiles a - /// statically linked library. To build a shared object, do: - /// tar -zxf bcm2835-1.3.tar.gz - /// cd bcm2835-1.3/src - /// make libbcm2835.a - /// cc -shared bcm2835.o -o libbcm2835.so - /// - public class GPIOMem : GPIO, IDisposable - { - private static bool _initialized = false; - - #region Constructor - /// - /// Access to the specified GPIO setup as an output port with an initial value of false (0) - /// - /// The GPIO pin - public GPIOMem(GPIOPins pin) - : base(pin,DirectionEnum.OUT,false) - { - } - - /// - /// Access to the specified GPIO setup with the specified direction with an initial value of false (0) - /// - /// The GPIO pin - /// Direction - public GPIOMem(GPIOPins pin, DirectionEnum direction) - : base(pin, direction, false) - { - ExportPin(pin, direction); - } - - /// - /// Access to the specified GPIO setup with the specified direction with the specified initial value - /// - /// The GPIO pin - /// Direction - /// Initial Value - public GPIOMem(GPIOPins pin, DirectionEnum direction, bool initialValue) - : base(pin, direction, initialValue) - { - ExportPin(pin, direction); - Write(pin, initialValue); - } - #endregion + /// + /// Raspberry Pi GPIO using the direct memory access method. + /// This requires the bcm2835 GPIO library provided by + /// Mike McCauley (mikem@open.com.au) at http://www.open.com.au/mikem/bcm2835/index.html. + /// + /// To create the shared object, download the source code from the link above. The standard Makefile compiles a + /// statically linked library. To build a shared object, do: + /// tar -zxf bcm2835-1.3.tar.gz + /// cd bcm2835-1.3/src + /// make libbcm2835.a + /// cc -shared bcm2835.o -o libbcm2835.so + /// Place the shared object in the same directory as the executable and other assemblies. + /// + public class GPIOMem : GPIO + { + #region Static Constructor + static GPIOMem() { + // initialize the mapped memory + if (!bcm2835_init()) + throw new Exception("Unable to initialize bcm2835.so library"); + } + #endregion + + #region Constructor + /// + /// Access to the specified GPIO setup as an output port with an initial value of false (0) + /// + /// The GPIO pin + public GPIOMem(GPIOPins pin) + : this(pin, GPIODirection.Out, false) { + } + + /// + /// Access to the specified GPIO setup with the specified direction with an initial value of false (0) + /// + /// The GPIO pin + /// Direction + public GPIOMem(GPIOPins pin, GPIODirection direction) + : this(pin, direction, false) { + } + + /// + /// Access to the specified GPIO setup with the specified direction with the specified initial value + /// + /// The GPIO pin + /// Direction + /// Initial Value + public GPIOMem(GPIOPins pin, GPIODirection direction, bool initialValue) + : base(pin, direction, initialValue) { + } + #endregion + + #region Properties + /// + /// Gets or sets the communication direction for this pin + /// + public override GPIODirection PinDirection { + get { + return base.PinDirection; + } + set { + if (PinDirection != (base.PinDirection = value)) // Left to right eval ensures base class gets to check for disposed object access + { + // Set the direction on the pin + bcm2835_gpio_fsel(_pin, value == GPIODirection.Out); + if (value == GPIODirection.In) + Resistor = GPIOResistor.OFF; + } + } + } - #region Static Methods /// - /// Initialize the memory access to the GPIO + /// Gets or sets the internal resistor value for the pin /// - /// - private static bool Initialize() + public override GPIOResistor Resistor { - int ret = 1; - if (!_initialized) - { - // initialize the mapped memory - ret = bcm2835_init(); - _initialized = true; + get { + return base.Resistor; } - - return ret == 0 ? false : true; - } - - /// - /// Export the GPIO setting the direction. This creates the /sys/class/gpio/gpioXX directory. - /// - /// The GPIO pin - /// - private static void ExportPin(GPIOPins pin, DirectionEnum direction) - { - Initialize(); - - // If the pin is already exported, check it's in the proper direction - if (_exportedPins.Keys.Contains((int)pin)) - // If the direction matches, return out of the function. If not, change the direction - if (_exportedPins[(int)pin] == direction) - return; - else + set { + if (Resistor != (base.Resistor = value)) // Left to right eval ensures base class gets to check for disposed object access { - // Set the direction on the pin and update the exported list - bcm2835_gpio_fsel((uint)pin, direction == DirectionEnum.IN ? (uint)0 : (uint)1); - _exportedPins[(int)pin] = direction; - return; + bcm2835_gpio_set_pud(_pin, (uint)value); } + } } + #endregion + + #region Class Methods + /// + /// Write a value to the pin + /// + /// The value to write to the pin + public override void Write(bool value) { + base.Write(value); + bcm2835_gpio_write(_pin, value); + } - /// - /// Static method to write a value to the specified pin. - /// - /// The GPIO pin - /// The value to write to the pin - public static void Write(GPIOPins pin, bool value) - { - if (pin == GPIOPins.GPIO_NONE) - return; - - ExportPin(pin, DirectionEnum.OUT); - - bcm2835_gpio_write((uint)pin, value ? (uint)1 : (uint)0); - Debug.WriteLine("output to pin " + pin + "/gpio " + (int)pin + ", value was " + value); - } - - /// - /// Static method to read a value to the specified pin. - /// - /// The GPIO pin - /// The value read from the pin - public static bool Read(GPIOPins pin) - { - ExportPin(pin, DirectionEnum.IN); - - uint value = bcm2835_gpio_lev((uint)pin); - bool returnValue = value == 0 ? false : true; - Debug.WriteLine("input from pin " + pin + "/gpio " + (int)pin + ", value was " + returnValue); - - return returnValue; - } - #endregion - - #region Class Methods /// /// Write a value to the pin /// - /// The value to write to the pin - public override void Write(bool value) + /// + public void Write(PinState pinState) { - Write(_pin, value); + Write(pinState == PinState.High); } - /// - /// Read a value from the pin - /// - /// The value read from the pin - public override bool Read() - { - return Read(_pin); - } - - /// - /// Dispose of the GPIO pin - /// - public override void Dispose() + /// + /// Read a value from the pin + /// + /// The value read from the pin + public override PinState Read() { - } - #endregion - - #region Imported functions - [DllImport("libbcm2835.so", EntryPoint = "bcm2835_init")] - static extern int bcm2835_init(); - - [DllImport("libbcm2835.so", EntryPoint = "bcm2835_gpio_fsel")] - static extern void bcm2835_gpio_fsel(uint pin, uint mode); - - [DllImport("libbcm2835.so", EntryPoint = "bcm2835_gpio_write")] - static extern void bcm2835_gpio_write(uint pin, uint value); - - [DllImport("libbcm2835.so", EntryPoint = "bcm2835_gpio_write")] - static extern uint bcm2835_gpio_lev(uint pin); - #endregion - } + base.Read(); + return bcm2835_gpio_lev(_pin) ? PinState.High : PinState.Low; + } + #endregion + + #region Imported functions + [DllImport("libbcm2835.so", EntryPoint = "bcm2835_init")] + static extern bool bcm2835_init(); + + [DllImport("libbcm2835.so", EntryPoint = "bcm2835_gpio_fsel")] + static extern void bcm2835_gpio_fsel(GPIOPins pin, bool mode_out); + + [DllImport("libbcm2835.so", EntryPoint = "bcm2835_gpio_write")] + static extern void bcm2835_gpio_write(GPIOPins pin, bool value); + + [DllImport("libbcm2835.so", EntryPoint = "bcm2835_gpio_lev")] + static extern bool bcm2835_gpio_lev(GPIOPins pin); + + [DllImport("libbcm2835.so", EntryPoint = "bcm2835_gpio_set_pud")] + static extern void bcm2835_gpio_set_pud(GPIOPins pin, uint pud); + + [DllImport("libbcm2835.so", EntryPoint = "bcm2835_gpio_set_multi")] + static extern void bcm2835_gpio_set_multi(GPIOPinMask mask); + + [DllImport("libbcm2835.so", EntryPoint = "bcm2835_gpio_clr_multi")] + static extern void bcm2835_gpio_clr_multi(GPIOPinMask mask); + + [DllImport("libbcm2835.so", EntryPoint = "bcm2835_gpio_write_multi")] + static extern void bcm2835_gpio_write_multi(GPIOPinMask mask, bool on); + + #endregion + + /// + /// Sets any of the first 32 GPIO output pins specified in the mask to HIGH. + /// + /// Mask of pins to affect. Use eg: (GPIOPinMask.GPIO_00) | GPIOPinMask.GPIO_01) + public static void SetMulti(GPIOPinMask mask) { + bcm2835_gpio_set_multi(mask); + } + + /// + /// Sets any of the first 32 GPIO output pins specified in the mask to LOW. + /// + /// Mask of pins to affect. Use eg: (GPIOPinMask.GPIO_00) | GPIOPinMask.GPIO_01) + public static void ClearMulti(GPIOPinMask mask) { + bcm2835_gpio_clr_multi(mask); + } + + /// + /// Sets any of the first 32 GPIO output pins specified in the mask to value. + /// + /// Mask of pins to affect. Use eg: (GPIOPinMask.GPIO_00) | GPIOPinMask.GPIO_01) + public static void WriteMulti(GPIOPinMask mask, bool value) { + bcm2835_gpio_write_multi(mask, value); + } + + } } diff --git a/RaspberryPiDotNet/GPIOPins.cs b/RaspberryPiDotNet/GPIOPins.cs new file mode 100644 index 0000000..0e488eb --- /dev/null +++ b/RaspberryPiDotNet/GPIOPins.cs @@ -0,0 +1,243 @@ +namespace RaspberryPiDotNet +{ + /// + /// Refer to http://elinux.org/Rpi_Low-level_peripherals for diagram. + /// P1-01 = bottom left, P1-02 = top left + /// pi connector P1 pin = GPIOnum + /// P1-03 = GPIO0 + /// P1-05 = GPIO1 + /// P1-07 = GPIO4 + /// P1-08 = GPIO14 - alt function (UART0_TXD) on boot-up + /// P1-10 = GPIO15 - alt function (UART0_TXD) on boot-up + /// P1-11 = GPIO17 + /// P1-12 = GPIO18 + /// P1-13 = GPIO21 + /// P1-15 = GPIO22 + /// P1-16 = GPIO23 + /// P1-18 = GPIO24 + /// P1-19 = GPIO10 + /// P1-21 = GPIO9 + /// P1-22 = GPIO25 + /// P1-23 = GPIO11 + /// P1-24 = GPIO8 + /// P1-26 = GPIO7 + /// + /// P5-03 = GPI28 + /// P5-04 = GPI29 + /// P5-05 = GPI30 + /// P5-06 = GPI31 + /// + /// So to turn on Pin7 on the GPIO connector, pass in enumGPIOPIN.gpio4 as the pin parameter + /// + public enum GPIOPins : uint + { + + GPIO_NONE = uint.MaxValue, + + //Revision 1 + + GPIO_00 = 0, + GPIO_01 = 1, + GPIO_04 = 4, + GPIO_07 = 7, + GPIO_08 = 8, + GPIO_09 = 9, + GPIO_10 = 10, + GPIO_11 = 11, + GPIO_14 = 14, + GPIO_15 = 15, + GPIO_17 = 17, + GPIO_18 = 18, + GPIO_21 = 21, + GPIO_22 = 22, + GPIO_23 = 23, + GPIO_24 = 24, + GPIO_25 = 25, + + Pin_P1_03 = 0, + Pin_P1_05 = 1, + Pin_P1_07 = 4, + Pin_P1_08 = 14, + Pin_P1_10 = 15, + Pin_P1_11 = 17, + Pin_P1_12 = 18, + Pin_P1_13 = 21, + Pin_P1_15 = 22, + Pin_P1_16 = 23, + Pin_P1_18 = 24, + Pin_P1_19 = 10, + Pin_P1_21 = 9, + Pin_P1_22 = 25, + Pin_P1_23 = 11, + Pin_P1_24 = 8, + Pin_P1_26 = 7, + LED = 16, + + //Revision 2 + + V2_GPIO_00 = 0, + V2_GPIO_02 = 2, + V2_GPIO_03 = 3, + V2_GPIO_01 = 1, + V2_GPIO_04 = 4, + V2_GPIO_07 = 7, + V2_GPIO_08 = 8, + V2_GPIO_09 = 9, + V2_GPIO_10 = 10, + V2_GPIO_11 = 11, + V2_GPIO_14 = 14, + V2_GPIO_15 = 15, + V2_GPIO_17 = 17, + V2_GPIO_18 = 18, + V2_GPIO_21 = 21, + V2_GPIO_22 = 22, + V2_GPIO_23 = 23, + V2_GPIO_24 = 24, + V2_GPIO_25 = 25, + V2_GPIO_27 = 27, + + //Revision 2, new plug P5 + V2_GPIO_28 = 28, + V2_GPIO_29 = 29, + V2_GPIO_30 = 30, + V2_GPIO_31 = 31, + + V2_Pin_P1_03 = 2, + V2_Pin_P1_05 = 3, + V2_Pin_P1_07 = 4, + V2_Pin_P1_08 = 14, + V2_Pin_P1_10 = 15, + V2_Pin_P1_11 = 17, + V2_Pin_P1_12 = 18, + V2_Pin_P1_13 = 27, + V2_Pin_P1_15 = 22, + V2_Pin_P1_16 = 23, + V2_Pin_P1_18 = 24, + V2_Pin_P1_19 = 10, + V2_Pin_P1_21 = 9, + V2_Pin_P1_22 = 25, + V2_Pin_P1_23 = 11, + V2_Pin_P1_24 = 8, + V2_Pin_P1_26 = 7, + V2_LED = 16, + + //Revision 2, new plug P5 + V2_Pin_P5_03 = 28, + V2_Pin_P5_04 = 29, + V2_Pin_P5_05 = 30, + V2_Pin_P5_06 = 31, + + //A+ and B+ pins + V2Plus_Pin_P1_29 = 5, + V2Plus_Pin_P1_31 = 6, + V2Plus_Pin_P1_32 = 12, + V2Plus_Pin_P1_33 = 13, + V2Plus_Pin_P1_35 = 19, + V2Plus_Pin_P1_36 = 16, + V2Plus_Pin_P1_37 = 26, + V2Plus_Pin_P1_38 = 20, + V2Plus_Pin_P1_40 = 21, + + }; + + public enum GPIOPinMask : uint + { + + GPIO_NONE = uint.MaxValue, + + //Revision 1 + + GPIO_00 = 0, + GPIO_01 = 1, + GPIO_04 = 1 << 4, + GPIO_07 = 1 << 7, + GPIO_08 = 1 << 8, + GPIO_09 = 1 << 9, + GPIO_10 = 1 << 10, + GPIO_11 = 1 << 11, + GPIO_14 = 1 << 14, + GPIO_15 = 1 << 15, + GPIO_17 = 1 << 17, + GPIO_18 = 1 << 18, + GPIO_21 = 1 << 21, + GPIO_22 = 1 << 22, + GPIO_23 = 1 << 23, + GPIO_24 = 1 << 24, + GPIO_25 = 1 << 25, + + Pin_P1_03 = 1 << 0, + Pin_P1_05 = 1 << 1, + Pin_P1_07 = 1 << 4, + Pin_P1_08 = 1 << 14, + Pin_P1_10 = 1 << 15, + Pin_P1_11 = 1 << 17, + Pin_P1_12 = 1 << 18, + Pin_P1_13 = 1 << 21, + Pin_P1_15 = 1 << 22, + Pin_P1_16 = 1 << 23, + Pin_P1_18 = 1 << 24, + Pin_P1_19 = 1 << 10, + Pin_P1_21 = 1 << 9, + Pin_P1_22 = 1 << 25, + Pin_P1_23 = 1 << 11, + Pin_P1_24 = 1 << 8, + Pin_P1_26 = 1 << 7, + LED = 1 << 16, + + //Revision 2 + + V2_GPIO_00 = 1 << 0, + V2_GPIO_02 = 1 << 2, + V2_GPIO_03 = 1 << 3, + V2_GPIO_01 = 1 << 1, + V2_GPIO_04 = 1 << 4, + V2_GPIO_07 = 1 << 7, + V2_GPIO_08 = 1 << 8, + V2_GPIO_09 = 1 << 9, + V2_GPIO_10 = 1 << 10, + V2_GPIO_11 = 1 << 11, + V2_GPIO_14 = 1 << 14, + V2_GPIO_15 = 1 << 15, + V2_GPIO_17 = 1 << 17, + V2_GPIO_18 = 1 << 18, + V2_GPIO_21 = 1 << 21, + V2_GPIO_22 = 1 << 22, + V2_GPIO_23 = 1 << 23, + V2_GPIO_24 = 1 << 24, + V2_GPIO_25 = 1 << 25, + V2_GPIO_27 = 1 << 27, + + //Revision 2, new plug P5 + V2_GPIO_28 = 1 << 28, + V2_GPIO_29 = 1 << 29, + V2_GPIO_30 = 1 << 30, + V2_GPIO_31 = (uint)1 << 31, + + V2_Pin_P1_03 = 1 << 2, + V2_Pin_P1_05 = 1 << 3, + V2_Pin_P1_07 = 1 << 4, + V2_Pin_P1_08 = 1 << 14, + V2_Pin_P1_10 = 1 << 15, + V2_Pin_P1_11 = 1 << 17, + V2_Pin_P1_12 = 1 << 18, + V2_Pin_P1_13 = 1 << 27, + V2_Pin_P1_15 = 1 << 22, + V2_Pin_P1_16 = 1 << 23, + V2_Pin_P1_18 = 1 << 24, + V2_Pin_P1_19 = 1 << 10, + V2_Pin_P1_21 = 1 << 9, + V2_Pin_P1_22 = 1 << 25, + V2_Pin_P1_23 = 1 << 11, + V2_Pin_P1_24 = 1 << 8, + V2_Pin_P1_26 = 1 << 7, + V2_LED = 1 << 16, + + //Revision 2, new plug P5 + V2_Pin_P5_03 = 1 << 28, + V2_Pin_P5_04 = 1 << 29, + V2_Pin_P5_05 = 1 << 30, + V2_Pin_P5_06 = (uint)1 << 31, + + }; + +} diff --git a/RaspberryPiDotNet/GPIOResistor.cs b/RaspberryPiDotNet/GPIOResistor.cs new file mode 100644 index 0000000..6065e72 --- /dev/null +++ b/RaspberryPiDotNet/GPIOResistor.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RaspberryPiDotNet +{ + public enum GPIOResistor + { + OFF = 0, + PULL_DOWN = 1, + PULL_UP = 2 + } +} diff --git a/RaspberryPiDotNet/MCP3008.cs b/RaspberryPiDotNet/MCP3008.cs new file mode 100644 index 0000000..8689c5e --- /dev/null +++ b/RaspberryPiDotNet/MCP3008.cs @@ -0,0 +1,105 @@ +using System; + +// Original author: Mikey Sklar - git://gist.github.com/3249416.git +// Adafruit article: http://learn.adafruit.com/reading-a-analog-in-and-controlling-audio-volume-with-the-raspberry-pi +// Ported from python and modified by: Gilberto Garcia ; twitter: @ferraripr + +namespace RaspberryPiDotNet +{ + /// + /// Raspberry Pi using MCP3008 A/D Converters with SPI Serial Interface + /// + /// + public class MCP3008 + { + private int adcnum; + private GPIO clockpin; + private GPIO mosipin; + private GPIO misopin; + private GPIO cspin; + + /// + /// Connect MCP3008 with clock, Serial Peripheral Interface(SPI) and channel + /// + /// MCP3008 channel number 0-7 (pin 1-8 on chip). + /// Clock pin + /// SPI Master Output, Slave Input (MOSI) + /// SPI Master Input, Slave Output (MISO) + /// SPI Chip Select + public MCP3008(int adc_channel, GPIO SPICLK, GPIO SPIMOSI, GPIO SPIMISO, GPIO SPICS) + { + adcnum = adc_channel; + clockpin = SPICLK; + mosipin = SPIMOSI; + misopin = SPIMISO; + cspin = SPICS; + // + if (adc_channel >= 0 && adc_channel <= 7) + { + //This is the range we are looking for, from CH0 to CH7. + } + else + { + throw new IndexOutOfRangeException("MCP3008 Channel Input is out of range, Channel input should be from 0-7 (8-Channel)."); + } + } + + /// + /// Analog to digital conversion + /// + public int AnalogToDigital + { + get + { + return readadc(); + } + } + + private int readadc() + { + if ((adcnum > 7) || adcnum < 0) + { + return -1; + } + cspin.Write(true); + + clockpin.Write(false); // #start clock low + cspin.Write(false); // #bring CS low + + int commandout = adcnum; + commandout |= 0x18; //# start bit + single-ended bit + commandout <<= 3; //# we only need to send 5 bits here + + for (int i = 0; i < 5; i++) + { + if ((commandout & 0x80) == 128) + { + mosipin.Write(true); + } + else + { + mosipin.Write(false); + } + commandout <<= 1; + clockpin.Write(true); + clockpin.Write(false); + } + + int adcout = 0; + //# read in one empty bit, one null bit and 10 ADC bits + for (var i = 0; i < 12; i++) + { + clockpin.Write(true); + clockpin.Write(false); + adcout <<= 1; + if (misopin.Read() == PinState.High) + adcout |= 0x1; + } + + cspin.Write(true); + adcout /= 2;//# first bit is 'null' so drop it + return adcout; + } + + } +} diff --git a/RaspberryPiDotNet/MicroLiquidCrystal/ILcdTransferProvider.cs b/RaspberryPiDotNet/MicroLiquidCrystal/ILcdTransferProvider.cs index 86149f9..1c84c71 100644 --- a/RaspberryPiDotNet/MicroLiquidCrystal/ILcdTransferProvider.cs +++ b/RaspberryPiDotNet/MicroLiquidCrystal/ILcdTransferProvider.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -// Micro Liquid Crystal Library +// Micro Liquid Crystal Library // http://microliquidcrystal.codeplex.com // Appache License Version 2.0 diff --git a/RaspberryPiDotNet/MicroLiquidCrystal/Lcd.cs b/RaspberryPiDotNet/MicroLiquidCrystal/Lcd.cs index d8538db..26cbb8e 100644 --- a/RaspberryPiDotNet/MicroLiquidCrystal/Lcd.cs +++ b/RaspberryPiDotNet/MicroLiquidCrystal/Lcd.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Text; using System.Threading; diff --git a/RaspberryPiDotNet/MicroLiquidCrystal/RaspPiGPIOFileLcdTransferProvider.cs b/RaspberryPiDotNet/MicroLiquidCrystal/RaspPiGPIOFileLcdTransferProvider.cs index 0034e39..0dc89eb 100644 --- a/RaspberryPiDotNet/MicroLiquidCrystal/RaspPiGPIOFileLcdTransferProvider.cs +++ b/RaspberryPiDotNet/MicroLiquidCrystal/RaspPiGPIOFileLcdTransferProvider.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; // Code modified from original - GPIOLcdTransferProvider.cs // Original code uses license: @@ -22,19 +19,19 @@ public class RaspPiGPIOFileLcdTransferProvider : IDisposable, ILcdTransferProvid private readonly bool _fourBitMode; private bool _disposed; - public RaspPiGPIOFileLcdTransferProvider(GPIOFile.GPIOPins rs, GPIOFile.GPIOPins enable, GPIOFile.GPIOPins d4, GPIOFile.GPIOPins d5, GPIOFile.GPIOPins d6, GPIOFile.GPIOPins d7) - : this(true, rs, GPIOFile.GPIOPins.GPIO_NONE, enable, GPIOFile.GPIOPins.GPIO_NONE, GPIOFile.GPIOPins.GPIO_NONE, GPIOFile.GPIOPins.GPIO_NONE, GPIOFile.GPIOPins.GPIO_NONE, d4, d5, d6, d7) + public RaspPiGPIOFileLcdTransferProvider(GPIOPins rs, GPIOPins enable, GPIOPins d4, GPIOPins d5, GPIOPins d6, GPIOPins d7) + : this(true, rs, GPIOPins.GPIO_NONE, enable, GPIOPins.GPIO_NONE, GPIOPins.GPIO_NONE, GPIOPins.GPIO_NONE, GPIOPins.GPIO_NONE, d4, d5, d6, d7) { } - public RaspPiGPIOFileLcdTransferProvider(GPIOFile.GPIOPins rs, GPIOFile.GPIOPins rw, GPIOFile.GPIOPins enable, GPIOFile.GPIOPins d4, GPIOFile.GPIOPins d5, GPIOFile.GPIOPins d6, GPIOFile.GPIOPins d7) - : this(true, rs, rw, enable, GPIOFile.GPIOPins.GPIO_NONE, GPIOFile.GPIOPins.GPIO_NONE, GPIOFile.GPIOPins.GPIO_NONE, GPIOFile.GPIOPins.GPIO_NONE, d4, d5, d6, d7) + public RaspPiGPIOFileLcdTransferProvider(GPIOPins rs, GPIOPins rw, GPIOPins enable, GPIOPins d4, GPIOPins d5, GPIOPins d6, GPIOPins d7) + : this(true, rs, rw, enable, GPIOPins.GPIO_NONE, GPIOPins.GPIO_NONE, GPIOPins.GPIO_NONE, GPIOPins.GPIO_NONE, d4, d5, d6, d7) { } - public RaspPiGPIOFileLcdTransferProvider(GPIOFile.GPIOPins rs, GPIOFile.GPIOPins enable, GPIOFile.GPIOPins d0, GPIOFile.GPIOPins d1, GPIOFile.GPIOPins d2, GPIOFile.GPIOPins d3, GPIOFile.GPIOPins d4, GPIOFile.GPIOPins d5, GPIOFile.GPIOPins d6, GPIOFile.GPIOPins d7) - : this(false, rs, GPIOFile.GPIOPins.GPIO_NONE, enable, d0, d1, d2, d3, d4, d5, d6, d7) + public RaspPiGPIOFileLcdTransferProvider(GPIOPins rs, GPIOPins enable, GPIOPins d0, GPIOPins d1, GPIOPins d2, GPIOPins d3, GPIOPins d4, GPIOPins d5, GPIOPins d6, GPIOPins d7) + : this(false, rs, GPIOPins.GPIO_NONE, enable, d0, d1, d2, d3, d4, d5, d6, d7) { } - public RaspPiGPIOFileLcdTransferProvider(GPIOFile.GPIOPins rs, GPIOFile.GPIOPins rw, GPIOFile.GPIOPins enable, GPIOFile.GPIOPins d0, GPIOFile.GPIOPins d1, GPIOFile.GPIOPins d2, GPIOFile.GPIOPins d3, GPIOFile.GPIOPins d4, GPIOFile.GPIOPins d5, GPIOFile.GPIOPins d6, GPIOFile.GPIOPins d7) + public RaspPiGPIOFileLcdTransferProvider(GPIOPins rs, GPIOPins rw, GPIOPins enable, GPIOPins d0, GPIOPins d1, GPIOPins d2, GPIOPins d3, GPIOPins d4, GPIOPins d5, GPIOPins d6, GPIOPins d7) : this(false, rs, rw, enable, d0, d1, d2, d3, d4, d5, d6, d7) { } @@ -53,27 +50,27 @@ public RaspPiGPIOFileLcdTransferProvider(GPIOFile.GPIOPins rs, GPIOFile.GPIOPins /// /// /// - public RaspPiGPIOFileLcdTransferProvider(bool fourBitMode, GPIOFile.GPIOPins rs, GPIOFile.GPIOPins rw, GPIOFile.GPIOPins enable, - GPIOFile.GPIOPins d0, GPIOFile.GPIOPins d1, GPIOFile.GPIOPins d2, GPIOFile.GPIOPins d3, - GPIOFile.GPIOPins d4, GPIOFile.GPIOPins d5, GPIOFile.GPIOPins d6, GPIOFile.GPIOPins d7) + public RaspPiGPIOFileLcdTransferProvider(bool fourBitMode, GPIOPins rs, GPIOPins rw, GPIOPins enable, + GPIOPins d0, GPIOPins d1, GPIOPins d2, GPIOPins d3, + GPIOPins d4, GPIOPins d5, GPIOPins d6, GPIOPins d7) { _fourBitMode = fourBitMode; - if (rs == GPIOFile.GPIOPins.GPIO_NONE) throw new ArgumentException("rs"); + if (rs == GPIOPins.GPIO_NONE) throw new ArgumentException("rs"); _rsPort = new GPIOFile(rs); // we can save 1 pin by not using RW. Indicate by passing GPIO.GPIOPins.GPIO_NONE instead of pin# - if (rw != GPIOFile.GPIOPins.GPIO_NONE) // (RW is optional) + if (rw != GPIOPins.GPIO_NONE) // (RW is optional) _rwPort = new GPIOFile(rw); - if (enable == GPIOFile.GPIOPins.GPIO_NONE) throw new ArgumentException("enable"); + if (enable == GPIOPins.GPIO_NONE) throw new ArgumentException("enable"); _enablePort = new GPIOFile(enable); var dataPins = new[] { d0, d1, d2, d3, d4, d5, d6, d7}; _dataPorts = new GPIOFile[8]; for (int i = 0; i < 8; i++) { - if (dataPins[i] != GPIOFile.GPIOPins.GPIO_NONE) + if (dataPins[i] != GPIOPins.GPIO_NONE) _dataPorts[i] = new GPIOFile(dataPins[i]); } } diff --git a/RaspberryPiDotNet/MicroLiquidCrystal/RaspPiGPIOMemLcdTransferProvider.cs b/RaspberryPiDotNet/MicroLiquidCrystal/RaspPiGPIOMemLcdTransferProvider.cs index a891361..680202c 100644 --- a/RaspberryPiDotNet/MicroLiquidCrystal/RaspPiGPIOMemLcdTransferProvider.cs +++ b/RaspberryPiDotNet/MicroLiquidCrystal/RaspPiGPIOMemLcdTransferProvider.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; // Code modified from original - GPIOLcdTransferProvider.cs // Original code uses license: @@ -22,19 +19,19 @@ public class RaspPiGPIOMemLcdTransferProvider : IDisposable, ILcdTransferProvide private readonly bool _fourBitMode; private bool _disposed; - public RaspPiGPIOMemLcdTransferProvider(GPIOMem.GPIOPins rs, GPIOMem.GPIOPins enable, GPIOMem.GPIOPins d4, GPIOMem.GPIOPins d5, GPIOMem.GPIOPins d6, GPIOMem.GPIOPins d7) - : this(true, rs, GPIOMem.GPIOPins.GPIO_NONE, enable, GPIOMem.GPIOPins.GPIO_NONE, GPIOMem.GPIOPins.GPIO_NONE, GPIOMem.GPIOPins.GPIO_NONE, GPIOMem.GPIOPins.GPIO_NONE, d4, d5, d6, d7) + public RaspPiGPIOMemLcdTransferProvider(GPIOPins rs, GPIOPins enable, GPIOPins d4, GPIOPins d5, GPIOPins d6, GPIOPins d7) + : this(true, rs, GPIOPins.GPIO_NONE, enable, GPIOPins.GPIO_NONE, GPIOPins.GPIO_NONE, GPIOPins.GPIO_NONE, GPIOPins.GPIO_NONE, d4, d5, d6, d7) { } - public RaspPiGPIOMemLcdTransferProvider(GPIOMem.GPIOPins rs, GPIOMem.GPIOPins rw, GPIOMem.GPIOPins enable, GPIOMem.GPIOPins d4, GPIOMem.GPIOPins d5, GPIOMem.GPIOPins d6, GPIOMem.GPIOPins d7) - : this(true, rs, rw, enable, GPIOMem.GPIOPins.GPIO_NONE, GPIOMem.GPIOPins.GPIO_NONE, GPIOMem.GPIOPins.GPIO_NONE, GPIOMem.GPIOPins.GPIO_NONE, d4, d5, d6, d7) + public RaspPiGPIOMemLcdTransferProvider(GPIOPins rs, GPIOPins rw, GPIOPins enable, GPIOPins d4, GPIOPins d5, GPIOPins d6, GPIOPins d7) + : this(true, rs, rw, enable, GPIOPins.GPIO_NONE, GPIOPins.GPIO_NONE, GPIOPins.GPIO_NONE, GPIOPins.GPIO_NONE, d4, d5, d6, d7) { } - public RaspPiGPIOMemLcdTransferProvider(GPIOMem.GPIOPins rs, GPIOMem.GPIOPins enable, GPIOMem.GPIOPins d0, GPIOMem.GPIOPins d1, GPIOMem.GPIOPins d2, GPIOMem.GPIOPins d3, GPIOMem.GPIOPins d4, GPIOMem.GPIOPins d5, GPIOMem.GPIOPins d6, GPIOMem.GPIOPins d7) - : this(false, rs, GPIOMem.GPIOPins.GPIO_NONE, enable, d0, d1, d2, d3, d4, d5, d6, d7) + public RaspPiGPIOMemLcdTransferProvider(GPIOPins rs, GPIOPins enable, GPIOPins d0, GPIOPins d1, GPIOPins d2, GPIOPins d3, GPIOPins d4, GPIOPins d5, GPIOPins d6, GPIOPins d7) + : this(false, rs, GPIOPins.GPIO_NONE, enable, d0, d1, d2, d3, d4, d5, d6, d7) { } - public RaspPiGPIOMemLcdTransferProvider(GPIOMem.GPIOPins rs, GPIOMem.GPIOPins rw, GPIOMem.GPIOPins enable, GPIOMem.GPIOPins d0, GPIOMem.GPIOPins d1, GPIOMem.GPIOPins d2, GPIOMem.GPIOPins d3, GPIOMem.GPIOPins d4, GPIOMem.GPIOPins d5, GPIOMem.GPIOPins d6, GPIOMem.GPIOPins d7) + public RaspPiGPIOMemLcdTransferProvider(GPIOPins rs, GPIOPins rw, GPIOPins enable, GPIOPins d0, GPIOPins d1, GPIOPins d2, GPIOPins d3, GPIOPins d4, GPIOPins d5, GPIOPins d6, GPIOPins d7) : this(false, rs, rw, enable, d0, d1, d2, d3, d4, d5, d6, d7) { } @@ -53,27 +50,27 @@ public RaspPiGPIOMemLcdTransferProvider(GPIOMem.GPIOPins rs, GPIOMem.GPIOPins rw /// /// /// - public RaspPiGPIOMemLcdTransferProvider(bool fourBitMode, GPIOMem.GPIOPins rs, GPIOMem.GPIOPins rw, GPIOMem.GPIOPins enable, - GPIOMem.GPIOPins d0, GPIOMem.GPIOPins d1, GPIOMem.GPIOPins d2, GPIOMem.GPIOPins d3, - GPIOMem.GPIOPins d4, GPIOMem.GPIOPins d5, GPIOMem.GPIOPins d6, GPIOMem.GPIOPins d7) + public RaspPiGPIOMemLcdTransferProvider(bool fourBitMode, GPIOPins rs, GPIOPins rw, GPIOPins enable, + GPIOPins d0, GPIOPins d1, GPIOPins d2, GPIOPins d3, + GPIOPins d4, GPIOPins d5, GPIOPins d6, GPIOPins d7) { _fourBitMode = fourBitMode; - if (rs == GPIOMem.GPIOPins.GPIO_NONE) throw new ArgumentException("rs"); + if (rs == GPIOPins.GPIO_NONE) throw new ArgumentException("rs"); _rsPort = new GPIOMem(rs); // we can save 1 pin by not using RW. Indicate by passing GPIO.GPIOPins.GPIO_NONE instead of pin# - if (rw != GPIOMem.GPIOPins.GPIO_NONE) // (RW is optional) + if (rw != GPIOPins.GPIO_NONE) // (RW is optional) _rwPort = new GPIOMem(rw); - if (enable == GPIOMem.GPIOPins.GPIO_NONE) throw new ArgumentException("enable"); + if (enable == GPIOPins.GPIO_NONE) throw new ArgumentException("enable"); _enablePort = new GPIOMem(enable); var dataPins = new[] { d0, d1, d2, d3, d4, d5, d6, d7}; _dataPorts = new GPIOMem[8]; for (int i = 0; i < 8; i++) { - if (dataPins[i] != GPIOMem.GPIOPins.GPIO_NONE) + if (dataPins[i] != GPIOPins.GPIO_NONE) _dataPorts[i] = new GPIOMem(dataPins[i]); } } diff --git a/RaspberryPiDotNet/PinState.cs b/RaspberryPiDotNet/PinState.cs new file mode 100644 index 0000000..ac19c22 --- /dev/null +++ b/RaspberryPiDotNet/PinState.cs @@ -0,0 +1,11 @@ +namespace RaspberryPiDotNet +{ + /// + /// This is a cleaner way to write the Pin Status + /// + public enum PinState + { + High, + Low + } +} \ No newline at end of file diff --git a/RaspberryPiDotNet/RaspberryPiDotNet.csproj b/RaspberryPiDotNet/RaspberryPiDotNet.csproj index a08d16d..5556768 100644 --- a/RaspberryPiDotNet/RaspberryPiDotNet.csproj +++ b/RaspberryPiDotNet/RaspberryPiDotNet.csproj @@ -12,6 +12,7 @@ RaspberryPiDotNet v4.0 512 + true @@ -34,23 +35,25 @@ - - - - - - + + + + + + + +