├── toc.yml
├── Support
├── pigpio-dotnet.png
└── pigpio-dotnet-256.png
├── Unosquare.PiGpio
├── Resources
│ ├── libpigpio.so
│ └── EmbeddedResources.cs
├── NativeEnums
│ ├── I2cQuickMode.cs
│ ├── TimeType.cs
│ ├── CpuPeripheral.cs
│ ├── DigitalValue.cs
│ ├── I2cBusId.cs
│ ├── SpiChannelId.cs
│ ├── SeekMode.cs
│ ├── AllocationMode.cs
│ ├── LevelChange.cs
│ ├── EdgeDetection.cs
│ ├── GpioPadId.cs
│ ├── PinDirection.cs
│ ├── GpioPullMode.cs
│ ├── InterfaceFlags.cs
│ ├── WaveMode.cs
│ ├── BoardType.cs
│ ├── FileModeFlags.cs
│ ├── TimerId.cs
│ ├── PinMode.cs
│ ├── DmaChannel.cs
│ ├── ConfigFlags.cs
│ ├── SoftSpiFlags.cs
│ ├── GpioPadStrength.cs
│ ├── UartRate.cs
│ ├── UserGpio.cs
│ ├── SpiFlags.cs
│ ├── BitMask.cs
│ └── SystemGpio.cs
├── SpiBus.cs
├── NativeTypes
│ ├── GpioSample.cs
│ ├── SysCall.cs
│ ├── GpioPulse.cs
│ ├── I2CMessageSegment.cs
│ ├── RawWave.cs
│ ├── BscTransfer.cs
│ ├── RawCBS.cs
│ ├── RawWaveInformation.cs
│ ├── RawSpiData.cs
│ └── Delegates.cs
├── Timing.cs
├── I2CBus.cs
├── BootstrapPiGpio.cs
├── ManagedModel
│ ├── GpioPad.cs
│ ├── GpioPadCollection.cs
│ ├── GpioPinServiceBase.cs
│ ├── GpioPinCollection.cs
│ ├── GpioPinSoftPwmService.cs
│ ├── BoardWaveService.cs
│ ├── GpioPinServoService.cs
│ ├── GpioPinPwmService.cs
│ ├── GpioPinClockService.cs
│ ├── SoftSpiChannel.cs
│ ├── SoftSerialPort.cs
│ ├── SpiChannel.cs
│ ├── UartPort.cs
│ ├── SoftI2cBus.cs
│ ├── GpioPinInterruptService.cs
│ ├── BoardTimingService.cs
│ ├── GpioPin.cs
│ └── GpioBank.cs
├── GpioController.cs
├── SystemInfo.cs
├── Threading.cs
├── Unosquare.PiGpio.csproj
├── NativeMethods
│ ├── Custom.cs
│ ├── Scripts.cs
│ ├── Serial.cs
│ └── Uart.cs
├── BoardException.cs
└── Board.cs
├── .github
├── workflows
│ └── build.yml
├── ISSUE_TEMPLATE
│ ├── feature_request.md
│ └── bug_report.md
├── stale.yml
└── dependabot.yml
├── Unosquare.PiGpio.Workbench
├── Runners
│ ├── LedBlinking.cs
│ ├── BoardInfo.cs
│ ├── Timers.cs
│ ├── ButtonInterrupts.cs
│ ├── Servo.cs
│ ├── Mpu6050.cs
│ ├── PiOled.cs
│ └── DhtSensor.cs
├── Program.cs
└── Unosquare.PiGpio.Workbench.csproj
├── LICENSE
├── docfx.json
├── appveyor.yml
├── Unosquare.PiGpio.sln
├── README.md
└── .gitignore
/toc.yml:
--------------------------------------------------------------------------------
1 | - name: API Documentation
2 | href: obj/api/
--------------------------------------------------------------------------------
/Support/pigpio-dotnet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unosquare/pigpio-dotnet/HEAD/Support/pigpio-dotnet.png
--------------------------------------------------------------------------------
/Support/pigpio-dotnet-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unosquare/pigpio-dotnet/HEAD/Support/pigpio-dotnet-256.png
--------------------------------------------------------------------------------
/Unosquare.PiGpio/Resources/libpigpio.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unosquare/pigpio-dotnet/HEAD/Unosquare.PiGpio/Resources/libpigpio.so
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: .NET Core
2 |
3 | on: [push]
4 |
5 | jobs:
6 | build:
7 | runs-on: ubuntu-latest
8 |
9 | steps:
10 | - uses: actions/checkout@v1
11 | - name: Setup .NET Core
12 | uses: actions/setup-dotnet@v1
13 | with:
14 | dotnet-version: 3.0.100
15 | - name: Build with dotnet
16 | run: dotnet build --configuration Release
17 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/I2cQuickMode.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | ///
4 | /// Enumerates the quick modes.
5 | ///
6 | public enum I2cQuickMode
7 | {
8 | ///
9 | /// The write mode
10 | ///
11 | Write = 0,
12 |
13 | ///
14 | /// The read mode
15 | ///
16 | Read = 1,
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/TimeType.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | ///
4 | /// Time Type enumeration.
5 | ///
6 | public enum TimeType
7 | {
8 | ///
9 | /// The relative time type
10 | ///
11 | Relative = 0,
12 |
13 | ///
14 | /// The absolute time type
15 | ///
16 | Absolute = 1,
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/CpuPeripheral.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | ///
4 | /// Defines the 2 different CPU peripherals for DMA.
5 | ///
6 | public enum CpuPeripheral
7 | {
8 | ///
9 | /// The Pulse-Width modulation peripheral
10 | ///
11 | Pwm = 0,
12 |
13 | ///
14 | /// The Pulse-Code Modulation peripheral
15 | ///
16 | Pcm = 1,
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/DigitalValue.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | ///
4 | /// Enumerates the digital values. Equivalent to True and False.
5 | ///
6 | public enum DigitalValue : int
7 | {
8 | ///
9 | /// The low value; low voltage or logical 0 (false)
10 | ///
11 | False = 0,
12 |
13 | ///
14 | /// The high value; high voltage or logical 1 (true)
15 | ///
16 | True = 1,
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/I2cBusId.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | ///
4 | /// The Pi has 2 hardware SPI buses. Bus 0 and Bus 1.
5 | /// Bus 1 is the default one, accessible through the main P1 header.
6 | ///
7 | public enum I2cBusId
8 | {
9 | ///
10 | /// The 0th I2c Bus
11 | ///
12 | Bus0 = 0,
13 |
14 | ///
15 | /// The 1st I2c Bus -- This is the default bus number on the Pi.
16 | ///
17 | Bus1 = 1,
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/SpiChannelId.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | ///
4 | /// Enumerates the different SPI Channels.
5 | ///
6 | public enum SpiChannelId
7 | {
8 | ///
9 | /// The spi channel 0
10 | ///
11 | SpiChannel0 = 0,
12 |
13 | ///
14 | /// The spi channel 1
15 | ///
16 | SpiChannel1 = 1,
17 |
18 | ///
19 | /// The spi channel 2 (Auxiliary)
20 | ///
21 | SpiChannel2 = 2,
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/SeekMode.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | ///
4 | /// Defines the different file seek modes.
5 | ///
6 | public enum SeekMode
7 | {
8 | ///
9 | /// From the start of the file
10 | ///
11 | FromStart = 0,
12 |
13 | ///
14 | /// From the current file position
15 | ///
16 | FromCurrent = 1,
17 |
18 | ///
19 | /// From the end position (backwards)
20 | ///
21 | FromEnd = 2,
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/AllocationMode.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | ///
4 | /// Enumerates the different memory allocation mode.
5 | ///
6 | public enum AllocationMode
7 | {
8 | ///
9 | /// The automatic allocation mode
10 | ///
11 | Auto = 0,
12 |
13 | ///
14 | /// The page map allocation mode
15 | ///
16 | PageMap = 1,
17 |
18 | ///
19 | /// The mail box allocation mode
20 | ///
21 | MailBox = 2,
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/LevelChange.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | ///
4 | /// Enumerates the different change states for edge detection.
5 | ///
6 | public enum LevelChange
7 | {
8 | ///
9 | /// Change to low (a falling edge)
10 | ///
11 | HighToLow = 0,
12 |
13 | ///
14 | /// Change to high (a rising edge)
15 | ///
16 | LowToHigh = 1,
17 |
18 | ///
19 | /// No level change (a watchdog timeout)
20 | ///
21 | NoChange = 2,
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/EdgeDetection.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | ///
4 | /// Defines the edge detection strategies.
5 | ///
6 | public enum EdgeDetection : int
7 | {
8 | ///
9 | /// The falling edge (from high to low voltage)
10 | ///
11 | FallingEdge = 0,
12 |
13 | ///
14 | /// The rising edge (from low to high voltage)
15 | ///
16 | RisingEdge = 1,
17 |
18 | ///
19 | /// Rising and falling edge detection strategy
20 | ///
21 | EitherEdge = 2,
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/GpioPadId.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | ///
4 | /// Enumerates the GPIO (electrical) Pads
5 | /// 0 @ 0-27
6 | /// 1 @ 28-45
7 | /// 2 @ 46-53.
8 | ///
9 | public enum GpioPadId
10 | {
11 | ///
12 | /// The pad of GPIO 0 to 27
13 | ///
14 | Pad00To27 = 0,
15 |
16 | ///
17 | /// The pad of GPIO 28 to 45
18 | ///
19 | Pad28To45 = 1,
20 |
21 | ///
22 | /// The pad of GPIO 46 to53
23 | ///
24 | Pad46To53 = 2,
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/PinDirection.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | ///
4 | /// Enumerates the IO directions.
5 | /// This enumeration is compatible with the enum.
6 | ///
7 | public enum PinDirection
8 | {
9 | ///
10 | /// The pin is operating in an alternative mode.
11 | ///
12 | Alternative = -1,
13 |
14 | ///
15 | /// The input operating mode
16 | ///
17 | Input = 0,
18 |
19 | ///
20 | /// The output operating mode
21 | ///
22 | Output = 1,
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/GpioPullMode.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | ///
4 | /// Input GPIOS have pull-up, pull-down or no resistors.
5 | /// This enumeration defines the different resistor pull modes.
6 | ///
7 | public enum GpioPullMode
8 | {
9 | ///
10 | /// No pull-up or pull-down mode.
11 | ///
12 | Off = 0,
13 |
14 | ///
15 | /// Pull-down resistor mode configuration
16 | ///
17 | Down = 1,
18 |
19 | ///
20 | /// Pull-up resistor mode configuration
21 | ///
22 | Up = 2,
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/SpiBus.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio
2 | {
3 | using RaspberryIO.Abstractions;
4 |
5 | ///
6 | /// The SPI Bus containing the 2 SPI channels.
7 | ///
8 | public class SpiBus : ISpiBus
9 | {
10 | ///
11 | public int Channel0Frequency { get; set; }
12 |
13 | ///
14 | public int Channel1Frequency { get; set; }
15 |
16 | ///
17 | public int DefaultFrequency => 8000000;
18 |
19 | ///
20 | public ISpiChannel Channel0 { get; }
21 |
22 | ///
23 | public ISpiChannel Channel1 { get; }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/InterfaceFlags.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | using System;
4 |
5 | ///
6 | /// Defines flags to enable or disable network
7 | /// interfaces.
8 | ///
9 | [Flags]
10 | public enum InterfaceFlags
11 | {
12 | ///
13 | /// The disable FIFO interface
14 | ///
15 | DisableFifoInterface = 1,
16 |
17 | ///
18 | /// The disable socket interface
19 | ///
20 | DisableSocketInterface = 2,
21 |
22 | ///
23 | /// The localhost interface
24 | ///
25 | LocalhostInterface = 4,
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/WaveMode.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | ///
4 | /// Enumerates the different wave modes.
5 | ///
6 | public enum WaveMode
7 | {
8 | ///
9 | /// The one shot wave mode
10 | ///
11 | OneShot = 0,
12 |
13 | ///
14 | /// The repeat wave mode
15 | ///
16 | Repeat = 1,
17 |
18 | ///
19 | /// The one shot synchronize wave mode
20 | ///
21 | OneShotSync = 2,
22 |
23 | ///
24 | /// The repeat synchronize wave mode
25 | ///
26 | RepeatSync = 3,
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/.github/stale.yml:
--------------------------------------------------------------------------------
1 | # Number of days of inactivity before an issue becomes stale
2 | daysUntilStale: 60
3 | # Number of days of inactivity before a stale issue is closed
4 | daysUntilClose: 7
5 | # Issues with these labels will never be considered stale
6 | exemptLabels:
7 | - pinned
8 | - security
9 | # Label to use when marking an issue as stale
10 | staleLabel: wontfix
11 | # Comment to post when marking an issue as stale. Set to `false` to disable
12 | markComment: >
13 | This issue has been automatically marked as stale because it has not had
14 | recent activity. It will be closed if no further activity occurs. Thank you
15 | for your contributions.
16 | # Comment to post when closing a stale issue. Set to `false` to disable
17 | closeComment: false
18 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeTypes/GpioSample.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeTypes
2 | {
3 | using System.Runtime.InteropServices;
4 |
5 | ///
6 | /// Represents sGPIO ample data.
7 | ///
8 | [StructLayout(LayoutKind.Sequential, Pack = 1)]
9 | public class GpioSample
10 | {
11 | private uint m_Tick;
12 | private uint m_Level;
13 |
14 | ///
15 | /// The ticks in microseconds. Wraps every ~72 minutes.
16 | ///
17 | public uint Tick { get => m_Tick; set => m_Tick = value; }
18 |
19 | ///
20 | /// The level (0 or 1).
21 | ///
22 | public uint Level { get => m_Level; set => m_Level = value; }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/BoardType.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | ///
4 | /// Enumerates the different Raspberry Pi board types.
5 | ///
6 | public enum BoardType : int
7 | {
8 | ///
9 | /// Unknown board type
10 | ///
11 | Unknown = 0,
12 |
13 | ///
14 | /// Type 1 - Model B (original model)
15 | ///
16 | Type1 = 1,
17 |
18 | ///
19 | /// Type 2 - Model A and B (revision 2)
20 | ///
21 | Type2 = 2,
22 |
23 | ///
24 | /// Type 3 - Model A+, B+, Pi Zero, Pi2B, Pi3B
25 | ///
26 | Type3 = 3,
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeTypes/SysCall.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeTypes
2 | {
3 | using System;
4 | using System.Runtime.InteropServices;
5 |
6 | internal static class SysCall
7 | {
8 | internal const string LibCLibrary = "libc";
9 |
10 | [DllImport(LibCLibrary, EntryPoint = "chmod", SetLastError = true)]
11 | public static extern int Chmod(string filename, uint mode);
12 |
13 | [DllImport(LibCLibrary, EntryPoint = "strtol", SetLastError = true)]
14 | public static extern int StringToInteger(string numberString, IntPtr endPointer, int numberBase);
15 |
16 | [DllImport(LibCLibrary, EntryPoint = "write", SetLastError = true)]
17 | public static extern int Write(int fd, byte[] buffer, int count);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/Timing.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio
2 | {
3 | using RaspberryIO.Abstractions;
4 |
5 | ///
6 | /// Represents a class with Timing related methods.
7 | ///
8 | ///
9 | public class Timing : ITiming
10 | {
11 | ///
12 | public void SleepMilliseconds(uint millis)
13 | {
14 | throw new System.NotImplementedException();
15 | }
16 |
17 | ///
18 | public void SleepMicroseconds(uint micros)
19 | {
20 | throw new System.NotImplementedException();
21 | }
22 |
23 | ///
24 | public uint Milliseconds { get; }
25 |
26 | ///
27 | public uint Microseconds { get; }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | registries:
3 | nuget-feed-npm-pkg-github-com-unosquare:
4 | type: nuget-feed
5 | url: https://npm.pkg.github.com/unosquare
6 | token: "${{secrets.NUGET_FEED_NPM_PKG_GITHUB_COM_UNOSQUARE_TOKEN}}"
7 | nuget-feed-nuget-pkg-github-com-unosquare-index-json:
8 | type: nuget-feed
9 | url: https://nuget.pkg.github.com/unosquare/index.json
10 | username: "${{secrets.NUGET_FEED_NUGET_PKG_GITHUB_COM_UNOSQUARE_INDEX_JSON_USERNAME}}"
11 | password: "${{secrets.NUGET_FEED_NUGET_PKG_GITHUB_COM_UNOSQUARE_INDEX_JSON_PASSWORD}}"
12 |
13 | updates:
14 | - package-ecosystem: nuget
15 | directory: "/"
16 | schedule:
17 | interval: daily
18 | time: "11:00"
19 | open-pull-requests-limit: 10
20 | registries:
21 | - nuget-feed-npm-pkg-github-com-unosquare
22 | - nuget-feed-nuget-pkg-github-com-unosquare-index-json
23 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeTypes/GpioPulse.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeTypes
2 | {
3 | using NativeEnums;
4 | using System.Runtime.InteropServices;
5 |
6 | ///
7 | /// A pulse representing microseconds in the high position,
8 | /// microseconds in the low position, and a delay measure.
9 | ///
10 | [StructLayout(LayoutKind.Sequential, Pack = 1)]
11 | public struct GpioPulse
12 | {
13 | ///
14 | /// The GPIO pins to turn on.
15 | ///
16 | public BitMask GpioOn;
17 |
18 | ///
19 | /// The gpio pins to turn off.
20 | ///
21 | public BitMask GpioOff;
22 |
23 | ///
24 | /// The duration in microseconds.
25 | ///
26 | public uint DurationMicroSecs;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/FileModeFlags.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | using System;
4 |
5 | ///
6 | /// Enumerates the different file acces modes.
7 | ///
8 | [Flags]
9 | public enum FileModeFlags : int
10 | {
11 | ///
12 | /// The read mode flag
13 | ///
14 | Read = 1,
15 |
16 | ///
17 | /// The write mode flag
18 | ///
19 | Write = 2,
20 |
21 | ///
22 | /// The append mode flag
23 | ///
24 | Append = 4,
25 |
26 | ///
27 | /// The create mode flag
28 | ///
29 | Create = 8,
30 |
31 | ///
32 | /// The truncate mode flag
33 | ///
34 | Truncate = 16,
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/I2CBus.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio
2 | {
3 | using System.Collections.ObjectModel;
4 | using RaspberryIO.Abstractions;
5 |
6 | ///
7 | /// A simple wrapper for the I2c bus on the Raspberry Pi.
8 | ///
9 | public class I2CBus : II2CBus
10 | {
11 | ///
12 | public II2CDevice GetDeviceById(int deviceId)
13 | {
14 | throw new System.NotImplementedException();
15 | }
16 |
17 | ///
18 | public II2CDevice AddDevice(int deviceId)
19 | {
20 | throw new System.NotImplementedException();
21 | }
22 |
23 | ///
24 | public ReadOnlyCollection Devices { get; }
25 |
26 | ///
27 | public II2CDevice this[int deviceId] => throw new System.NotImplementedException();
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio.Workbench/Runners/LedBlinking.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.Workbench.Runners
2 | {
3 | using ManagedModel;
4 | using Swan.Threading;
5 | using System.Threading;
6 |
7 | internal class LedBlinking : RunnerBase
8 | {
9 | private GpioPin _pin;
10 |
11 | public LedBlinking(bool isEnabled)
12 | : base(isEnabled) { }
13 |
14 | protected override void OnSetup()
15 | {
16 | _pin = Board.Pins[17];
17 | }
18 |
19 | protected override void DoBackgroundWork(CancellationToken ct)
20 | {
21 | while (!ct.IsCancellationRequested)
22 | {
23 | _pin.Value = !_pin.Value;
24 | Board.Timing.Sleep(500);
25 | }
26 | }
27 |
28 | protected override void Cleanup()
29 | {
30 | _pin.Value = false;
31 | Board.Timing.Sleep(200);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio.Workbench/Runners/BoardInfo.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.Workbench.Runners
2 | {
3 | using System.Threading;
4 | using Swan.Logging;
5 | using Swan.Threading;
6 |
7 | internal class BoardInfo : RunnerBase
8 | {
9 | public BoardInfo(bool isEnabled)
10 | : base(isEnabled) { }
11 |
12 | protected override void DoBackgroundWork(CancellationToken ct)
13 | {
14 | $"{nameof(Board.BoardType),-22}: {Board.BoardType}".Info(Name);
15 | $"{nameof(Board.HardwareRevision),-22}: {Board.HardwareRevision}".Info(Name);
16 | $"{nameof(Board.IsAvailable),-22}: {Board.IsAvailable}".Info(Name);
17 | $"{nameof(Board.LibraryVersion),-22}: {Board.LibraryVersion}".Info(Name);
18 | $"{nameof(Board.Timing.Timestamp),-22}: {Board.Timing.Timestamp}".Info(Name);
19 | $"{nameof(Board.Timing.TimestampSeconds),-22}: {Board.Timing.TimestampSeconds}".Info(Name);
20 | $"{nameof(Board.Timing.TimestampMicroseconds),-22}: {Board.Timing.TimestampMicroseconds}".Info(Name);
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Unosquare Labs
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/docfx.json:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": [
3 | {
4 | "src": [
5 | {
6 | "files": [ "Unosquare.PiGpio/**/*.cs", "Unosquare.PiGpio.Peripherals/**/*.cs", "Unosquare.PiGpio.Workbench/**/*.cs" ],
7 | "exclude": [ "**/bin/**", "**/obj/**" ]
8 | }
9 | ],
10 | "dest": "obj/api"
11 | }
12 | ],
13 | "build": {
14 | "xrefService": "https://xref.docs.microsoft.com/query?uid={uid}",
15 | "template": [
16 | "best-practices/templates/default"
17 | ],
18 | "content": [
19 | {
20 | "files": [ "**/*.yml" ],
21 | "cwd": "obj/api",
22 | "dest": "api"
23 | },
24 | {
25 | "files": [ "*.md", "toc.yml" ]
26 | }
27 | ],
28 | "resource": [
29 | {
30 | "files": [ "best-practices/resources/**", "Support/pigpio-dotnet-256.png"]
31 | }
32 | ],
33 | "globalMetadata": {
34 | "_appTitle": "Unosquare Raspbery Pi - libpigpio for .net",
35 | "_enableSearch": true,
36 | "_docLogo": "Support/pigpio-dotnet-256.png",
37 | "_appLogoPath": "best-practices/resources/images/logo.png"
38 | },
39 | "dest": "_site"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/BootstrapPiGpio.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio
2 | {
3 | using RaspberryIO.Abstractions;
4 | using Swan.DependencyInjection;
5 |
6 | ///
7 | /// Represents the bootstrap process to use PiGPio.
8 | ///
9 | ///
10 | public class BootstrapPiGpio : IBootstrap
11 | {
12 | private static readonly object SyncLock = new object();
13 |
14 | ///
15 | public void Bootstrap()
16 | {
17 | lock (SyncLock)
18 | {
19 | Resources.EmbeddedResources.ExtractAll();
20 |
21 | DependencyContainer.Current.Register(new GpioController());
22 | DependencyContainer.Current.Register(new SpiBus());
23 | DependencyContainer.Current.Register(new I2CBus());
24 | DependencyContainer.Current.Register(new SystemInfo());
25 | DependencyContainer.Current.Register(new Timing());
26 | DependencyContainer.Current.Register(new Threading());
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/TimerId.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | ///
4 | /// The Pi can register up to 10 hardware timers.
5 | /// This lists all 10 hardware timers from 0 to 9.
6 | ///
7 | public enum TimerId : int
8 | {
9 | /// The GPIO Hardware Timer 00
10 | Timer00 = 0,
11 |
12 | /// The GPIO Hardware Timer 01
13 | Timer01 = 1,
14 |
15 | /// The GPIO Hardware Timer 02
16 | Timer02 = 2,
17 |
18 | /// The GPIO Hardware Timer 03
19 | Timer03 = 3,
20 |
21 | /// The GPIO Hardware Timer 04
22 | Timer04 = 4,
23 |
24 | /// The GPIO Hardware Timer 05
25 | Timer05 = 5,
26 |
27 | /// The GPIO Hardware Timer 06
28 | Timer06 = 6,
29 |
30 | /// The GPIO Hardware Timer 07
31 | Timer07 = 7,
32 |
33 | /// The GPIO Hardware Timer 08
34 | Timer08 = 8,
35 |
36 | /// The GPIO Hardware Timer 09
37 | Timer09 = 9,
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/PinMode.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | ///
4 | /// Pins can operate in different modes.
5 | /// This enumeration defines the fdifferent operation modes from 0 to 7.
6 | ///
7 | public enum PinMode : int
8 | {
9 | ///
10 | /// The input operating mode
11 | ///
12 | Input = 0,
13 |
14 | ///
15 | /// The output operating mode
16 | ///
17 | Output = 1,
18 |
19 | ///
20 | /// The alt5 operating mode
21 | ///
22 | Alt5 = 2,
23 |
24 | ///
25 | /// The alt4 operating mode
26 | ///
27 | Alt4 = 3,
28 |
29 | ///
30 | /// The alt0 operating mode
31 | ///
32 | Alt0 = 4,
33 |
34 | ///
35 | /// The alt1 operating mode
36 | ///
37 | Alt1 = 5,
38 |
39 | ///
40 | /// The alt2 operating mode
41 | ///
42 | Alt2 = 6,
43 |
44 | ///
45 | /// The alt3 operating mode
46 | ///
47 | Alt3 = 7,
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeTypes/I2CMessageSegment.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeTypes
2 | {
3 | using System.Runtime.InteropServices;
4 |
5 | ///
6 | /// An I2C Message Segment.
7 | ///
8 | [StructLayout(LayoutKind.Sequential, Pack = 1)]
9 | public class I2CMessageSegment
10 | {
11 | #region Fields
12 |
13 | private ushort m_Address;
14 |
15 | private ushort m_Flags;
16 |
17 | private ushort m_Length;
18 |
19 | [MarshalAs(UnmanagedType.LPArray)]
20 | private byte[] m_Buffer;
21 |
22 | #endregion
23 |
24 | ///
25 | /// Slave address.
26 | ///
27 | public ushort Address { get => m_Address; set => m_Address = value; }
28 |
29 | ///
30 | /// The flags.
31 | ///
32 | public ushort Flags { get => m_Flags; set => m_Flags = value; }
33 |
34 | ///
35 | /// msg length.
36 | ///
37 | public ushort Length { get => m_Length; set => m_Length = value; }
38 |
39 | ///
40 | /// pointer to msg data.
41 | ///
42 | public byte[] Buffer { get => m_Buffer; set => m_Buffer = value; }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/ManagedModel/GpioPad.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.ManagedModel
2 | {
3 | using NativeEnums;
4 | using NativeMethods;
5 |
6 | ///
7 | /// Represents an electrical pad which groups
8 | /// GPIO pins and has configurable electrical drive strength.
9 | ///
10 | public sealed class GpioPad
11 | {
12 | ///
13 | /// Initializes a new instance of the class.
14 | ///
15 | /// The pad identifier.
16 | internal GpioPad(GpioPadId padId)
17 | {
18 | PadId = padId;
19 | }
20 |
21 | ///
22 | /// Gets the electrical pad identifier.
23 | ///
24 | public GpioPadId PadId { get; }
25 |
26 | ///
27 | /// Gets electrical pad object.
28 | ///
29 | public GpioPad Pad => Board.GpioPads[PadId];
30 |
31 | ///
32 | /// Gets or sets the electrical pad strength.
33 | ///
34 | public GpioPadStrength PadStrength
35 | {
36 | get => IO.GpioGetPad(PadId);
37 | set => BoardException.ValidateResult(IO.GpioSetPad(PadId, value));
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/ManagedModel/GpioPadCollection.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.ManagedModel
2 | {
3 | using NativeEnums;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Collections.ObjectModel;
7 |
8 | ///
9 | /// A collection of GPIO electrical pads.
10 | ///
11 | public sealed class GpioPadCollection
12 | : ReadOnlyDictionary
13 | {
14 | ///
15 | /// Initializes a new instance of the class.
16 | ///
17 | internal GpioPadCollection()
18 | : base(CreateInternalCollection())
19 | {
20 | // placeholder
21 | }
22 |
23 | ///
24 | /// Creates the internal collection.
25 | ///
26 | /// The items in the collection.
27 | private static Dictionary CreateInternalCollection()
28 | {
29 | var enumValues = Enum.GetValues(typeof(GpioPadId));
30 | var result = new Dictionary(enumValues.Length);
31 |
32 | foreach (GpioPadId value in enumValues)
33 | {
34 | result[value] = new GpioPad(value);
35 | }
36 |
37 | return result;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio.Workbench/Program.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.Workbench
2 | {
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using RaspberryIO;
7 | using Runners;
8 | using Swan;
9 | using Swan.Logging;
10 | using Swan.Threading;
11 |
12 | internal static class Program
13 | {
14 | public static void Main()
15 | {
16 | Pi.Init();
17 |
18 | var workbenchItems = new List
19 | {
20 | new BoardInfo(true),
21 | new LedBlinking(false),
22 | new Servo(false),
23 | new Timers(false),
24 | new ButtonInterrupts(false),
25 | new DhtSensor(false),
26 | new Mpu6050(false),
27 | };
28 |
29 | $"Enabled Workbench Items: {workbenchItems.Count(wbi => wbi.IsEnabled)}".Info(nameof(Program));
30 | foreach (var wbi in workbenchItems)
31 | wbi.Start();
32 |
33 | Terminal.ReadKey(intercept: true, disableLocking: true);
34 |
35 | foreach (var wbi in workbenchItems)
36 | wbi.Stop();
37 |
38 | "Program Finished".Info(nameof(Program));
39 | Terminal.Flush(TimeSpan.FromSeconds(2));
40 | Board.Release();
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/DmaChannel.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | ///
4 | /// Enumerates the different DMA channels.
5 | ///
6 | public enum DmaChannel
7 | {
8 | /// DMA Channel 0
9 | Dma00 = 0,
10 |
11 | /// DMA Channel 1
12 | Dma01 = 1,
13 |
14 | /// DMA Channel 2
15 | Dma02 = 2,
16 |
17 | /// DMA Channel 3
18 | Dma03 = 3,
19 |
20 | /// DMA Channel 4
21 | Dma04 = 4,
22 |
23 | /// DMA Channel 5
24 | Dma05 = 5,
25 |
26 | /// DMA Channel 6
27 | Dma06 = 6,
28 |
29 | /// DMA Channel 7
30 | Dma07 = 7,
31 |
32 | /// DMA Channel 8
33 | Dma08 = 8,
34 |
35 | /// DMA Channel 9
36 | Dma09 = 9,
37 |
38 | /// DMA Channel 10
39 | Dma10 = 10,
40 |
41 | /// DMA Channel 11
42 | Dma11 = 11,
43 |
44 | /// DMA Channel 12
45 | Dma12 = 12,
46 |
47 | /// DMA Channel 13
48 | Dma13 = 13,
49 |
50 | /// DMA Channel 14
51 | Dma14 = 14,
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/GpioController.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio
2 | {
3 | using System;
4 | using System.Collections;
5 | using System.Collections.Generic;
6 | using RaspberryIO.Abstractions;
7 |
8 | ///
9 | /// Represents the Raspberry Pi GPIO controller
10 | /// as an IReadOnlyCollection of GpioPins
11 | /// Low level operations are accomplished by using the PiGPIO library.
12 | ///
13 | public class GpioController : IGpioController
14 | {
15 | ///
16 | public IEnumerator GetEnumerator()
17 | {
18 | throw new NotImplementedException();
19 | }
20 |
21 | ///
22 | IEnumerator IEnumerable.GetEnumerator()
23 | {
24 | return GetEnumerator();
25 | }
26 |
27 | ///
28 | public int Count { get; }
29 |
30 | ///
31 | public IGpioPin this[int bcmPinNumber] => throw new NotImplementedException();
32 |
33 | ///
34 | public IGpioPin this[BcmPin bcmPin] => throw new NotImplementedException();
35 |
36 | ///
37 | public IGpioPin this[P1 pinNumber] => throw new NotImplementedException();
38 |
39 | ///
40 | public IGpioPin this[P5 pinNumber] => throw new NotImplementedException();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeTypes/RawWave.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeTypes
2 | {
3 | using System.Runtime.InteropServices;
4 |
5 | ///
6 | /// Represents raw waveform data.
7 | ///
8 | [StructLayout(LayoutKind.Sequential, Pack = 1)]
9 | public sealed class RawWave
10 | {
11 | private uint m_GpioOn;
12 | private uint m_GpioOff;
13 | private uint m_DelayMicroseconds;
14 | private uint m_Flags;
15 |
16 | ///
17 | /// The gpio on.
18 | ///
19 | public uint GpioOn
20 | {
21 | get => m_GpioOn;
22 | set => m_GpioOn = value;
23 | }
24 |
25 | ///
26 | /// The gpio off.
27 | ///
28 | public uint GpioOff
29 | {
30 | get => m_GpioOff;
31 | set => m_GpioOff = value;
32 | }
33 |
34 | ///
35 | /// The delay microseconds.
36 | ///
37 | public uint DelayMicroseconds
38 | {
39 | get => m_DelayMicroseconds;
40 | set => m_DelayMicroseconds = value;
41 | }
42 |
43 | ///
44 | /// The flags.
45 | ///
46 | public uint Flags
47 | {
48 | get => m_Flags;
49 | set => m_Flags = value;
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/SystemInfo.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio
2 | {
3 | using System;
4 | using NativeEnums;
5 | using NativeMethods;
6 | using RaspberryIO.Abstractions;
7 |
8 | ///
9 | /// Represents the system info.
10 | ///
11 | ///
12 | public class SystemInfo : ISystemInfo
13 | {
14 | private static readonly Version _libVersion;
15 | private static readonly BoardRevision _boardRevision = BoardRevision.Rev2;
16 |
17 | static SystemInfo()
18 | {
19 | HardwareRevision = Utilities.GpioHardwareRevision();
20 | _libVersion = new Version(Convert.ToInt32(Utilities.GpioVersion()), 0);
21 | _boardRevision = Constants.GetBoardRevision(HardwareRevision);
22 | BoardType = Constants.GetBoardType(HardwareRevision);
23 | }
24 |
25 | ///
26 | /// Gets the hardware revision number.
27 | ///
28 | public static long HardwareRevision { get; }
29 |
30 | ///
31 | /// Gets the type of the board. See the enumeration.
32 | ///
33 | public static BoardType BoardType { get; }
34 |
35 | ///
36 | public BoardRevision BoardRevision => _boardRevision;
37 |
38 | ///
39 | public Version LibraryVersion => _libVersion;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeTypes/BscTransfer.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeTypes
2 | {
3 | using System.Runtime.InteropServices;
4 |
5 | ///
6 | /// A data structure representing a BSC transfer.
7 | ///
8 | [StructLayout(LayoutKind.Sequential, Pack = 1)]
9 | public class BscTransfer
10 | {
11 | #region Fields
12 |
13 | private uint m_Control;
14 |
15 | private int m_ReceiveCount;
16 |
17 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
18 | private byte[] m_ReceiveBuffer;
19 |
20 | private int m_SendCount;
21 |
22 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
23 | private byte[] m_SendBuffer;
24 |
25 | #endregion
26 |
27 | ///
28 | /// Write.
29 | ///
30 | public uint Control { get => m_Control; set => m_Control = value; }
31 |
32 | ///
33 | /// The rx count.
34 | ///
35 | public int ReceiveCount { get => m_ReceiveCount; set => m_ReceiveCount = value; }
36 |
37 | ///
38 | /// Read only.
39 | ///
40 | public byte[] ReceiveBuffer { get => m_ReceiveBuffer; set => m_ReceiveBuffer = value; }
41 |
42 | ///
43 | /// Write.
44 | ///
45 | public int SendCount { get => m_SendCount; set => m_SendCount = value; }
46 |
47 | ///
48 | /// Write.
49 | ///
50 | public byte[] SendBuffer { get => m_SendBuffer; set => m_SendBuffer = value; }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio.Workbench/Runners/Timers.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.Workbench.Runners
2 | {
3 | using Swan.Logging;
4 | using Swan.Threading;
5 | using System.Threading;
6 |
7 | #pragma warning disable CA1001 // Types that own disposable fields should be disposable
8 | internal class Timers : RunnerBase
9 | #pragma warning restore CA1001 // Types that own disposable fields should be disposable
10 | {
11 | private Timer _currentTimer;
12 | private ManualResetEvent _timerTicked;
13 | private int _remainingTicks = 30;
14 |
15 | public Timers(bool isEnabled)
16 | : base(isEnabled) { }
17 |
18 | protected override void OnSetup()
19 | {
20 | _remainingTicks = 30;
21 | _timerTicked = new ManualResetEvent(false);
22 | _currentTimer = Board.Timing.StartTimer(500, () =>
23 | {
24 | _remainingTicks--;
25 | _timerTicked.Set();
26 | });
27 | }
28 |
29 | protected override void DoBackgroundWork(CancellationToken ct)
30 | {
31 | while (ct.IsCancellationRequested == false)
32 | {
33 | if (_timerTicked.WaitOne(50))
34 | {
35 | $"Timer Ticked. Remaining Ticks: {_remainingTicks}".Info(Name);
36 | _timerTicked.Reset();
37 | }
38 |
39 | if (_remainingTicks <= 0)
40 | break;
41 | }
42 | }
43 |
44 | protected override void Cleanup()
45 | {
46 | _currentTimer.Dispose();
47 | _timerTicked.Dispose();
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/ConfigFlags.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | using System;
4 |
5 | ///
6 | /// Enumerates the different configuration flags.
7 | ///
8 | [Flags]
9 | public enum ConfigFlags : uint
10 | {
11 | ///
12 | /// The debug level0
13 | ///
14 | DebugLevel0 = 1,
15 |
16 | ///
17 | /// The debug level1
18 | ///
19 | DebugLevel1 = 1 << 1,
20 |
21 | ///
22 | /// The debug level2
23 | ///
24 | DebugLevel2 = 1 << 2,
25 |
26 | ///
27 | /// The debug level3
28 | ///
29 | DebugLevel3 = 1 << 3,
30 |
31 | ///
32 | /// The alert frequency0
33 | ///
34 | AlertFrequency0 = 1 << 4,
35 |
36 | ///
37 | /// The alert frequency1
38 | ///
39 | AlertFrequency1 = 1 << 5,
40 |
41 | ///
42 | /// The alert frequency2
43 | ///
44 | AlertFrequency2 = 1 << 6,
45 |
46 | ///
47 | /// The alert frequency3
48 | ///
49 | AlertFrequency3 = 1 << 7,
50 |
51 | ///
52 | /// The real time priority
53 | ///
54 | RealTimePriority = 1 << 8,
55 |
56 | ///
57 | /// The stats
58 | ///
59 | Stats = 1 << 9,
60 |
61 | ///
62 | /// The no signal handler
63 | ///
64 | NoSignalHandler = 1 << 10,
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/SoftSpiFlags.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | using System;
4 |
5 | ///
6 | /// Defines the Software-based SPI flags.
7 | ///
8 | [Flags]
9 | public enum SoftSpiFlags
10 | {
11 | ///
12 | /// The default flags (all 0)
13 | ///
14 | Default = 0,
15 |
16 | ///
17 | /// For CPHA=1, the out side changes the data on the leading
18 | /// edge of the current clock cycle, while the in side captures
19 | /// the data on (or shortly after) the trailing edge of the clock cycle.
20 | /// The out side holds the data valid until the leading edge of the
21 | /// following clock cycle. For the last cycle, the slave holds
22 | /// the MISO line valid until slave select is deasserted.
23 | ///
24 | ClockPhaseLeadingEdge = 0b0_0_00000000000_0_0_1,
25 |
26 | ///
27 | /// CPOL=1 is a clock which idles at 1, and each cycle consists
28 | /// of a pulse of 0. That is, the leading edge is a falling edge,
29 | /// and the trailing edge is a rising edge.
30 | ///
31 | ClockPolarityIdleHigh = 0b0_0_00000000000_0_1_0,
32 |
33 | ///
34 | /// T is 1 if the least significant bit is transmitted on MOSI first, the
35 | /// default (0) shifts the most significant bit out first.
36 | ///
37 | MosiInvert = 0b0_1_00000000000_0_0_0,
38 |
39 | ///
40 | /// R is 1 if the least significant bit is received on MISO first, the
41 | /// default (0) receives the most significant bit first.
42 | ///
43 | MisoInvert = 0b1_0_00000000000_0_0_0,
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/ManagedModel/GpioPinServiceBase.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.ManagedModel
2 | {
3 | using System;
4 |
5 | ///
6 | /// Provides a base implementation of a GPIO Pin Service.
7 | ///
8 | public abstract class GpioPinServiceBase
9 | {
10 | ///
11 | /// Initializes a new instance of the class.
12 | ///
13 | /// The pin.
14 | protected GpioPinServiceBase(GpioPin pin)
15 | {
16 | Pin = pin;
17 | IsAvailable = ResolveAvailable();
18 | }
19 |
20 | ///
21 | /// Gets a value indicating whether this service is available on the associated pin.
22 | ///
23 | public bool IsAvailable { get; }
24 |
25 | ///
26 | /// Gets the associated pin.
27 | ///
28 | protected GpioPin Pin { get; }
29 |
30 | ///
31 | /// Resolves the availability of this service for the associated pin.
32 | ///
33 | /// True when the service is deemed as available.
34 | protected abstract bool ResolveAvailable();
35 |
36 | ///
37 | /// Validates that this service is available. Otherwise, a is thrown.
38 | ///
39 | /// Only pins marked as IsUserGpio support this service.
40 | protected void ValidateAvailable()
41 | {
42 | if (IsAvailable == false)
43 | throw new NotSupportedException($"Only pins that are marked as '{nameof(Pin.IsUserGpio)}' can use the {nameof(GpioPinInterruptService)}.");
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | version: '1.0.{build}'
2 | image: Visual Studio 2019
3 | configuration: Release
4 | platform: Any CPU
5 | notifications:
6 | - provider: Slack
7 | auth_token:
8 | secure: Q+xg4/yU5OR9BVF14cw4yZ+3qlhMeYDsAhUQyOIszmF1mHvq44tIvQpWByBJCd/cgUIZk3SwBpk4hh1MrkQIk6rnaOZ2LNBTev4zrq36oXk=
9 | channel: '#builds'
10 | environment:
11 | # Don't report back to the mothership
12 | DOTNET_CLI_TELEMETRY_OPTOUT: 1
13 | op_build_user: "Geo Perez"
14 | op_build_user_email: "geovanni.perez@gmail.com"
15 | access_token:
16 | secure: HzWdswNyfQbQ0vLk9IQyO+Ei9mxoPYp9rvv6HPhtC9J/Fm7EHRzyV953pbPRXI9I
17 | before_build:
18 | - nuget restore
19 | - ps: |
20 | if(-Not $env:APPVEYOR_PULL_REQUEST_TITLE)
21 | {
22 | git checkout $env:APPVEYOR_REPO_BRANCH -q
23 | cinst docfx -y
24 | }
25 | after_build:
26 | - ps: |
27 | if(-Not $env:APPVEYOR_PULL_REQUEST_TITLE)
28 | {
29 | git config --global credential.helper store
30 | Add-Content "$env:USERPROFILE\.git-credentials" "https://$($env:access_token):x-oauth-basic@github.com`n"
31 | git config --global core.autocrlf false
32 | git config --global user.email $env:op_build_user_email
33 | git config --global user.name $env:op_build_user
34 | git clone https://github.com/unosquare/pigpio-dotnet.git -b gh-pages origin_site -q
35 | git clone -b documentation https://github.com/unosquare/best-practices.git -q
36 | docfx docfx.json --logLevel Error
37 | Copy-Item origin_site/.git _site -recurse
38 | CD _site
39 | Copy-Item README.html index.html -force
40 | git add -A 2>&1
41 | git commit -m "Documentation update" -q
42 | git push origin gh-pages -q
43 | CD ..
44 | }
45 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeTypes/RawCBS.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeTypes
2 | {
3 | using System.Runtime.InteropServices;
4 |
5 | ///
6 | /// The Raw CBS (Linux Control Block).
7 | ///
8 | [StructLayout(LayoutKind.Sequential, Pack = 1)]
9 | public class RawCBS
10 | {
11 | #region Fields
12 |
13 | private uint m_Info;
14 |
15 | private uint m_Source;
16 |
17 | private uint m_Destination;
18 |
19 | private uint m_Length;
20 |
21 | private uint m_Stride;
22 |
23 | private uint m_Next;
24 |
25 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
26 | private uint[] m_Pad;
27 |
28 | #endregion
29 |
30 | ///
31 | /// The information.
32 | ///
33 | public uint Info { get => m_Info; set => m_Info = value; }
34 |
35 | ///
36 | /// The source.
37 | ///
38 | public uint Source { get => m_Source; set => m_Source = value; }
39 |
40 | ///
41 | /// The destination.
42 | ///
43 | public uint Destination { get => m_Destination; set => m_Destination = value; }
44 |
45 | ///
46 | /// The length.
47 | ///
48 | public uint Length { get => m_Length; set => m_Length = value; }
49 |
50 | ///
51 | /// The stride.
52 | ///
53 | public uint Stride { get => m_Stride; set => m_Stride = value; }
54 |
55 | ///
56 | /// The next.
57 | ///
58 | public uint Next { get => m_Next; set => m_Next = value; }
59 |
60 | ///
61 | /// The pad.
62 | ///
63 | public uint[] Pad { get => m_Pad; set => m_Pad = value; }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio.Workbench/Runners/ButtonInterrupts.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.Workbench.Runners
2 | {
3 | using ManagedModel;
4 | using NativeEnums;
5 | using Swan.Logging;
6 | using Swan.Threading;
7 | using System.Threading;
8 |
9 | internal class ButtonInterrupts : RunnerBase
10 | {
11 | private GpioPin _pin;
12 | private uint _previousTick;
13 |
14 | public ButtonInterrupts(bool isEnabled)
15 | : base(isEnabled) { }
16 |
17 | protected override void OnSetup()
18 | {
19 | _pin = Board.Pins[4];
20 | _pin.Direction = PinDirection.Input;
21 | _pin.PullMode = GpioPullMode.Off;
22 | _pin.Interrupts.EdgeDetection = EdgeDetection.EitherEdge;
23 | _pin.Interrupts.TimeoutMilliseconds = 1000;
24 | _previousTick = Board.Timing.TimestampTick;
25 | _pin.Interrupts.Start((pin, level, tick) =>
26 | {
27 | if (level == LevelChange.NoChange)
28 | {
29 | $"Pin: {pin} | Level: {_pin.Value} | Tick: {tick} | Elapsed: {(tick - _previousTick) / 1000d:0.000} ms.".Info(Name);
30 | }
31 | else
32 | {
33 | $"Pin: {pin} | Level: {level} | Tick: {tick} | Elapsed: {(tick - _previousTick) / 1000d:0.000} ms.".Info(Name);
34 |
35 | if (level == LevelChange.LowToHigh)
36 | {
37 | Board.Pins[17].Write(1);
38 | }
39 | }
40 |
41 | _previousTick = tick;
42 | });
43 | }
44 |
45 | protected override void DoBackgroundWork(CancellationToken ct)
46 | {
47 | while (!ct.IsCancellationRequested)
48 | {
49 | Board.Timing.Sleep(50);
50 | }
51 | }
52 |
53 | protected override void Cleanup() => _pin.Interrupts.Stop();
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/Threading.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio
2 | {
3 | using System;
4 | using NativeMethods;
5 | using RaspberryIO.Abstractions;
6 |
7 | ///
8 | /// Use this class to access threading methods using interop.
9 | ///
10 | ///
11 | public class Threading : IThreading
12 | {
13 | private readonly object _lock = new object();
14 | private UIntPtr _currentThread;
15 |
16 | ///
17 | public void StartThread(Action worker)
18 | {
19 | if (worker == null)
20 | throw new ArgumentNullException(nameof(worker));
21 |
22 | lock (_lock)
23 | {
24 | StopThread();
25 | _currentThread = StartThreadEx(x => worker(), UIntPtr.Zero);
26 | }
27 | }
28 |
29 | ///
30 | /// Stops a thread that was previously started with .
31 | ///
32 | public void StopThread()
33 | {
34 | if (_currentThread == UIntPtr.Zero)
35 | return;
36 |
37 | lock (_lock)
38 | {
39 | if (_currentThread == UIntPtr.Zero)
40 | return;
41 |
42 | StopThreadEx(_currentThread);
43 | _currentThread = UIntPtr.Zero;
44 | }
45 | }
46 |
47 | ///
48 | public UIntPtr StartThreadEx(Action worker, UIntPtr userData)
49 | {
50 | if (worker == null)
51 | throw new ArgumentNullException(nameof(worker));
52 |
53 | return BoardException.ValidateResult(
54 | Threads.GpioStartThread(w => worker(w), userData));
55 | }
56 |
57 | ///
58 | public void StopThreadEx(UIntPtr handle)
59 | {
60 | if (handle == UIntPtr.Zero)
61 | return;
62 |
63 | Threads.GpioStopThread(handle);
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/ManagedModel/GpioPinCollection.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.ManagedModel
2 | {
3 | using NativeEnums;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Collections.ObjectModel;
7 |
8 | ///
9 | /// Represents a dictionary of all GPIO Pins.
10 | ///
11 | public sealed class GpioPinCollection
12 | : ReadOnlyDictionary
13 | {
14 | ///
15 | /// Initializes a new instance of the class.
16 | ///
17 | internal GpioPinCollection()
18 | : base(CreateInternalCollection())
19 | {
20 | // placeholder
21 | }
22 |
23 | ///
24 | /// Gets the with the specified gpio.
25 | ///
26 | ///
27 | /// The .
28 | ///
29 | /// The gpio.
30 | /// The pin object.
31 | public GpioPin this[SystemGpio gpio] => this[(int)gpio];
32 |
33 | ///
34 | /// Gets the with the specified gpio.
35 | ///
36 | ///
37 | /// The .
38 | ///
39 | /// The gpio.
40 | /// The pin object.
41 | public GpioPin this[UserGpio gpio] => this[(int)gpio];
42 |
43 | ///
44 | /// Creates the internal collection.
45 | ///
46 | /// The items in the collection.
47 | private static Dictionary CreateInternalCollection()
48 | {
49 | var enumValues = Enum.GetValues(typeof(SystemGpio));
50 | var result = new Dictionary(enumValues.Length);
51 |
52 | foreach (SystemGpio value in enumValues)
53 | {
54 | result[(int)value] = new GpioPin(value);
55 | }
56 |
57 | return result;
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeTypes/RawWaveInformation.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeTypes
2 | {
3 | using System.Runtime.InteropServices;
4 |
5 | ///
6 | /// Represents raw waveform information.
7 | ///
8 | [StructLayout(LayoutKind.Sequential, Pack = 1)]
9 | public class RawWaveInformation
10 | {
11 | #region Fields
12 |
13 | private ushort m_BottomCB;
14 | private ushort m_TopCB;
15 | private ushort m_BottomOOL;
16 | private ushort m_TopOOL;
17 | private ushort m_Deleted;
18 | private ushort m_NumberCB;
19 | private ushort m_NumberBOOL;
20 | private ushort m_NumberTOOL;
21 |
22 | #endregion
23 |
24 | ///
25 | /// first CB used by wave.
26 | ///
27 | public ushort BottomCB { get => m_BottomCB; set => m_BottomCB = value; }
28 |
29 | ///
30 | /// last CB used by wave.
31 | ///
32 | public ushort TopCB { get => m_TopCB; set => m_TopCB = value; }
33 |
34 | ///
35 | /// last OOL used by wave.
36 | ///
37 | public ushort BottomOOL { get => m_BottomOOL; set => m_BottomOOL = value; }
38 |
39 | ///
40 | /// first OOL used by wave.
41 | ///
42 | public ushort TopOOL { get => m_TopOOL; set => m_TopOOL = value; }
43 |
44 | ///
45 | /// Gets or sets the deleted.
46 | ///
47 | public ushort Deleted { get => m_Deleted; set => m_Deleted = value; }
48 |
49 | ///
50 | /// Gets or sets the number cb.
51 | ///
52 | public ushort NumberCB { get => m_NumberCB; set => m_NumberCB = value; }
53 |
54 | ///
55 | /// Gets or sets the number bool.
56 | ///
57 | public ushort NumberBOOL { get => m_NumberBOOL; set => m_NumberBOOL = value; }
58 |
59 | ///
60 | /// Gets or sets the number tool.
61 | ///
62 | public ushort NumberTOOL { get => m_NumberTOOL; set => m_NumberTOOL = value; }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio.Workbench/Runners/Servo.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.Workbench.Runners
2 | {
3 | using System.Threading;
4 | using ManagedModel;
5 | using Swan.Logging;
6 | using Swan.Threading;
7 |
8 | internal class Servo : RunnerBase
9 | {
10 | private const int MinPulseWidth = GpioPinServoService.PulseWidthMin + 50;
11 | private const int MaxPulseWidth = GpioPinServoService.PulseWidthMax;
12 | private const int InitialPulseWidth = GpioPinServoService.PulseWidthMin + 500;
13 | private GpioPin _pin;
14 |
15 | public Servo(bool isEnabled)
16 | : base(isEnabled) { }
17 |
18 | protected override void OnSetup()
19 | {
20 | _pin = Board.Pins[18];
21 | }
22 |
23 | protected override void DoBackgroundWork(CancellationToken ct)
24 | {
25 | var pulseWidth = InitialPulseWidth;
26 | var pulseDelta = 10;
27 | while (ct.IsCancellationRequested == false)
28 | {
29 | var flipDelta = false;
30 |
31 | if (pulseWidth >= MaxPulseWidth)
32 | {
33 | pulseWidth = MaxPulseWidth;
34 | flipDelta = true;
35 | }
36 | else if (pulseWidth <= MinPulseWidth)
37 | {
38 | pulseWidth = MinPulseWidth;
39 | flipDelta = true;
40 | }
41 |
42 | _pin.Servo.PulseWidth = pulseWidth;
43 |
44 | if (flipDelta)
45 | {
46 | $"Pulse Width is now {_pin.Servo.PulseWidth}, {_pin.Servo.PositionPercent:p}".Info(Name);
47 | pulseDelta *= -1;
48 | Board.Timing.Sleep(500);
49 | }
50 |
51 | pulseWidth = pulseWidth + pulseDelta;
52 | Board.Timing.SleepMicros(5000);
53 | }
54 | }
55 |
56 | protected override void Cleanup()
57 | {
58 | _pin.Servo.PulseWidth = InitialPulseWidth;
59 | Board.Timing.Sleep(500); // give it some time to let the servo move to the requested position
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeTypes/RawSpiData.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeTypes
2 | {
3 | using System.Runtime.InteropServices;
4 |
5 | ///
6 | /// Represents Raw SPI channel data.
7 | ///
8 | [StructLayout(LayoutKind.Sequential, Pack = 1)]
9 | public class RawSpiData
10 | {
11 | #region Fields
12 |
13 | private int m_ClockPin;
14 | private int m_MosiPin;
15 | private int m_MisoPin;
16 | private int m_SlaveSelectOffState;
17 | private int m_SlaveSelectDelayMicroseconds;
18 | private int m_ClockOffState;
19 | private int m_ClockPhase;
20 | private int m_ClockMicroseconds;
21 |
22 | #endregion
23 |
24 | ///
25 | /// GPIO for clock.
26 | ///
27 | public int ClockPin { get => m_ClockPin; set => m_ClockPin = value; }
28 |
29 | ///
30 | /// GPIO for MOSI.
31 | ///
32 | public int MosiPin { get => m_MosiPin; set => m_MosiPin = value; }
33 |
34 | ///
35 | /// GPIO for MISO.
36 | ///
37 | public int MisoPin { get => m_MisoPin; set => m_MisoPin = value; }
38 |
39 | ///
40 | /// slave select off state.
41 | ///
42 | public int SlaveSelectOffState { get => m_SlaveSelectOffState; set => m_SlaveSelectOffState = value; }
43 |
44 | ///
45 | /// delay after slave select.
46 | ///
47 | public int SlaveSelectDelayMicroseconds { get => m_SlaveSelectDelayMicroseconds; set => m_SlaveSelectDelayMicroseconds = value; }
48 |
49 | ///
50 | /// clock off state.
51 | ///
52 | public int ClockOffState { get => m_ClockOffState; set => m_ClockOffState = value; }
53 |
54 | ///
55 | /// clock phase.
56 | ///
57 | public int ClockPhase { get => m_ClockPhase; set => m_ClockPhase = value; }
58 |
59 | ///
60 | /// clock micros.
61 | ///
62 | public int ClockMicroseconds { get => m_ClockMicroseconds; set => m_ClockMicroseconds = value; }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio.Workbench/Unosquare.PiGpio.Workbench.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp3.0
6 | Unosquare.PiGpio.Workbench
7 | 1.67.0.1
8 | Mario Di Vece and Contributors to the pigpio-dotnet project
9 | Unosquare SA de CV
10 | Unosquare.PiGpio.Workbench
11 | Contains sample code using peripherals and the PiGpio library
12 | Unosquare SA de CV, Mario Di Vece, and Contributors, (C) 2017-2018
13 | https://github.com/unosquare/pigpio-dotnet
14 | https://github.com/unosquare/pigpio-dotnet/blob/master/LICENSE
15 | https://github.com/unosquare/ffmediaelement/blob/master/Support/pigpio-dotnet.png
16 | https://github.com/unosquare/pigpio-dotnet
17 | GitHub
18 | Raspberry Pi, GPIO, ISR, DMA, Clock, I2C, SPI, UART
19 | pigpio-workbench
20 | ..\StyleCop.Analyzers.ruleset
21 | false
22 | 8.0
23 | Unosquare.PiGpio.Workbench
24 |
25 |
26 |
27 |
28 |
29 | all
30 | runtime; build; native; contentfiles; analyzers
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/Unosquare.PiGpio.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | Unosquare.PiGpio
6 | 0.3.1
7 | Mario Di Vece and Contributors to the pigpio-dotnet project
8 | Unosquare
9 | Unosquare.PiGpio
10 | true
11 | Contains native and managed APIs to accress the libpigpio library
12 | Unosquare SA de CV, Mario Di Vece, and Contributors, (C) 2017-2019
13 | https://github.com/unosquare/pigpio-dotnet
14 | https://github.com/unosquare/pigpio-dotnet/blob/master/LICENSE
15 | https://raw.githubusercontent.com/unosquare/pigpio-dotnet/master/Support/pigpio-dotnet.png
16 | https://github.com/unosquare/pigpio-dotnet
17 | GitHub
18 | Raspberry Pi, GPIO, ISR, DMA, Clock, I2C, SPI, UART
19 | Unosquare.PiGpio
20 | false
21 | ..\StyleCop.Analyzers.ruleset
22 | false
23 | 8.0
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | all
36 | runtime; build; native; contentfiles; analyzers
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/GpioPadStrength.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | ///
4 | /// Enumerates the different Pad Strengths in milli Amperes.
5 | ///
6 | public enum GpioPadStrength
7 | {
8 | ///
9 | /// The pad strength 1 mA
10 | ///
11 | PadStrength1mA = 1,
12 |
13 | ///
14 | /// The pad strength 2 mA
15 | ///
16 | PadStrength2mA = 2,
17 |
18 | ///
19 | /// The pad strength 3 mA
20 | ///
21 | PadStrength3mA = 3,
22 |
23 | ///
24 | /// The pad strength 4 mA
25 | ///
26 | PadStrength4mA = 4,
27 |
28 | ///
29 | /// The pad strength 5 mA
30 | ///
31 | PadStrength5mA = 5,
32 |
33 | ///
34 | /// The pad strength 6 mA
35 | ///
36 | PadStrength6mA = 6,
37 |
38 | ///
39 | /// The pad strength 7 mA
40 | ///
41 | PadStrength7mA = 7,
42 |
43 | ///
44 | /// The pad strength 8 mA
45 | ///
46 | PadStrength8mA = 8,
47 |
48 | ///
49 | /// The pad strength 9 mA
50 | ///
51 | PadStrength9mA = 9,
52 |
53 | ///
54 | /// The pad strength 10 mA
55 | ///
56 | PadStrength10mA = 10,
57 |
58 | ///
59 | /// The pad strength 11mA
60 | ///
61 | PadStrength11mA = 11,
62 |
63 | ///
64 | /// The pad strength 12 mA
65 | ///
66 | PadStrength12mA = 12,
67 |
68 | ///
69 | /// The pad strength 13 mA
70 | ///
71 | PadStrength13mA = 13,
72 |
73 | ///
74 | /// The pad strength 14 mA
75 | ///
76 | PadStrength14mA = 14,
77 |
78 | ///
79 | /// The pad strength 15 mA
80 | ///
81 | PadStrength15mA = 15,
82 |
83 | ///
84 | /// The pad strength 16 mA
85 | ///
86 | PadStrength16mA = 16,
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/Resources/EmbeddedResources.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.Resources
2 | {
3 | using System;
4 | using NativeTypes;
5 | using System.Collections.ObjectModel;
6 | using System.IO;
7 | using System.Reflection;
8 |
9 | ///
10 | /// Provides access to embedded assembly files.
11 | ///
12 | internal static class EmbeddedResources
13 | {
14 | ///
15 | /// Initializes static members of the class.
16 | ///
17 | static EmbeddedResources()
18 | {
19 | ResourceNames =
20 | new ReadOnlyCollection(typeof(EmbeddedResources).Assembly.GetManifestResourceNames());
21 | }
22 |
23 | ///
24 | /// Gets the resource names.
25 | ///
26 | ///
27 | /// The resource names.
28 | ///
29 | public static ReadOnlyCollection ResourceNames { get; }
30 |
31 | ///
32 | /// Extracts all the file resources to the specified base path.
33 | ///
34 | public static void ExtractAll()
35 | {
36 | var basePath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
37 | var executablePermissions = SysCall.StringToInteger("0777", IntPtr.Zero, 8);
38 |
39 | foreach (var resourceName in ResourceNames)
40 | {
41 | var filename = resourceName.Substring($"{typeof(EmbeddedResources).Namespace}.".Length);
42 | var targetPath = Path.Combine(basePath, filename);
43 | if (File.Exists(targetPath)) return;
44 |
45 | using var stream = typeof(EmbeddedResources).Assembly
46 | .GetManifestResourceStream($"{typeof(EmbeddedResources).Namespace}.{filename}");
47 | using (var outputStream = File.OpenWrite(targetPath))
48 | {
49 | stream?.CopyTo(outputStream);
50 | }
51 |
52 | try
53 | {
54 | SysCall.Chmod(targetPath, (uint)executablePermissions);
55 | }
56 | catch
57 | {
58 | /* Ignore */
59 | }
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29326.143
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Support", "Support", "{98778E74-B179-472B-B74D-AB306274437F}"
7 | ProjectSection(SolutionItems) = preProject
8 | .gitignore = .gitignore
9 | appveyor.yml = appveyor.yml
10 | Support\libpigpio.so = Support\libpigpio.so
11 | LICENSE = LICENSE
12 | Support\pigpio-dotnet-256.png = Support\pigpio-dotnet-256.png
13 | Support\pigpio-dotnet.png = Support\pigpio-dotnet.png
14 | Support\pigpio.c = Support\pigpio.c
15 | Support\pigpio.h = Support\pigpio.h
16 | README.md = README.md
17 | StyleCop.Analyzers.ruleset = StyleCop.Analyzers.ruleset
18 | EndProjectSection
19 | EndProject
20 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unosquare.PiGpio", "Unosquare.PiGpio\Unosquare.PiGpio.csproj", "{73E89A82-F351-4CAE-8AA4-A038DCD2D733}"
21 | EndProject
22 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unosquare.PiGpio.Workbench", "Unosquare.PiGpio.Workbench\Unosquare.PiGpio.Workbench.csproj", "{58482F68-38E4-41FE-B234-257E548CDC66}"
23 | EndProject
24 | Global
25 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
26 | Debug|Any CPU = Debug|Any CPU
27 | Release|Any CPU = Release|Any CPU
28 | EndGlobalSection
29 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
30 | {73E89A82-F351-4CAE-8AA4-A038DCD2D733}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31 | {73E89A82-F351-4CAE-8AA4-A038DCD2D733}.Debug|Any CPU.Build.0 = Debug|Any CPU
32 | {73E89A82-F351-4CAE-8AA4-A038DCD2D733}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 | {73E89A82-F351-4CAE-8AA4-A038DCD2D733}.Release|Any CPU.Build.0 = Release|Any CPU
34 | {58482F68-38E4-41FE-B234-257E548CDC66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
35 | {58482F68-38E4-41FE-B234-257E548CDC66}.Debug|Any CPU.Build.0 = Debug|Any CPU
36 | {58482F68-38E4-41FE-B234-257E548CDC66}.Release|Any CPU.ActiveCfg = Release|Any CPU
37 | {58482F68-38E4-41FE-B234-257E548CDC66}.Release|Any CPU.Build.0 = Release|Any CPU
38 | EndGlobalSection
39 | GlobalSection(SolutionProperties) = preSolution
40 | HideSolutionNode = FALSE
41 | EndGlobalSection
42 | GlobalSection(ExtensibilityGlobals) = postSolution
43 | SolutionGuid = {458E4143-9DD7-4F40-BC2A-9AA4AA144E86}
44 | EndGlobalSection
45 | EndGlobal
46 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/ManagedModel/GpioPinSoftPwmService.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.ManagedModel
2 | {
3 | using NativeEnums;
4 | using NativeMethods;
5 | using System;
6 |
7 | ///
8 | /// Provides a software-based PWM service on the associated pin.
9 | ///
10 | ///
11 | public class GpioPinSoftPwmService : GpioPinServiceBase
12 | {
13 | ///
14 | /// Initializes a new instance of the class.
15 | ///
16 | /// The pin.
17 | internal GpioPinSoftPwmService(GpioPin pin)
18 | : base(pin)
19 | {
20 | // placeholder
21 | }
22 |
23 | ///
24 | /// Gets or sets the range of the duty cycle.
25 | ///
26 | public int Range
27 | {
28 | get => BoardException.ValidateResult(Pwm.GpioGetPwmRange((UserGpio)Pin.PinNumber));
29 | set => BoardException.ValidateResult(Pwm.GpioSetPwmRange((UserGpio)Pin.PinNumber, Convert.ToUInt32(value)));
30 | }
31 |
32 | ///
33 | /// Gets or sets the duty cycle. Setting this property starts the PWM pulses.
34 | /// The default range is 255.
35 | ///
36 | public int DutyCycle
37 | {
38 | get => BoardException.ValidateResult(Pwm.GpioGetPwmDutyCycle((UserGpio)Pin.PinNumber));
39 | set => BoardException.ValidateResult(Pwm.GpioPwm((UserGpio)Pin.PinNumber, Convert.ToUInt32(value)));
40 | }
41 |
42 | ///
43 | /// Gets or sets the frequency (in Hz) at which the PWM runs.
44 | ///
45 | public int Frequency
46 | {
47 | get => BoardException.ValidateResult(Pwm.GpioGetPwmFrequency((UserGpio)Pin.PinNumber));
48 | set => BoardException.ValidateResult(Pwm.GpioSetPwmFrequency((UserGpio)Pin.PinNumber, Convert.ToUInt32(value)));
49 | }
50 |
51 | ///
52 | /// Resolves the availability of this service for the associated pin.
53 | ///
54 | ///
55 | /// True when the service is deemed as available.
56 | ///
57 | protected override bool ResolveAvailable()
58 | {
59 | return Pin.IsUserGpio;
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeMethods/Custom.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeMethods
2 | {
3 | using System.Runtime.InteropServices;
4 |
5 | ///
6 | /// Defines method calls for cutom functions.
7 | /// These calls are reserved but still provided for reference purposes.
8 | /// They are unused in the managed model of this library.
9 | ///
10 | public static class Custom
11 | {
12 | ///
13 | /// This function is available for user customisation.
14 | ///
15 | /// It returns a single integer value.
16 | ///
17 | ///
18 | /// Argument 1: >=0.
19 | /// Argument 2: >=0.
20 | /// extra (byte) arguments.
21 | /// number of extra arguments.
22 | /// Returns >= 0 if OK, less than 0 indicates a user defined error.
23 | [DllImport(Constants.PiGpioLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "gpioCustom1")]
24 | public static extern int GpioCustom1(uint arg1, uint arg2, [In, MarshalAs(UnmanagedType.LPArray)] byte[] argx, uint argc);
25 |
26 | ///
27 | /// This function is available for user customisation.
28 | ///
29 | /// It differs from gpioCustom1 in that it returns an array of bytes
30 | /// rather than just an integer.
31 | ///
32 | /// The returned value is an integer indicating the number of returned bytes.
33 | ///
34 | /// The number of returned bytes must be retMax or less.
35 | ///
36 | /// >=0.
37 | /// extra (byte) arguments.
38 | /// number of extra arguments.
39 | /// buffer for returned bytes.
40 | /// maximum number of bytes to return.
41 | /// Returns >= 0 if OK, less than 0 indicates a user defined error.
42 | [DllImport(Constants.PiGpioLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "gpioCustom2")]
43 | public static extern int GpioCustom2(uint arg1, [In, MarshalAs(UnmanagedType.LPArray)] byte[] argx, uint argc, [In, MarshalAs(UnmanagedType.LPArray)] byte[] retBuf, uint retMax);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/ManagedModel/BoardWaveService.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.ManagedModel
2 | {
3 | using NativeMethods;
4 |
5 | ///
6 | /// Provides a a pin service to generate pulses with microsecond precision.
7 | ///
8 | ///
9 | public sealed class BoardWaveService
10 | {
11 | ///
12 | /// Initializes a new instance of the class.
13 | ///
14 | internal BoardWaveService()
15 | {
16 | // placeholder
17 | // TODO: implementation is incomplete
18 | // see https://github.com/bschwind/ir-slinger/blob/master/irslinger.h
19 | // for usage
20 | MaxPulses = Waves.GpioWaveGetMaxPulses();
21 | MaxDmaControlBlocks = Waves.GpioWaveGetMaxCbs();
22 | MaxDurationMicroSecs = Waves.GpioWaveGetMaxMicros();
23 | }
24 |
25 | ///
26 | /// Gets the maximum pulses allowable per wave.
27 | ///
28 | public int MaxPulses { get; }
29 |
30 | ///
31 | /// Gets the maximum DMA control blocks per wave.
32 | ///
33 | public int MaxDmaControlBlocks { get; }
34 |
35 | ///
36 | /// Gets the maximum duration of a wave in micro seconds.
37 | ///
38 | public int MaxDurationMicroSecs { get; }
39 |
40 | ///
41 | /// Gets a value indicating whether a waveform is being transmitted.
42 | ///
43 | public bool IsBusy => Waves.GpioWaveTxBusy() > 0;
44 |
45 | ///
46 | /// Gets the current wave identifier.
47 | ///
48 | public int CurrentWaveId
49 | {
50 | get
51 | {
52 | var waveId = Waves.GpioWaveTxAt();
53 | return waveId >= 0 && waveId < 9998 ? waveId : -1;
54 | }
55 | }
56 |
57 | ///
58 | /// Stops the current wave being transmitted.
59 | /// This is intended to stop waves that are generated with a cycling mode.
60 | ///
61 | public void StopCurrent() => Waves.GpioWaveTxStop();
62 |
63 | ///
64 | /// Creates the wave.
65 | ///
66 | /// A wave builder object to create and transmit PWM waves.
67 | public WaveBuilder CreateWave() => new WaveBuilder();
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/UartRate.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | ///
4 | /// Defines the valid UART rates.
5 | ///
6 | public enum UartRate
7 | {
8 | ///
9 | /// The baud rate 50 bps
10 | ///
11 | BaudRate50 = 50,
12 |
13 | ///
14 | /// The baud rate 75 bps
15 | ///
16 | BaudRate75 = 75,
17 |
18 | ///
19 | /// The baud rate 110 bps
20 | ///
21 | BaudRate110 = 110,
22 |
23 | ///
24 | /// The baud rate 134 bps
25 | ///
26 | BaudRate134 = 134,
27 |
28 | ///
29 | /// The baud rate 150 bps
30 | ///
31 | BaudRate150 = 150,
32 |
33 | ///
34 | /// The baud rate 200 bps
35 | ///
36 | BaudRate200 = 200,
37 |
38 | ///
39 | /// The baud rate 300 bps
40 | ///
41 | BaudRate300 = 300,
42 |
43 | ///
44 | /// The baud rate 600 bps
45 | ///
46 | BaudRate600 = 600,
47 |
48 | ///
49 | /// The baud rate 1200 bps
50 | ///
51 | BaudRate1200 = 1200,
52 |
53 | ///
54 | /// The baud rate 1800 bps
55 | ///
56 | BaudRate1800 = 1800,
57 |
58 | ///
59 | /// The baud rate 2400 bps
60 | ///
61 | BaudRate2400 = 2400,
62 |
63 | ///
64 | /// The baud rate 4800 bps
65 | ///
66 | BaudRate4800 = 4800,
67 |
68 | ///
69 | /// The baud rate 9600 bps
70 | ///
71 | BaudRate9600 = 9600,
72 |
73 | ///
74 | /// The baud rate 19200 bps
75 | ///
76 | BaudRate19200 = 19200,
77 |
78 | ///
79 | /// The baud rate 38400 bps
80 | ///
81 | BaudRate38400 = 38400,
82 |
83 | ///
84 | /// The baud rate 57600 bps
85 | ///
86 | BaudRate57600 = 57600,
87 |
88 | ///
89 | /// The baud rate 115200 bps
90 | ///
91 | BaudRate115200 = 115200,
92 |
93 | ///
94 | /// The baud rate 230400 bps
95 | ///
96 | BaudRate230400 = 230400,
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/ManagedModel/GpioPinServoService.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.ManagedModel
2 | {
3 | using System;
4 | using NativeEnums;
5 | using NativeMethods;
6 |
7 | ///
8 | /// Provides a standard servo PWM service running at 50Hz.
9 | /// The pulse width must be 0, or a number beween 500 and 2500.
10 | ///
11 | ///
12 | public sealed class GpioPinServoService : GpioPinServiceBase
13 | {
14 | ///
15 | /// The pulse width minimum in microseconds.
16 | ///
17 | public const int PulseWidthMin = 500;
18 |
19 | ///
20 | /// The pulse width maximum in microseconds.
21 | ///
22 | public const int PulseWidthMax = 2500;
23 |
24 | ///
25 | /// The pulse range difference in microseconds.
26 | ///
27 | public const int PulseWidthRange = PulseWidthMax - PulseWidthMin;
28 |
29 | internal GpioPinServoService(GpioPin pin)
30 | : base(pin)
31 | {
32 | // placeholder
33 | }
34 |
35 | ///
36 | /// Gets or sets the width of the pulse in microseconds.
37 | /// Value must be between 500 and 2500 microseconds.
38 | /// Setting to 0 will turn off the PWM.
39 | ///
40 | public int PulseWidth
41 | {
42 | get => BoardException.ValidateResult(
43 | Pwm.GpioGetServoPulseWidth((UserGpio)Pin.PinNumber));
44 | set => BoardException.ValidateResult(
45 | Pwm.GpioServo((UserGpio)Pin.PinNumber, Convert.ToUInt32(value)));
46 | }
47 |
48 | ///
49 | /// Gets or sets the pulse width as a position percent for 0.0 to 1.0.
50 | /// Use -1.0 to turn off the PWM pulses.
51 | ///
52 | public double PositionPercent
53 | {
54 | get
55 | {
56 | var currentWidth = PulseWidth;
57 | if (currentWidth <= 0) return -1d;
58 |
59 | currentWidth -= PulseWidthMin;
60 | return currentWidth / (double)PulseWidthRange;
61 | }
62 | set
63 | {
64 | if (value < 0d)
65 | {
66 | PulseWidth = 0;
67 | return;
68 | }
69 |
70 | if (value > 1d) value = 1d;
71 | PulseWidth = Convert.ToInt32(PulseWidthMin + (value * PulseWidthRange));
72 | }
73 | }
74 |
75 | ///
76 | protected override bool ResolveAvailable() => Pin.IsUserGpio;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/BoardException.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio
2 | {
3 | using System;
4 | using NativeEnums;
5 |
6 | ///
7 | /// Represents a PiGpio Library call exception.
8 | ///
9 | ///
10 | public class BoardException : Exception
11 | {
12 | ///
13 | /// Initializes a new instance of the class.
14 | ///
15 | /// The result code.
16 | private BoardException(int resultCode)
17 | : base(GetStarndardMessage(resultCode))
18 | {
19 | ResultCode = (ResultCode)resultCode;
20 | }
21 |
22 | ///
23 | /// Gets the result code.
24 | ///
25 | public ResultCode ResultCode { get; }
26 |
27 | ///
28 | /// Validates the result. This call is typically used for Setter methods.
29 | ///
30 | /// The result code.
31 | /// The Result Code.
32 | internal static ResultCode ValidateResult(ResultCode resultCode)
33 | {
34 | return (ResultCode)ValidateResult((int)resultCode);
35 | }
36 |
37 | ///
38 | /// Validates the result. This call is typically used for Getter methods.
39 | ///
40 | /// The result code.
41 | /// The integer result.
42 | internal static int ValidateResult(int resultCode)
43 | {
44 | if (resultCode < 0)
45 | throw new BoardException(resultCode);
46 |
47 | return resultCode;
48 | }
49 |
50 | ///
51 | /// Validates the result. This call is typically used for execute methods.
52 | ///
53 | /// The handle.
54 | /// The pointer or handle.
55 | internal static UIntPtr ValidateResult(UIntPtr handle)
56 | {
57 | if (handle == UIntPtr.Zero)
58 | throw new BoardException((int)ResultCode.BadHandle);
59 |
60 | return handle;
61 | }
62 |
63 | ///
64 | /// Gets the starndard message.
65 | ///
66 | /// The result code.
67 | /// The standard corresponding error message based on the result code.
68 | private static string GetStarndardMessage(int resultCode)
69 | {
70 | return $"Hardware Exception Encountered. Error Code {resultCode}: {(ResultCode)resultCode}: " +
71 | $"{Constants.GetResultCodeMessage(resultCode)}";
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/ManagedModel/GpioPinPwmService.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.ManagedModel
2 | {
3 | using NativeEnums;
4 | using NativeMethods;
5 | using System;
6 | using System.Linq;
7 |
8 | ///
9 | /// Provides hardware-based PWM services on the pin.
10 | ///
11 | ///
12 | public sealed class GpioPinPwmService : GpioPinServiceBase
13 | {
14 | internal GpioPinPwmService(GpioPin pin)
15 | : base(pin)
16 | {
17 | // placeholder
18 | // TODO: Not fully implemented yet
19 | }
20 |
21 | ///
22 | /// Gets the range of the duty cycle.
23 | ///
24 | public int Range => BoardException.ValidateResult(Pwm.GpioGetPwmRealRange((UserGpio)Pin.PinNumber));
25 |
26 | ///
27 | /// Gets the frequency.
28 | ///
29 | public int Frequency => BoardException.ValidateResult(Pwm.GpioGetPwmFrequency((UserGpio)Pin.PinNumber));
30 |
31 | ///
32 | /// Gets the PWM channel, 0 or 1. A negative number mans there is no associated PWM channel.
33 | ///
34 | public int Channel { get; private set; }
35 |
36 | ///
37 | /// Starts PWM hardware pulses.
38 | /// Frequencies above 30MHz are unlikely to work.
39 | ///
40 | /// The frequency. 0 (off) or 1-125000000 (125M).
41 | /// 0 (off) to 1000000 (1M)(fully on).
42 | public void Start(int frequency, int dutyCycle)
43 | {
44 | BoardException.ValidateResult(
45 | Pwm.GpioHardwarePwm(Pin.PinGpio, Convert.ToUInt32(frequency), Convert.ToUInt32(dutyCycle)));
46 | }
47 |
48 | ///
49 | /// Stops PWM hardware pulses.
50 | ///
51 | public void Stop() => Start(0, 0);
52 |
53 | ///
54 | protected override bool ResolveAvailable()
55 | {
56 | if (Board.BoardType == BoardType.Type1 || Board.BoardType == BoardType.Type2)
57 | {
58 | if (Pin.PinNumber == 18)
59 | {
60 | Channel = 0;
61 | return true;
62 | }
63 |
64 | Channel = -1;
65 | return false;
66 | }
67 |
68 | if ((new[] { 12, 18, 40, 52 }).Contains(Pin.PinNumber))
69 | {
70 | Channel = 0;
71 | return true;
72 | }
73 |
74 | if ((new[] { 13, 19, 41, 45, 53 }).Contains(Pin.PinNumber))
75 | {
76 | Channel = 1;
77 | return true;
78 | }
79 |
80 | Channel = -1;
81 | return false;
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://ci.appveyor.com/project/geoperez/pigpio-dotnet/branch/master)
2 |
3 | #
Raspbery Pi - libpigpio for .net
4 |
5 | **WE ARE LOOKING FOR A NEW HOME FOR THIS PROJECT. APPLY AT:** https://adoptoposs.org/p/d3470190-942b-44ac-84fc-90259cbdee43
6 |
7 | *:star: Please star this project if you find it useful!*
8 |
9 | Provides complete managed access to the popular pigpio C library.
10 |
11 | The premise is simple: using the powerful features of C# to control the ARM peripherals of the Raspberry Pi. This library provides a comprehensive way to access the hardware of the Pi. It uses the fantastic C library [pigpio](https://github.com/joan2937/pigpio/). The [documentation of the library can be found here](http://abyz.me.uk/rpi/pigpio/).
12 |
13 | As a programmer, the choice is yours. You can call the native methods either directly or via the comprehensive API of PiGpio.net.
14 |
15 | ## Example of blinking an LED with direct native calls
16 |
17 | ```csharp
18 | Setup.GpioInitialise();
19 | var pin = SystemGpio.Bcm18;
20 | IO.GpioSetMode(pin, PinMode.Output);
21 |
22 | while (true)
23 | {
24 | IO.GpioWrite(pin, true);
25 | Thread.Sleep(500);
26 | IO.GpioWrite(pin, false);
27 | Thread.Sleep(500);
28 | }
29 | ```
30 |
31 | ## Example of blinking an LED with the PiGpio.net Managed API
32 |
33 | ```csharp
34 | var pin = Board.Pins[18];
35 |
36 | while (true)
37 | {
38 | pin.Value = !pin.Value;
39 | Thread.Sleep(500);
40 | }
41 | ```
42 |
43 | ## Related Projects and Nugets
44 | | Name | Author | Description |
45 | | ---- | ------ | ----------- |
46 | | [RaspberryIO](https://github.com/unosquare/raspberryio) | [Unosquare](https://github.com/unosquare) | The Raspberry Pi's IO Functionality in an easy-to-use API for .NET (Mono/.NET Core). |
47 | | [PiGpio.net](https://github.com/unosquare/pigpio-dotnet) | [Unosquare](https://github.com/unosquare) | Provides complete managed access to the popular pigpio C library |
48 | | [Raspberry Abstractions](https://www.nuget.org/packages/Unosquare.Raspberry.Abstractions) | [Unosquare](https://www.nuget.org/profiles/Unosquare) | Allows you to implement your own provider for RaspberryIO. |
49 | | [Raspberry# IO](https://github.com/raspberry-sharp/raspberry-sharp-io) | [raspberry-sharp](https://github.com/raspberry-sharp) | Raspberry# IO is a .NET/Mono IO Library for Raspberry Pi. This project is an initiative of the [Raspberry#](http://www.raspberry-sharp.org/) Community. |
50 | | [WiringPi.Net](https://github.com/danriches/WiringPi.Net) | [Daniel Riches](https://github.com/danriches) | A simple C# wrapper for Gordon's WiringPi library. |
51 | | [PiSharp](https://github.com/andycb/PiSharp) |[Andy Bradford](https://github.com/andycb) | Pi# is a library to expose the GPIO functionality of the Raspberry Pi computer to the C# and Visual Basic.Net languages |
52 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/UserGpio.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | ///
4 | /// Provides an enumeration of User GPIOs from 0 to 31.
5 | /// Do not use undocumented pin numbers because they might be reserved or crash the hardware
6 | /// and corrupt the SD card.
7 | ///
8 | public enum UserGpio : int
9 | {
10 | /// The BCM GPIO 00
11 | Bcm00 = 0,
12 |
13 | /// The BCM GPIO 01
14 | Bcm01 = 1,
15 |
16 | /// The BCM GPIO 02
17 | Bcm02 = 2,
18 |
19 | /// The BCM GPIO 03
20 | Bcm03 = 3,
21 |
22 | /// The BCM GPIO 04
23 | Bcm04 = 4,
24 |
25 | /// The BCM GPIO 05
26 | Bcm05 = 5,
27 |
28 | /// The BCM GPIO 06
29 | Bcm06 = 6,
30 |
31 | /// The BCM GPIO 07
32 | Bcm07 = 7,
33 |
34 | /// The BCM GPIO 08
35 | Bcm08 = 8,
36 |
37 | /// The BCM GPIO 09
38 | Bcm09 = 9,
39 |
40 | /// The BCM GPIO 10
41 | Bcm10 = 10,
42 |
43 | /// The BCM GPIO 11
44 | Bcm11 = 11,
45 |
46 | /// The BCM GPIO 12
47 | Bcm12 = 12,
48 |
49 | /// The BCM GPIO 13
50 | Bcm13 = 13,
51 |
52 | /// The BCM GPIO 14
53 | Bcm14 = 14,
54 |
55 | /// The BCM GPIO 15
56 | Bcm15 = 15,
57 |
58 | /// The BCM GPIO 16
59 | Bcm16 = 16,
60 |
61 | /// The BCM GPIO 17
62 | Bcm17 = 17,
63 |
64 | /// The BCM GPIO 18
65 | Bcm18 = 18,
66 |
67 | /// The BCM GPIO 19
68 | Bcm19 = 19,
69 |
70 | /// The BCM GPIO 20
71 | Bcm20 = 20,
72 |
73 | /// The BCM GPIO 21
74 | Bcm21 = 21,
75 |
76 | /// The BCM GPIO 22
77 | Bcm22 = 22,
78 |
79 | /// The BCM GPIO 23
80 | Bcm23 = 23,
81 |
82 | /// The BCM GPIO 24
83 | Bcm24 = 24,
84 |
85 | /// The BCM GPIO 25
86 | Bcm25 = 25,
87 |
88 | /// The BCM GPIO 26
89 | Bcm26 = 26,
90 |
91 | /// The BCM GPIO 27
92 | Bcm27 = 27,
93 |
94 | /// The BCM GPIO 28
95 | Bcm28 = 28,
96 |
97 | /// The BCM GPIO 29
98 | Bcm29 = 29,
99 |
100 | /// The BCM GPIO 30
101 | Bcm30 = 30,
102 |
103 | /// The BCM GPIO 31
104 | Bcm31 = 31,
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio.Workbench/Runners/Mpu6050.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.Workbench.Runners
2 | {
3 | using System;
4 | using System.Threading;
5 | using ManagedModel;
6 | using NativeMethods;
7 | using Swan;
8 | using Swan.Logging;
9 | using Swan.Threading;
10 |
11 | internal class Mpu6050 : RunnerBase
12 | {
13 | private const byte PowerManagementRegister = 0x6B;
14 | private I2cDevice _device;
15 |
16 | public Mpu6050(bool isEnabled)
17 | : base(isEnabled)
18 | {
19 | // placeholder
20 | }
21 |
22 | private bool Sleep
23 | {
24 | get
25 | {
26 | var powerConfig = _device.ReadByte(PowerManagementRegister);
27 | return powerConfig.GetBit(6);
28 | }
29 | set
30 | {
31 | var powerConfig = _device.ReadByte(PowerManagementRegister);
32 | _device.Write(PowerManagementRegister, powerConfig.SetBit(6, value));
33 | }
34 | }
35 |
36 | private double Temperature
37 | {
38 | get
39 | {
40 | if (_device == null) return double.NaN;
41 |
42 | // receives the high byte (MSB) first and then the low byte (LSB) as an int 16
43 | var tempBytes = BitConverter.GetBytes(_device.ReadWord(0x41));
44 |
45 | // Since we are in little endian, we need to reverse so that we parse LSB and MSB
46 | var rawReading = BitConverter.ToInt16(new[] { tempBytes[1], tempBytes[0] }, 0);
47 | return (rawReading / 340d) + 36.53d;
48 | }
49 | }
50 |
51 | protected override void OnSetup()
52 | {
53 | "Scanning I2C bus . . .".Info(Name);
54 | var deviceAddresses = Board.Peripherals.ScanI2cBus();
55 | $"Found {deviceAddresses.Length} I2C device(s)".Info(Name);
56 | foreach (var address in deviceAddresses)
57 | $" Device on address 0x{address:X2}".Info(Name);
58 |
59 | if (deviceAddresses.Contains(0x68))
60 | {
61 | _device = Board.Peripherals.OpenI2cDevice(0x68);
62 | return;
63 | }
64 |
65 | if (deviceAddresses.Contains(0x69))
66 | {
67 | _device = Board.Peripherals.OpenI2cDevice(0x69);
68 | }
69 | }
70 |
71 | protected override void DoBackgroundWork(CancellationToken ct)
72 | {
73 | if (_device == null)
74 | return;
75 |
76 | Sleep = false;
77 |
78 | while (!ct.IsCancellationRequested)
79 | {
80 | Thread.Sleep(500);
81 | $"Temperature: {Temperature,6:0.000}".Info(Name);
82 | }
83 | }
84 |
85 | protected override void Cleanup()
86 | {
87 | if (_device == null) return;
88 |
89 | Sleep = true;
90 | _device.Dispose();
91 | _device = null;
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/ManagedModel/GpioPinClockService.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.ManagedModel
2 | {
3 | using NativeEnums;
4 | using NativeMethods;
5 | using System;
6 | using System.Linq;
7 |
8 | ///
9 | /// Provides a hardware clock services on the associated pin.
10 | /// Only a few pins support this.
11 | ///
12 | ///
13 | public sealed class GpioPinClockService : GpioPinServiceBase
14 | {
15 | ///
16 | /// Initializes a new instance of the class.
17 | ///
18 | /// The pin.
19 | internal GpioPinClockService(GpioPin pin)
20 | : base(pin)
21 | {
22 | // placeholder
23 | if (Constants.HardwareClockPins0.Contains(Pin.PinNumber))
24 | ClockChannel = 0;
25 | else if (Constants.HardwareClockPins2.Contains(Pin.PinNumber))
26 | ClockChannel = 2;
27 | else
28 | ClockChannel = -1;
29 | }
30 |
31 | ///
32 | /// Gets the clock channel.
33 | ///
34 | public int ClockChannel { get; private set; }
35 |
36 | ///
37 | /// Starts the hardware clock on this pin.
38 | /// All pins sharing the clock channel and running in clock mode will get theis new frequency.
39 | /// The frequency must be 0 (off) or 4689-250,000,000 (250M) Hz.
40 | ///
41 | /// The frequency. 0 (off) or 4689-250000000 (250M).
42 | public void Start(int frequency)
43 | {
44 | if (ClockChannel < 0) return;
45 | BoardException.ValidateResult(Pwm.GpioHardwareClock(Pin.PinGpio, Convert.ToUInt32(frequency)));
46 | }
47 |
48 | ///
49 | /// Stops the hardware clock on this pin.
50 | ///
51 | public void Stop()
52 | {
53 | if (ClockChannel < 0) return;
54 | BoardException.ValidateResult(Pwm.GpioHardwareClock(Pin.PinGpio, 0));
55 | }
56 |
57 | ///
58 | /// Resolves the availability of this service for the associated pin.
59 | ///
60 | ///
61 | /// True when the service is deemed as available.
62 | ///
63 | protected override bool ResolveAvailable()
64 | {
65 | if (Board.BoardType == BoardType.Type1 || Board.BoardType == BoardType.Type2)
66 | {
67 | if (Pin.PinNumber == 4)
68 | {
69 | ClockChannel = 0;
70 | return true;
71 | }
72 | else
73 | {
74 | ClockChannel = -1;
75 | return false;
76 | }
77 | }
78 |
79 | if (Constants.HardwareClockPins0.Contains(Pin.PinNumber))
80 | {
81 | ClockChannel = 0;
82 | return true;
83 | }
84 |
85 | if (Constants.HardwareClockPins2.Contains(Pin.PinNumber))
86 | {
87 | ClockChannel = 2;
88 | return true;
89 | }
90 |
91 | ClockChannel = -1;
92 | return false;
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/SpiFlags.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | using System;
4 |
5 | ///
6 | /// SPI Open Flags.
7 | ///
8 | [Flags]
9 | public enum SpiFlags
10 | {
11 | ///
12 | /// The default
13 | ///
14 | Default = 0b000000_0_0_0000_0_0_000_000_00,
15 |
16 | ///
17 | /// The mode bit0
18 | ///
19 | ModeBit0 = 0b000000_0_0_0000_0_0_000_000_01,
20 |
21 | ///
22 | /// The mode bit1
23 | ///
24 | ModeBit1 = 0b000000_0_0_0000_0_0_000_000_10,
25 |
26 | ///
27 | /// The chip enable active low bit0
28 | ///
29 | ChipEnableActiveLowBit0 = 0b000000_0_0_0000_0_0_000_001_00,
30 |
31 | ///
32 | /// The chip enable active low bit1
33 | ///
34 | ChipEnableActiveLowBit1 = 0b000000_0_0_0000_0_0_000_010_00,
35 |
36 | ///
37 | /// The chip enable active low bit2
38 | ///
39 | ChipEnableActiveLowBit2 = 0b000000_0_0_0000_0_0_000_100_00,
40 |
41 | ///
42 | /// The chip enable reserved bit0
43 | ///
44 | ChipEnableReservedBit0 = 0b000000_0_0_0000_0_0_001_000_00,
45 |
46 | ///
47 | /// The chip enable reserved bit1
48 | ///
49 | ChipEnableReservedBit1 = 0b000000_0_0_0000_0_0_010_000_00,
50 |
51 | ///
52 | /// The chip enable reserved bit2
53 | ///
54 | ChipEnableReservedBit2 = 0b000000_0_0_0000_0_0_100_000_00,
55 |
56 | ///
57 | /// The use auxiliary spi
58 | ///
59 | UseAuxiliarySpi = 0b000000_0_0_0000_0_1_000_000_00,
60 |
61 | ///
62 | /// The use3 wire device
63 | ///
64 | Use3WireDevice = 0b000000_0_0_0000_1_0_000_000_00,
65 |
66 | ///
67 | /// The byte count3 wire bit0
68 | ///
69 | ByteCount3WireBit0 = 0b000000_0_0_0001_0_0_000_000_00,
70 |
71 | ///
72 | /// The byte count3 wire bit1
73 | ///
74 | ByteCount3WireBit1 = 0b000000_0_0_0010_0_0_000_000_00,
75 |
76 | ///
77 | /// The byte count3 wire bit2
78 | ///
79 | ByteCount3WireBit2 = 0b000000_0_0_0100_0_0_000_000_00,
80 |
81 | ///
82 | /// The byte count3 wire bit3
83 | ///
84 | ByteCount3WireBit3 = 0b000000_0_0_1000_0_0_000_000_00,
85 |
86 | ///
87 | /// The invert mosi
88 | ///
89 | InvertMosi = 0b000000_0_1_0000_0_0_000_000_00,
90 |
91 | ///
92 | /// The invert miso
93 | ///
94 | InvertMiso = 0b000000_1_0_0000_0_0_000_000_00,
95 |
96 | ///
97 | /// The word size bit0
98 | ///
99 | WordSizeBit0 = 0b000001_0_0_0000_0_0_000_000_00,
100 |
101 | ///
102 | /// The word size bit1
103 | ///
104 | WordSizeBit1 = 0b000010_0_0_0000_0_0_000_000_00,
105 |
106 | ///
107 | /// The word size bit2
108 | ///
109 | WordSizeBit2 = 0b000100_0_0_0000_0_0_000_000_00,
110 |
111 | ///
112 | /// The word size bit3
113 | ///
114 | WordSizeBit3 = 0b001000_0_0_0000_0_0_000_000_00,
115 |
116 | ///
117 | /// The word size bit4
118 | ///
119 | WordSizeBit4 = 0b010000_0_0_0000_0_0_000_000_00,
120 |
121 | ///
122 | /// The word size bit5
123 | ///
124 | WordSizeBit5 = 0b100000_0_0_0000_0_0_000_000_00,
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/BitMask.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | using System;
4 |
5 | ///
6 | /// Provides an enumeration of a 32-bit mask.
7 | ///
8 | [Flags]
9 | public enum BitMask : uint
10 | {
11 | /// An empty bitmask
12 | None = 0x00000000,
13 |
14 | /// An full bitmask
15 | All = 0xFFFFFFFF,
16 |
17 | /// The bit at index 00, from right LSB to left MSB
18 | Bit00 = 0x00000001,
19 |
20 | /// The bit at index 01, from right LSB to left MSB
21 | Bit01 = 0x00000002,
22 |
23 | /// The bit at index 02, from right LSB to left MSB
24 | Bit02 = 0x00000004,
25 |
26 | /// The bit at index 03, from right LSB to left MSB
27 | Bit03 = 0x00000008,
28 |
29 | /// The bit at index 04, from right LSB to left MSB
30 | Bit04 = 0x00000010,
31 |
32 | /// The bit at index 05, from right LSB to left MSB
33 | Bit05 = 0x00000020,
34 |
35 | /// The bit at index 06, from right LSB to left MSB
36 | Bit06 = 0x00000040,
37 |
38 | /// The bit at index 07, from right LSB to left MSB
39 | Bit07 = 0x00000080,
40 |
41 | /// The bit at index 08, from right LSB to left MSB
42 | Bit08 = 0x00000100,
43 |
44 | /// The bit at index 09, from right LSB to left MSB
45 | Bit09 = 0x00000200,
46 |
47 | /// The bit at index 10, from right LSB to left MSB
48 | Bit10 = 0x00000400,
49 |
50 | /// The bit at index 11, from right LSB to left MSB
51 | Bit11 = 0x00000800,
52 |
53 | /// The bit at index 12, from right LSB to left MSB
54 | Bit12 = 0x00001000,
55 |
56 | /// The bit at index 13, from right LSB to left MSB
57 | Bit13 = 0x00002000,
58 |
59 | /// The bit at index 14, from right LSB to left MSB
60 | Bit14 = 0x00004000,
61 |
62 | /// The bit at index 15, from right LSB to left MSB
63 | Bit15 = 0x00008000,
64 |
65 | /// The bit at index 16, from right LSB to left MSB
66 | Bit16 = 0x00010000,
67 |
68 | /// The bit at index 17, from right LSB to left MSB
69 | Bit17 = 0x00020000,
70 |
71 | /// The bit at index 18, from right LSB to left MSB
72 | Bit18 = 0x00040000,
73 |
74 | /// The bit at index 19, from right LSB to left MSB
75 | Bit19 = 0x00080000,
76 |
77 | /// The bit at index 20, from right LSB to left MSB
78 | Bit20 = 0x00100000,
79 |
80 | /// The bit at index 21, from right LSB to left MSB
81 | Bit21 = 0x00200000,
82 |
83 | /// The bit at index 22, from right LSB to left MSB
84 | Bit22 = 0x00400000,
85 |
86 | /// The bit at index 23, from right LSB to left MSB
87 | Bit23 = 0x00800000,
88 |
89 | /// The bit at index 24, from right LSB to left MSB
90 | Bit24 = 0x01000000,
91 |
92 | /// The bit at index 25, from right LSB to left MSB
93 | Bit25 = 0x02000000,
94 |
95 | /// The bit at index 26, from right LSB to left MSB
96 | Bit26 = 0x04000000,
97 |
98 | /// The bit at index 27, from right LSB to left MSB
99 | Bit27 = 0x08000000,
100 |
101 | /// The bit at index 28, from right LSB to left MSB
102 | Bit28 = 0x10000000,
103 |
104 | /// The bit at index 29, from right LSB to left MSB
105 | Bit29 = 0x20000000,
106 |
107 | /// The bit at index 30, from right LSB to left MSB
108 | Bit30 = 0x40000000,
109 |
110 | /// The bit at index 31, from right LSB to left MSB
111 | Bit31 = 0x80000000,
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/ManagedModel/SoftSpiChannel.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.ManagedModel
2 | {
3 | using NativeEnums;
4 | using NativeMethods;
5 | using System;
6 |
7 | ///
8 | /// Provides a bit-banged version of a SPI channel.
9 | ///
10 | ///
11 | public sealed class SoftSpiChannel : IDisposable
12 | {
13 | private bool _isDisposed;
14 |
15 | ///
16 | /// Initializes a new instance of the class.
17 | ///
18 | /// The cs pin.
19 | /// The miso pin.
20 | /// The mosi pin.
21 | /// The clock pin.
22 | /// The baud rate.
23 | /// The flags.
24 | internal SoftSpiChannel(GpioPin csPin, GpioPin misoPin, GpioPin mosiPin, GpioPin clockPin, int baudRate, SoftSpiFlags flags)
25 | {
26 | BoardException.ValidateResult(Spi.BbSPIOpen(
27 | (UserGpio)csPin.PinNumber,
28 | (UserGpio)misoPin.PinNumber,
29 | (UserGpio)mosiPin.PinNumber,
30 | (UserGpio)clockPin.PinNumber,
31 | Convert.ToUInt32(baudRate),
32 | flags));
33 |
34 | Handle = (UserGpio)csPin.PinNumber;
35 | ChipSelectPin = csPin;
36 | MosiPin = mosiPin;
37 | MisoPin = misoPin;
38 | ClockPin = clockPin;
39 | BaudRate = baudRate;
40 | Flags = flags;
41 | }
42 |
43 | ///
44 | /// Gets the handle.
45 | ///
46 | public UserGpio Handle { get; }
47 |
48 | ///
49 | /// Gets the chip select pin.
50 | ///
51 | public GpioPin ChipSelectPin { get; }
52 |
53 | ///
54 | /// Gets the MOSI pin.
55 | ///
56 | public GpioPin MosiPin { get; }
57 |
58 | ///
59 | /// Gets the MISO pin.
60 | ///
61 | public GpioPin MisoPin { get; }
62 |
63 | ///
64 | /// Gets the clock pin.
65 | ///
66 | public GpioPin ClockPin { get; }
67 |
68 | ///
69 | /// Gets the baud rate.
70 | ///
71 | public int BaudRate { get; }
72 |
73 | ///
74 | /// Gets the flags.
75 | ///
76 | public SoftSpiFlags Flags { get; }
77 |
78 | ///
79 | /// Transfers the specified transmit buffer and returns the read bytes in a new buffer.
80 | ///
81 | /// The transmit buffer.
82 | /// The received bytes as a result of writing to the ring buffer.
83 | public byte[] Transfer(byte[] transmitBuffer)
84 | {
85 | if (_isDisposed)
86 | throw new ObjectDisposedException(nameof(SoftSpiChannel));
87 |
88 | var receiveBuffer = new byte[transmitBuffer.Length];
89 | var result = BoardException.ValidateResult(Spi.BbSPIXfer(Handle, transmitBuffer, receiveBuffer, Convert.ToUInt32(receiveBuffer.Length)));
90 | if (result == receiveBuffer.Length)
91 | return receiveBuffer;
92 |
93 | var output = new byte[result];
94 | Buffer.BlockCopy(receiveBuffer, 0, output, 0, result);
95 | return output;
96 | }
97 |
98 | ///
99 | public void Dispose() => Dispose(true);
100 |
101 | ///
102 | /// Releases unmanaged and - optionally - managed resources.
103 | ///
104 | /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
105 | private void Dispose(bool alsoManaged)
106 | {
107 | if (_isDisposed) return;
108 |
109 | _isDisposed = true;
110 | if (alsoManaged)
111 | {
112 | Spi.BbSPIClose(Handle);
113 | }
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/ManagedModel/SoftSerialPort.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.ManagedModel
2 | {
3 | using NativeEnums;
4 | using NativeMethods;
5 | using System;
6 |
7 | ///
8 | /// Provides a software based (bit-banged Serial Port).
9 | ///
10 | public sealed class SoftSerialPort : IDisposable
11 | {
12 | private readonly GpioPin _transmitPin;
13 | private bool _isDisposed;
14 |
15 | ///
16 | /// Initializes a new instance of the class.
17 | ///
18 | /// The receive pin.
19 | /// The transmit pin.
20 | /// The baud rate.
21 | /// The data bits.
22 | /// if set to true [invert].
23 | internal SoftSerialPort(GpioPin receivePin, GpioPin transmitPin, UartRate baudRate, int dataBits, bool invert)
24 | {
25 | BoardException.ValidateResult(
26 | Serial.GpioSerialReadOpen((UserGpio)receivePin.PinNumber, Convert.ToUInt32(baudRate), Convert.ToUInt32(dataBits)));
27 |
28 | Handle = (UserGpio)receivePin.PinNumber;
29 | DataBits = dataBits;
30 | BaudRate = (int)baudRate;
31 |
32 | if (invert)
33 | {
34 | Serial.GpioSerialReadInvert(Handle, true);
35 | Invert = true;
36 | }
37 |
38 | _transmitPin = transmitPin;
39 | }
40 |
41 | ///
42 | /// Gets or sets the stop bits. Defaults to 2 stop bits.
43 | ///
44 | public int StopBits { get; set; } = 2;
45 |
46 | ///
47 | /// Gets the baud rate.
48 | ///
49 | public int BaudRate { get; }
50 |
51 | ///
52 | /// Gets a value indicating whether the IO is inverted.
53 | ///
54 | public bool Invert { get; }
55 |
56 | ///
57 | /// Gets the data bits.
58 | ///
59 | public int DataBits { get; }
60 |
61 | ///
62 | /// Gets the handle.
63 | ///
64 | public UserGpio Handle { get; }
65 |
66 | ///
67 | /// Reads up to count bytes.
68 | ///
69 | /// The count.
70 | /// The bytes that were read.
71 | public byte[] Read(int count) =>
72 | Serial.GpioSerialRead(Handle, count);
73 |
74 | ///
75 | /// Writes the specified buffer to the transmit pin as a free-form wave.
76 | ///
77 | /// The buffer.
78 | public void Write(byte[] buffer)
79 | {
80 | Waves.GpioWaveClear();
81 | BoardException.ValidateResult(
82 | Waves.GpioWaveAddSerial(
83 | (UserGpio)_transmitPin.PinNumber,
84 | Convert.ToUInt32(BaudRate),
85 | Convert.ToUInt32(DataBits),
86 | Convert.ToUInt32(StopBits),
87 | 0,
88 | Convert.ToUInt32(buffer.Length),
89 | buffer));
90 |
91 | var waveId = BoardException.ValidateResult(
92 | Waves.GpioWaveCreate());
93 | Waves.GpioWaveTxSend(Convert.ToUInt32(waveId), WaveMode.OneShotSync);
94 |
95 | // Wait for the wave to finish sending
96 | while (Waves.GpioWaveTxBusy() > 0)
97 | Board.Timing.Sleep(1);
98 |
99 | Waves.GpioWaveDelete(Convert.ToUInt32(waveId));
100 | }
101 |
102 | ///
103 | public void Dispose() => Dispose(true);
104 |
105 | ///
106 | /// Releases unmanaged and - optionally - managed resources.
107 | ///
108 | /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
109 | private void Dispose(bool alsoManaged)
110 | {
111 | if (_isDisposed) return;
112 | _isDisposed = true;
113 |
114 | if (alsoManaged)
115 | {
116 | Serial.GpioSerialReadClose(Handle);
117 | }
118 | }
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio.Workbench/Runners/PiOled.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.Workbench.Runners
2 | {
3 | using System;
4 | using System.Diagnostics;
5 | using System.Drawing;
6 | using System.Drawing.Drawing2D;
7 | using System.Drawing.Imaging;
8 | using System.Threading;
9 | using Swan.Logging;
10 | using Swan.Threading;
11 | using RaspberryIO.Peripherals;
12 |
13 | #pragma warning disable CA1001 // Types that own disposable fields should be disposable
14 | internal class PiOled : RunnerBase
15 | #pragma warning restore CA1001 // Types that own disposable fields should be disposable
16 | {
17 | private OledDisplaySsd1306 _display;
18 |
19 | internal PiOled(bool isEnabled)
20 | : base(isEnabled)
21 | {
22 | // placeholder
23 | }
24 |
25 | protected override void OnSetup()
26 | {
27 | _display = new OledDisplaySsd1306(OledDisplaySsd1306.DisplayModel.Display128X32);
28 | }
29 |
30 | protected override void DoBackgroundWork(CancellationToken ct)
31 | {
32 | var currentX = 0;
33 | var currentY = 0;
34 | var currentVal = true;
35 | var sw = new Stopwatch();
36 | var cycleSw = new Stopwatch();
37 | var frameCount = 0d;
38 | var cycleCount = 0;
39 | const double currentThreshold = 0.5d;
40 |
41 | var bitmap = new Bitmap(_display.Width, _display.Height, PixelFormat.Format32bppArgb);
42 | var graphicPen = Pens.White;
43 | var graphics = Graphics.FromImage(bitmap);
44 | {
45 | graphics.CompositingQuality = CompositingQuality.HighSpeed;
46 | graphics.InterpolationMode = InterpolationMode.Default;
47 | graphics.SmoothingMode = SmoothingMode.Default;
48 | }
49 |
50 | // ProcessRunner.GetProcessOutputAsync("hostname", "-I").GetAwaiter().GetResult().RemoveControlChars().Trim().Truncate(15);
51 | const string address = "W.X.Y.Z";
52 |
53 | sw.Start();
54 | cycleSw.Start();
55 | while (!ct.IsCancellationRequested)
56 | {
57 | cycleSw.Restart();
58 |
59 | // Display.Render(
60 | // $"X: {currentX,3} Y: {currentY,3}",
61 | // $"Cycles: {cycleCount,6} T {currentThreshold:p}",
62 | // $"{DateTime.Now}",
63 | // $"IP: {address} THIS IS SOME VERY LONG LINE",
64 | // $"THIS SHOULD NOT BE SHOWN");
65 | graphics.Clear(Color.Black);
66 | _display.DrawText(bitmap,
67 | graphics,
68 | $"X: {currentX,3} Y: {currentY,3}",
69 | $"Cycles: {cycleCount,6} T {currentThreshold:p}",
70 | $"{DateTime.Now}",
71 | $"IP: {address}");
72 | graphics.DrawEllipse(graphicPen, currentX, 24, 6, 6);
73 | graphics.Flush();
74 | _display.LoadBitmap(bitmap, currentThreshold, 0, 0);
75 | _display[currentX, currentY] = true; // currentVal;
76 | _display.Render();
77 |
78 | currentX++;
79 | frameCount += 1;
80 | cycleCount += 1;
81 |
82 | if (currentX >= _display.Width)
83 | {
84 | var elapsedSeconds = sw.Elapsed.TotalSeconds;
85 | var framesPerSecond = frameCount / elapsedSeconds;
86 | $"Contrast: {_display.Contrast}. X: {currentX} Y: {currentY} Frames: {cycleCount:0} Elapsed {elapsedSeconds:0.000} FPS: {framesPerSecond:0.000}".Info(Name);
87 | sw.Restart();
88 | frameCount = 0;
89 | currentX = 0;
90 | currentY += 1;
91 | }
92 |
93 | if (currentY >= _display.Height)
94 | {
95 | currentY = 0;
96 | currentVal = !currentVal;
97 | }
98 |
99 | if (cycleSw.ElapsedMilliseconds > 40)
100 | continue;
101 |
102 | // Board.Timing.Sleep(40 - cycleSw.ElapsedMilliseconds);
103 | }
104 |
105 | graphics.Dispose();
106 | bitmap.Dispose();
107 | }
108 |
109 | protected override void Cleanup()
110 | {
111 | _display.Dispose();
112 | }
113 | }
114 | }
--------------------------------------------------------------------------------
/Unosquare.PiGpio/ManagedModel/SpiChannel.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.ManagedModel
2 | {
3 | using NativeEnums;
4 | using NativeMethods;
5 | using System;
6 |
7 | ///
8 | /// Provides access to the Hardware SPI channels.
9 | ///
10 | ///
11 | public sealed class SpiChannel : IDisposable
12 | {
13 | private bool _isDisposed;
14 |
15 | ///
16 | /// Initializes a new instance of the class.
17 | ///
18 | /// The channel.
19 | /// The baud rate.
20 | /// The flags.
21 | internal SpiChannel(SpiChannelId channel, int baudRate, SpiFlags flags)
22 | {
23 | BaudRate = baudRate;
24 | Channel = channel;
25 | Handle = Spi.SpiOpen(channel, baudRate, flags);
26 | }
27 |
28 | ///
29 | /// Gets the baud rate in bits per second.
30 | ///
31 | public int BaudRate { get; }
32 |
33 | ///
34 | /// Gets the SPI channel identifier.
35 | ///
36 | public SpiChannelId Channel { get; }
37 |
38 | ///
39 | /// Gets the SPI flags this channel was opened with.
40 | ///
41 | public SpiFlags Flags { get; }
42 |
43 | ///
44 | /// Gets the SPI channel handle.
45 | ///
46 | public UIntPtr Handle { get; private set; }
47 |
48 | ///
49 | /// Reads up to one tenth of the byte rate.
50 | ///
51 | /// The bytes that were read.
52 | public byte[] Read() => Read(BaudRate / 8 / 10);
53 |
54 | ///
55 | /// Reads up to the specified number of bytes.
56 | ///
57 | /// The count.
58 | /// The bytes read.
59 | public byte[] Read(int count) => Spi.SpiRead(Handle, count);
60 |
61 | ///
62 | /// Reads int the specified buffer.
63 | ///
64 | /// The buffer.
65 | /// The offset.
66 | /// The count.
67 | /// The number of bytes read into the buffer.
68 | public int Read(byte[] buffer, int offset, int count)
69 | {
70 | var data = Spi.SpiRead(Handle, count);
71 | Buffer.BlockCopy(data, 0, buffer, offset, data.Length);
72 | return data.Length;
73 | }
74 |
75 | ///
76 | /// Writes the specified buffer.
77 | ///
78 | /// The buffer.
79 | /// The number of bytes written.
80 | public int Write(byte[] buffer) => Spi.SpiWrite(Handle, buffer);
81 |
82 | ///
83 | /// Writes the specified buffer.
84 | ///
85 | /// The buffer.
86 | /// The offset.
87 | /// The count.
88 | /// The number of bytes written.
89 | public int Write(byte[] buffer, int offset, int count)
90 | {
91 | var data = new byte[count];
92 | Buffer.BlockCopy(buffer, offset, data, 0, count);
93 | return Spi.SpiWrite(Handle, data);
94 | }
95 |
96 | ///
97 | /// Transfers the specified buffer and simultaneously reads the same amount of buyes in that send buffer.
98 | ///
99 | /// The buffer.
100 | /// The bytes that were read.
101 | public byte[] Transfer(byte[] buffer) => Spi.SpiXfer(Handle, buffer);
102 |
103 | ///
104 | public void Dispose() => Dispose(true);
105 |
106 | ///
107 | /// Releases unmanaged and - optionally - managed resources.
108 | ///
109 | /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
110 | private void Dispose(bool alsoManaged)
111 | {
112 | if (_isDisposed) return;
113 |
114 | if (alsoManaged)
115 | {
116 | Spi.SpiClose(Handle);
117 | Handle = UIntPtr.Zero;
118 | }
119 |
120 | _isDisposed = true;
121 | }
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/ManagedModel/UartPort.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.ManagedModel
2 | {
3 | using NativeEnums;
4 | using NativeMethods;
5 | using System;
6 |
7 | ///
8 | /// Provides libpigpio implementation of a UART port.
9 | /// Alternatively you can use the System.IO.Ports.SerialPort implementation.
10 | ///
11 | public sealed class UartPort : IDisposable
12 | {
13 | private bool IsDisposed = false;
14 |
15 | ///
16 | /// Initializes a new instance of the class.
17 | ///
18 | /// Name of the port.
19 | /// The baud rate.
20 | internal UartPort(string portName, UartRate baudRate)
21 | {
22 | Handle = Uart.SerOpen(portName, baudRate);
23 | BaudRate = (int)baudRate;
24 | PortName = portName;
25 | }
26 |
27 | ///
28 | /// Gets the serial port handle.
29 | ///
30 | public UIntPtr Handle { get; private set; }
31 |
32 | ///
33 | /// Gets the baud rate.
34 | ///
35 | public int BaudRate { get; }
36 |
37 | ///
38 | /// Gets the name of the port.
39 | ///
40 | public string PortName { get; }
41 |
42 | ///
43 | /// Gets the number of available bytes to read in the hardware buffer.
44 | ///
45 | public int Available => BoardException.ValidateResult(Uart.SerDataAvailable(Handle));
46 |
47 | ///
48 | /// Reads the byte.
49 | ///
50 | /// The byte value. Null if no bytes were read.
51 | public byte? ReadByte()
52 | {
53 | var result = Uart.SerReadByte(Handle);
54 | if (result >= 0)
55 | return (byte)result;
56 |
57 | return default;
58 | }
59 |
60 | ///
61 | /// Reads this instance.
62 | ///
63 | /// A buffer containing the bytes.
64 | public byte[] Read() => Read(Available);
65 |
66 | ///
67 | /// Reads the specified number of bytes.
68 | ///
69 | /// The count.
70 | /// A byte array of read bytes.
71 | public byte[] Read(int count)
72 | {
73 | var buffer = new byte[count];
74 | var result = BoardException.ValidateResult(Uart.SerRead(Handle, buffer, (uint)count));
75 | if (result == 0) return new byte[0];
76 | if (result == count)
77 | return buffer;
78 |
79 | var output = new byte[result];
80 | Buffer.BlockCopy(buffer, 0, output, 0, result);
81 | return output;
82 | }
83 |
84 | ///
85 | /// Writes the specified value.
86 | ///
87 | /// The value.
88 | public void Write(byte value) =>
89 | BoardException.ValidateResult(Uart.SerWriteByte(Handle, value));
90 |
91 | ///
92 | /// Writes the specified buffer.
93 | ///
94 | /// The buffer.
95 | /// The count.
96 | public void Write(byte[] buffer, int count) =>
97 | BoardException.ValidateResult(Uart.SerWrite(Handle, buffer, (uint)count));
98 |
99 | ///
100 | /// Writes the specified buffer.
101 | ///
102 | /// The buffer.
103 | public void Write(byte[] buffer) =>
104 | Write(buffer, buffer.Length);
105 |
106 | ///
107 | /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
108 | ///
109 | public void Dispose() =>
110 | Dispose(true);
111 |
112 | ///
113 | /// Releases unmanaged and - optionally - managed resources.
114 | ///
115 | /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
116 | private void Dispose(bool alsoManaged)
117 | {
118 | if (IsDisposed) return;
119 | IsDisposed = true;
120 |
121 | if (alsoManaged)
122 | {
123 | Uart.SerClose(Handle);
124 | Handle = UIntPtr.Zero;
125 | }
126 | }
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeEnums/SystemGpio.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeEnums
2 | {
3 | ///
4 | /// Provides an enumeration of System GPIOs from 0 to 53.
5 | /// User GPIOs are from 0 to 31 (some of them are reserved depending on hardware).
6 | /// All chip GPIOs go from 0 to 53. It is safe to read all of them but writing to some
7 | /// of them might crash the hardware and corrupt the SD card. So use documetned ones only.
8 | ///
9 | public enum SystemGpio : int
10 | {
11 | /// The BCM GPIO 00
12 | Bcm00 = 0,
13 |
14 | /// The BCM GPIO 01
15 | Bcm01 = 1,
16 |
17 | /// The BCM GPIO 02
18 | Bcm02 = 2,
19 |
20 | /// The BCM GPIO 03
21 | Bcm03 = 3,
22 |
23 | /// The BCM GPIO 04
24 | Bcm04 = 4,
25 |
26 | /// The BCM GPIO 05
27 | Bcm05 = 5,
28 |
29 | /// The BCM GPIO 06
30 | Bcm06 = 6,
31 |
32 | /// The BCM GPIO 07
33 | Bcm07 = 7,
34 |
35 | /// The BCM GPIO 08
36 | Bcm08 = 8,
37 |
38 | /// The BCM GPIO 09
39 | Bcm09 = 9,
40 |
41 | /// The BCM GPIO 10
42 | Bcm10 = 10,
43 |
44 | /// The BCM GPIO 11
45 | Bcm11 = 11,
46 |
47 | /// The BCM GPIO 12
48 | Bcm12 = 12,
49 |
50 | /// The BCM GPIO 13
51 | Bcm13 = 13,
52 |
53 | /// The BCM GPIO 14
54 | Bcm14 = 14,
55 |
56 | /// The BCM GPIO 15
57 | Bcm15 = 15,
58 |
59 | /// The BCM GPIO 16
60 | Bcm16 = 16,
61 |
62 | /// The BCM GPIO 17
63 | Bcm17 = 17,
64 |
65 | /// The BCM GPIO 18
66 | Bcm18 = 18,
67 |
68 | /// The BCM GPIO 19
69 | Bcm19 = 19,
70 |
71 | /// The BCM GPIO 20
72 | Bcm20 = 20,
73 |
74 | /// The BCM GPIO 21
75 | Bcm21 = 21,
76 |
77 | /// The BCM GPIO 22
78 | Bcm22 = 22,
79 |
80 | /// The BCM GPIO 23
81 | Bcm23 = 23,
82 |
83 | /// The BCM GPIO 24
84 | Bcm24 = 24,
85 |
86 | /// The BCM GPIO 25
87 | Bcm25 = 25,
88 |
89 | /// The BCM GPIO 26
90 | Bcm26 = 26,
91 |
92 | /// The BCM GPIO 27
93 | Bcm27 = 27,
94 |
95 | /// The BCM GPIO 28
96 | Bcm28 = 28,
97 |
98 | /// The BCM GPIO 29
99 | Bcm29 = 29,
100 |
101 | /// The BCM GPIO 30
102 | Bcm30 = 30,
103 |
104 | /// The BCM GPIO 31
105 | Bcm31 = 31,
106 |
107 | /// The BCM GPIO 32
108 | Bcm32 = 32,
109 |
110 | /// The BCM GPIO 33
111 | Bcm33 = 33,
112 |
113 | /// The BCM GPIO 34
114 | Bcm34 = 34,
115 |
116 | /// The BCM GPIO 35
117 | Bcm35 = 35,
118 |
119 | /// The BCM GPIO 36
120 | Bcm36 = 36,
121 |
122 | /// The BCM GPIO 37
123 | Bcm37 = 37,
124 |
125 | /// The BCM GPIO 38
126 | Bcm38 = 38,
127 |
128 | /// The BCM GPIO 39
129 | Bcm39 = 39,
130 |
131 | /// The BCM GPIO 40
132 | Bcm40 = 40,
133 |
134 | /// The BCM GPIO 41
135 | Bcm41 = 41,
136 |
137 | /// The BCM GPIO 42
138 | Bcm42 = 42,
139 |
140 | /// The BCM GPIO 43
141 | Bcm43 = 43,
142 |
143 | /// The BCM GPIO 44
144 | Bcm44 = 44,
145 |
146 | /// The BCM GPIO 45
147 | Bcm45 = 45,
148 |
149 | /// The BCM GPIO 46
150 | Bcm46 = 46,
151 |
152 | /// The BCM GPIO 47
153 | Bcm47 = 47,
154 |
155 | /// The BCM GPIO 48
156 | Bcm48 = 48,
157 |
158 | /// The BCM GPIO 49
159 | Bcm49 = 49,
160 |
161 | /// The BCM GPIO 50
162 | Bcm50 = 50,
163 |
164 | /// The BCM GPIO 51
165 | Bcm51 = 51,
166 |
167 | /// The BCM GPIO 52
168 | Bcm52 = 52,
169 |
170 | /// The BCM GPIO 53
171 | Bcm53 = 53,
172 | }
173 | }
174 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/ManagedModel/SoftI2cBus.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.ManagedModel
2 | {
3 | using NativeEnums;
4 | using NativeMethods;
5 | using System;
6 |
7 | ///
8 | /// Provides a software based (bit-banged) I2C bus on 2 pins.
9 | ///
10 | ///
11 | public sealed class SoftI2cBus : IDisposable
12 | {
13 | ///
14 | /// The default baud rate for a software-based I2C bus
15 | /// Baud rate can go up to 500kbits per second.
16 | ///
17 | public const int DefaultBaudRate = 100000; // 100kbits per second
18 |
19 | ///
20 | /// To detect redundant calls.
21 | ///
22 | private bool _isDisposed; // To detect redundant calls
23 |
24 | ///
25 | /// Initializes a new instance of the class.
26 | ///
27 | /// The data pin.
28 | /// The clock pin.
29 | /// The baud rate.
30 | internal SoftI2cBus(GpioPin dataPin, GpioPin clockPin, int baudRate)
31 | {
32 | BoardException.ValidateResult(I2c.BbI2COpen((UserGpio)dataPin.PinNumber, (UserGpio)clockPin.PinNumber, Convert.ToUInt32(baudRate)));
33 | Handle = (UserGpio)dataPin.PinNumber;
34 | DataPin = dataPin;
35 | ClockPin = clockPin;
36 | BaudRate = baudRate;
37 | }
38 |
39 | ///
40 | /// Gets or the I2C bus handle. This points to the SDA (data) pin of the I2C bus.
41 | ///
42 | public UserGpio Handle { get; }
43 |
44 | ///
45 | /// Gets the data pin.
46 | ///
47 | public GpioPin DataPin { get; }
48 |
49 | ///
50 | /// Gets the clock pin.
51 | ///
52 | public GpioPin ClockPin { get; }
53 |
54 | ///
55 | /// Gets the baud rate.
56 | ///
57 | public int BaudRate { get; }
58 |
59 | ///
60 | /// Writes data to the specified address.
61 | ///
62 | /// The address.
63 | /// The buffer. Recommended 32 bytes max.
64 | public void Write(byte address, byte[] buffer)
65 | {
66 | var data = new byte[7 + buffer.Length];
67 | data[0] = 0x04; // Set Address
68 | data[1] = address; // Address Literal
69 | data[2] = 0x02; // Start Condition
70 | data[3] = 0x07; // Write Command
71 | data[4] = Convert.ToByte(data.Length); // data length;
72 | data[data.Length - 2] = 0x03; // Stop condition
73 | data[data.Length - 1] = 0x00; // End command;
74 |
75 | // copy buffer data to command
76 | Buffer.BlockCopy(buffer, 0, data, 5, data.Length);
77 |
78 | var output = new byte[32];
79 | BoardException.ValidateResult(
80 | I2c.BbI2CZip(Handle, data, Convert.ToUInt32(data.Length), output, Convert.ToUInt32(output.Length)));
81 | }
82 |
83 | ///
84 | /// Reads data from the specified address.
85 | ///
86 | /// The address.
87 | /// The count. Recommended 32 as maximum.
88 | /// The byte array that was read.
89 | public byte[] Read(byte address, int count)
90 | {
91 | var data = new byte[7];
92 | data[0] = 0x04; // Set Address
93 | data[1] = address; // Address Literal
94 | data[2] = 0x02; // Start Condition
95 | data[3] = 0x06; // Write Command
96 | data[4] = Convert.ToByte(count); // data length;
97 | data[5] = 0x03; // Stop condition
98 | data[6] = 0x00; // End command;
99 |
100 | var output = new byte[count];
101 | var outCount = BoardException.ValidateResult(
102 | I2c.BbI2CZip(Handle, data, Convert.ToUInt32(data.Length), output, Convert.ToUInt32(output.Length)));
103 |
104 | if (output.Length == outCount)
105 | return output;
106 |
107 | var result = new byte[outCount];
108 | Buffer.BlockCopy(output, 0, result, 0, outCount);
109 | return result;
110 | }
111 |
112 | ///
113 | public void Dispose() => Dispose(true);
114 |
115 | ///
116 | /// Releases unmanaged and - optionally - managed resources.
117 | ///
118 | /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
119 | private void Dispose(bool alsoManaged)
120 | {
121 | if (_isDisposed) return;
122 | _isDisposed = true;
123 |
124 | if (alsoManaged)
125 | {
126 | I2c.BbI2CClose(Handle);
127 | }
128 | }
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/Board.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio
2 | {
3 | using ManagedModel;
4 | using NativeEnums;
5 | using NativeMethods;
6 | using System;
7 |
8 | ///
9 | /// Represents the Raspberry Pi Board and provides
10 | /// access to all GPIO initialization and functionality.
11 | ///
12 | public static class Board
13 | {
14 | ///
15 | /// Initializes static members of the class.
16 | ///
17 | static Board()
18 | {
19 | try
20 | {
21 | // Retrieve internal configuration
22 | var config = (int)Setup.GpioCfgGetInternals();
23 |
24 | // config = config.ApplyBits(false, 3, 2, 1, 0); // Clear debug flags
25 | /*
26 | MJA
27 | If you use Visual Studio 2019 together with VSMonoDebugger and X11 remote debugging,
28 | you need to enable the next line, otherwise Mono will catch the Signals and stop
29 | debugging immediately although native started program will work ok
30 | */
31 | config = config | (int)ConfigFlags.NoSignalHandler;
32 | Setup.GpioCfgSetInternals((ConfigFlags)config);
33 |
34 | var initResultCode = Setup.GpioInitialise();
35 | /*
36 | MJA
37 | Setup.GpioInitialise() gives back value greater than zero if it has success.
38 | More in detail:
39 | The given back number is the version of the library version you use on RasPi.
40 | Therefore a greater or equal comparison would make potentially more sense.
41 | */
42 | // IsAvailable = initResultCode == ResultCode.Ok;
43 | IsAvailable = initResultCode >= ResultCode.Ok;
44 |
45 | // You will need to compile libgpio.h adding
46 | // #define EMBEDDED_IN_VM
47 | // Also, remove the atexit( ... call in pigpio.c
48 | // So there is no output or signal handling
49 | }
50 | catch { IsAvailable = false; }
51 |
52 | // Populate basic information
53 | HardwareRevision = Utilities.GpioHardwareRevision();
54 | LibraryVersion = Utilities.GpioVersion();
55 | BoardType = Constants.GetBoardType(HardwareRevision);
56 |
57 | // Instantiate collections and services.
58 | Pins = new GpioPinCollection();
59 | GpioPads = new GpioPadCollection();
60 | BankA = new GpioBank(1);
61 | BankB = new GpioBank(2);
62 | Timing = new BoardTimingService();
63 | Peripherals = new BoardPeripheralsService();
64 | Waves = new BoardWaveService();
65 | }
66 |
67 | ///
68 | /// Gets a value indicating whether the board has been initialized.
69 | ///
70 | public static bool IsAvailable { get; private set; }
71 |
72 | ///
73 | /// Gets the hardware revision number.
74 | ///
75 | public static long HardwareRevision { get; }
76 |
77 | ///
78 | /// Gets the library version number.
79 | ///
80 | public static long LibraryVersion { get; }
81 |
82 | ///
83 | /// Gets the type of the board. See the enumeration.
84 | ///
85 | public static BoardType BoardType { get; }
86 |
87 | ///
88 | /// Provides access to the pin collection.
89 | ///
90 | public static GpioPinCollection Pins { get; }
91 |
92 | ///
93 | /// Provides access to the electrical pads.
94 | ///
95 | public static GpioPadCollection GpioPads { get; }
96 |
97 | ///
98 | /// Provides access to GPIO bank 1 (or A)
99 | /// consisting of GPIO 0 to 31.
100 | ///
101 | public static GpioBank BankA { get; }
102 |
103 | ///
104 | /// Provides access to GPIO bank 2 (or B)
105 | /// consisting of GPIO 32 to 53.
106 | ///
107 | public static GpioBank BankB { get; }
108 |
109 | ///
110 | /// Provides timing and date functions.
111 | ///
112 | public static BoardTimingService Timing { get; }
113 |
114 | ///
115 | /// Provides peripheral communication buses available to the board.
116 | ///
117 | public static BoardPeripheralsService Peripherals { get; }
118 |
119 | ///
120 | /// Provides a service to build and send waveforms
121 | /// with precisions of a few microseconds ~5us per pulse.
122 | ///
123 | public static BoardWaveService Waves { get; }
124 |
125 | ///
126 | /// Releases board resources.
127 | ///
128 | public static void Release()
129 | {
130 | IsAvailable = false;
131 | Setup.GpioTerminate();
132 | Console.CursorVisible = true;
133 | }
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/ManagedModel/GpioPinInterruptService.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.ManagedModel
2 | {
3 | using NativeEnums;
4 | using NativeMethods;
5 | using NativeTypes;
6 | using System;
7 |
8 | ///
9 | /// Provides Interrupt Service Routine callback services on the GPIO pin.
10 | ///
11 | ///
12 | public sealed class GpioPinInterruptService : GpioPinServiceBase
13 | {
14 | private readonly object SyncLock = new object();
15 | private PiGpioIsrDelegate Callback = null;
16 | private EdgeDetection m_EdgeDetection = EdgeDetection.EitherEdge;
17 | private int m_TimeoutMilliseconds = 0;
18 |
19 | internal GpioPinInterruptService(GpioPin pin)
20 | : base(pin)
21 | {
22 | // placeholder;
23 | }
24 |
25 | ///
26 | /// Gets or sets the edge detection strategy.
27 | ///
28 | /// EdgeDetection cannot be set when callbacks have started.
29 | public EdgeDetection EdgeDetection
30 | {
31 | get
32 | {
33 | lock (SyncLock) return m_EdgeDetection;
34 | }
35 | set
36 | {
37 | ValidateAvailable();
38 |
39 | lock (SyncLock)
40 | {
41 | if (Callback != null)
42 | throw new InvalidOperationException($"Unable to change {nameof(EdgeDetection)} when callback is set.");
43 | m_EdgeDetection = value;
44 | }
45 | }
46 | }
47 |
48 | ///
49 | /// Gets or sets the ISR timeout milliseconds.
50 | /// When no changes are detected for this amount of time,
51 | /// the callback returns with a no level change.
52 | ///
53 | ///
54 | /// The timeout in milliseconds.
55 | ///
56 | public int TimeoutMilliseconds
57 | {
58 | get
59 | {
60 | lock (SyncLock) return m_TimeoutMilliseconds;
61 | }
62 | set
63 | {
64 | ValidateAvailable();
65 |
66 | lock (SyncLock)
67 | {
68 | if (Callback != null)
69 | throw new InvalidOperationException($"Unable to change {nameof(TimeoutMilliseconds)} when callback is set.");
70 |
71 | m_TimeoutMilliseconds = value;
72 | }
73 | }
74 | }
75 |
76 | ///
77 | /// Starts the hardware ISR callbacks.
78 | ///
79 | /// The callback.
80 | /// The edge detection.
81 | /// The timeout milliseconds.
82 | /// callback - Use Stop first.
83 | /// A callback is already registered. Clear the current callback before registering a new one. - callback.
84 | public void Start(PiGpioIsrDelegate callback, EdgeDetection edgeDetection, int timeoutMilliseconds)
85 | {
86 | ValidateAvailable();
87 |
88 | if (callback == null)
89 | throw new ArgumentNullException(nameof(callback), $"The callback cannot be null. Use the '{nameof(Stop)}' method instead.");
90 |
91 | lock (SyncLock)
92 | {
93 | if (Callback != null)
94 | throw new ArgumentException("A callback is already registered. Clear the current callback before registering a new one.", nameof(callback));
95 |
96 | BoardException.ValidateResult(
97 | IO.GpioSetIsrFunc(Pin.PinGpio, edgeDetection, timeoutMilliseconds, callback));
98 |
99 | m_EdgeDetection = edgeDetection;
100 | m_TimeoutMilliseconds = timeoutMilliseconds;
101 | Callback = callback;
102 | }
103 | }
104 |
105 | ///
106 | /// Starts the hardware ISR callbacks.
107 | ///
108 | /// The callback.
109 | /// IsUserGpio is false.
110 | /// callback - ClearAlertCallback.
111 | /// A callback is already registered. Clear the current callback before registering a new one. - callback.
112 | public void Start(PiGpioIsrDelegate callback)
113 | {
114 | Start(callback, EdgeDetection, TimeoutMilliseconds);
115 | }
116 |
117 | ///
118 | /// Stops the hardware ISR callbacks.
119 | ///
120 | public void Stop()
121 | {
122 | ValidateAvailable();
123 |
124 | lock (SyncLock)
125 | {
126 | BoardException.ValidateResult(
127 | IO.GpioSetIsrFunc(Pin.PinGpio, 0, 0, null));
128 | Callback = null;
129 | }
130 | }
131 |
132 | ///
133 | /// Resolves the availability of this service for the associated pin.
134 | ///
135 | ///
136 | /// True when the service is deemed as available.
137 | ///
138 | protected override bool ResolveAvailable() => true;
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # MSTest test Results
33 | [Tt]est[Rr]esult*/
34 | [Bb]uild[Ll]og.*
35 |
36 | # NUNIT
37 | *.VisualState.xml
38 | TestResult.xml
39 |
40 | # Build Results of an ATL Project
41 | [Dd]ebugPS/
42 | [Rr]eleasePS/
43 | dlldata.c
44 |
45 | # .NET Core
46 | project.lock.json
47 | project.fragment.lock.json
48 | artifacts/
49 | **/Properties/launchSettings.json
50 |
51 | *_i.c
52 | *_p.c
53 | *_i.h
54 | *.ilk
55 | *.meta
56 | *.obj
57 | *.pch
58 | *.pdb
59 | *.pgc
60 | *.pgd
61 | *.rsp
62 | *.sbr
63 | *.tlb
64 | *.tli
65 | *.tlh
66 | *.tmp
67 | *.tmp_proj
68 | *.log
69 | *.vspscc
70 | *.vssscc
71 | .builds
72 | *.pidb
73 | *.svclog
74 | *.scc
75 |
76 | # Chutzpah Test files
77 | _Chutzpah*
78 |
79 | # Visual C++ cache files
80 | ipch/
81 | *.aps
82 | *.ncb
83 | *.opendb
84 | *.opensdf
85 | *.sdf
86 | *.cachefile
87 | *.VC.db
88 | *.VC.VC.opendb
89 |
90 | # Visual Studio profiler
91 | *.psess
92 | *.vsp
93 | *.vspx
94 | *.sap
95 |
96 | # TFS 2012 Local Workspace
97 | $tf/
98 |
99 | # Guidance Automation Toolkit
100 | *.gpState
101 |
102 | # ReSharper is a .NET coding add-in
103 | _ReSharper*/
104 | *.[Rr]e[Ss]harper
105 | *.DotSettings.user
106 |
107 | # JustCode is a .NET coding add-in
108 | .JustCode
109 |
110 | # TeamCity is a build add-in
111 | _TeamCity*
112 |
113 | # DotCover is a Code Coverage Tool
114 | *.dotCover
115 |
116 | # Visual Studio code coverage results
117 | *.coverage
118 | *.coveragexml
119 |
120 | # NCrunch
121 | _NCrunch_*
122 | .*crunch*.local.xml
123 | nCrunchTemp_*
124 |
125 | # MightyMoose
126 | *.mm.*
127 | AutoTest.Net/
128 |
129 | # Web workbench (sass)
130 | .sass-cache/
131 |
132 | # Installshield output folder
133 | [Ee]xpress/
134 |
135 | # DocProject is a documentation generator add-in
136 | DocProject/buildhelp/
137 | DocProject/Help/*.HxT
138 | DocProject/Help/*.HxC
139 | DocProject/Help/*.hhc
140 | DocProject/Help/*.hhk
141 | DocProject/Help/*.hhp
142 | DocProject/Help/Html2
143 | DocProject/Help/html
144 |
145 | # Click-Once directory
146 | publish/
147 |
148 | # Publish Web Output
149 | *.[Pp]ublish.xml
150 | *.azurePubxml
151 | # TODO: Comment the next line if you want to checkin your web deploy settings
152 | # but database connection strings (with potential passwords) will be unencrypted
153 | *.pubxml
154 | *.publishproj
155 |
156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
157 | # checkin your Azure Web App publish settings, but sensitive information contained
158 | # in these scripts will be unencrypted
159 | PublishScripts/
160 |
161 | # NuGet Packages
162 | *.nupkg
163 | # The packages folder can be ignored because of Package Restore
164 | **/packages/*
165 | # except build/, which is used as an MSBuild target.
166 | !**/packages/build/
167 | # Uncomment if necessary however generally it will be regenerated when needed
168 | #!**/packages/repositories.config
169 | # NuGet v3's project.json files produces more ignorable files
170 | *.nuget.props
171 | *.nuget.targets
172 |
173 | # Microsoft Azure Build Output
174 | csx/
175 | *.build.csdef
176 |
177 | # Microsoft Azure Emulator
178 | ecf/
179 | rcf/
180 |
181 | # Windows Store app package directories and files
182 | AppPackages/
183 | BundleArtifacts/
184 | Package.StoreAssociation.xml
185 | _pkginfo.txt
186 |
187 | # Visual Studio cache files
188 | # files ending in .cache can be ignored
189 | *.[Cc]ache
190 | # but keep track of directories ending in .cache
191 | !*.[Cc]ache/
192 |
193 | # Others
194 | ClientBin/
195 | ~$*
196 | *~
197 | *.dbmdl
198 | *.dbproj.schemaview
199 | *.jfm
200 | *.pfx
201 | *.publishsettings
202 | orleans.codegen.cs
203 |
204 | # Since there are multiple workflows, uncomment next line to ignore bower_components
205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
206 | #bower_components/
207 |
208 | # RIA/Silverlight projects
209 | Generated_Code/
210 |
211 | # Backup & report files from converting an old project file
212 | # to a newer Visual Studio version. Backup files are not needed,
213 | # because we have git ;-)
214 | _UpgradeReport_Files/
215 | Backup*/
216 | UpgradeLog*.XML
217 | UpgradeLog*.htm
218 |
219 | # SQL Server files
220 | *.mdf
221 | *.ldf
222 | *.ndf
223 |
224 | # Business Intelligence projects
225 | *.rdl.data
226 | *.bim.layout
227 | *.bim_*.settings
228 |
229 | # Microsoft Fakes
230 | FakesAssemblies/
231 |
232 | # GhostDoc plugin setting file
233 | *.GhostDoc.xml
234 |
235 | # Node.js Tools for Visual Studio
236 | .ntvs_analysis.dat
237 | node_modules/
238 |
239 | # Typescript v1 declaration files
240 | typings/
241 |
242 | # Visual Studio 6 build log
243 | *.plg
244 |
245 | # Visual Studio 6 workspace options file
246 | *.opt
247 |
248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
249 | *.vbw
250 |
251 | # Visual Studio LightSwitch build output
252 | **/*.HTMLClient/GeneratedArtifacts
253 | **/*.DesktopClient/GeneratedArtifacts
254 | **/*.DesktopClient/ModelManifest.xml
255 | **/*.Server/GeneratedArtifacts
256 | **/*.Server/ModelManifest.xml
257 | _Pvt_Extensions
258 |
259 | # Paket dependency manager
260 | .paket/paket.exe
261 | paket-files/
262 |
263 | # FAKE - F# Make
264 | .fake/
265 |
266 | # JetBrains Rider
267 | .idea/
268 | *.sln.iml
269 |
270 | # CodeRush
271 | .cr/
272 |
273 | # Python Tools for Visual Studio (PTVS)
274 | __pycache__/
275 | *.pyc
276 |
277 | # Cake - Uncomment if you are using it
278 | # tools/**
279 | # !tools/packages.config
280 |
281 | # Telerik's JustMock configuration file
282 | *.jmconfig
283 |
284 | # BizTalk build output
285 | *.btp.cs
286 | *.btm.cs
287 | *.odx.cs
288 | *.xsd.cs
289 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeMethods/Scripts.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeMethods
2 | {
3 | using NativeEnums;
4 | using System.Runtime.InteropServices;
5 |
6 | ///
7 | /// Provides access to scripting methods of the pigpio library. Scripts are used by the
8 | /// pigpio daemon to execute a set of instructions to speedup GPIO instructions.
9 | /// Unused in the managed model of this library but provided for reference purposes.
10 | ///
11 | public static class Scripts
12 | {
13 | ///
14 | /// This function stores a null terminated script for later execution.
15 | ///
16 | /// See [[http://abyz.me.uk/rpi/pigpio/pigs.html#Scripts]] for details.
17 | ///
18 | /// The function returns a script id if the script is valid,
19 | /// otherwise PI_BAD_SCRIPT.
20 | ///
21 | /// the text of the script.
22 | /// The result code. 0 for success. See the enumeration.
23 | [DllImport(Constants.PiGpioLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "gpioStoreScript")]
24 | public static extern int GpioStoreScript(string script);
25 |
26 | ///
27 | /// This function runs a stored script.
28 | ///
29 | /// The function returns 0 if OK, otherwise PI_BAD_SCRIPT_ID, or
30 | /// PI_TOO_MANY_PARAM.
31 | ///
32 | /// param is an array of up to 10 parameters which may be referenced in
33 | /// the script as p0 to p9.
34 | ///
35 | /// >=0, as returned by .
36 | /// 0-10, the number of parameters.
37 | /// an array of parameters.
38 | /// The result code. 0 for success. See the enumeration.
39 | [DllImport(Constants.PiGpioLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "gpioRunScript")]
40 | public static extern int GpioRunScript(uint script_id, uint numPar, [In, MarshalAs(UnmanagedType.LPArray)] uint[] param);
41 |
42 | ///
43 | /// This function sets the parameters of a script. The script may or
44 | /// may not be running. The first numPar parameters of the script are
45 | /// overwritten with the new values.
46 | ///
47 | /// The function returns 0 if OK, otherwise PI_BAD_SCRIPT_ID, or
48 | /// PI_TOO_MANY_PARAM.
49 | ///
50 | /// param is an array of up to 10 parameters which may be referenced in
51 | /// the script as p0 to p9.
52 | ///
53 | /// >=0, as returned by .
54 | /// 0-10, the number of parameters.
55 | /// an array of parameters.
56 | /// The result code. 0 for success. See the enumeration.
57 | [DllImport(Constants.PiGpioLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "gpioUpdateScript")]
58 | public static extern int GpioUpdateScript(uint script_id, uint numPar, [In, MarshalAs(UnmanagedType.LPArray)] uint[] param);
59 |
60 | ///
61 | /// This function returns the run status of a stored script as well as
62 | /// the current values of parameters 0 to 9.
63 | ///
64 | /// The function returns greater than or equal to 0 if OK,
65 | /// otherwise PI_BAD_SCRIPT_ID.
66 | ///
67 | /// The run status may be
68 | ///
69 | /// The current value of script parameters 0 to 9 are returned in param.
70 | ///
71 | ///
72 | /// PI_SCRIPT_INITING
73 | /// PI_SCRIPT_HALTED
74 | /// PI_SCRIPT_RUNNING
75 | /// PI_SCRIPT_WAITING
76 | /// PI_SCRIPT_FAILED.
77 | ///
78 | /// >=0, as returned by .
79 | /// an array to hold the returned 10 parameters.
80 | /// The result code. 0 for success. See the enumeration.
81 | [DllImport(Constants.PiGpioLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "gpioScriptStatus")]
82 | public static extern int GpioScriptStatus(uint script_id, [In, MarshalAs(UnmanagedType.LPArray)] uint[] param);
83 |
84 | ///
85 | /// This function stops a running script.
86 | ///
87 | /// The function returns 0 if OK, otherwise PI_BAD_SCRIPT_ID.
88 | ///
89 | /// >=0, as returned by .
90 | /// The result code. 0 for success. See the enumeration.
91 | [DllImport(Constants.PiGpioLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "gpioStopScript")]
92 | public static extern int GpioStopScript(uint script_id);
93 |
94 | ///
95 | /// This function deletes a stored script.
96 | ///
97 | /// The function returns 0 if OK, otherwise PI_BAD_SCRIPT_ID.
98 | ///
99 | /// >=0, as returned by .
100 | /// The result code. 0 for success. See the enumeration.
101 | [DllImport(Constants.PiGpioLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "gpioDeleteScript")]
102 | public static extern int GpioDeleteScript(uint script_id);
103 |
104 | ///
105 | /// Used to print a readable version of a script to stderr.
106 | ///
107 | /// Not intended for general use.
108 | ///
109 | /// >=0, a script_id returned by .
110 | [DllImport(Constants.PiGpioLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "rawDumpScript")]
111 | public static extern void RawDumpScript(uint scriptId);
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeTypes/Delegates.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeTypes
2 | {
3 | using NativeEnums;
4 | using System;
5 | using System.Runtime.InteropServices;
6 |
7 | ///
8 | /// Defines a signature for a pthread worker.
9 | /// Use built-in CLR instead.
10 | ///
11 | /// The user data.
12 | public delegate void PiGpioThreadDelegate(UIntPtr userData);
13 |
14 | ///
15 | /// Defines a signature for alert callbacks. Conatins the pin number, a level change and a microseconds
16 | /// timestamp. The timestamp wraps around every ~72 minutes.
17 | /// Unlike Interrupts, alerts are generated by continuously sampling the value of the pin.
18 | ///
19 | /// The user gpio.
20 | /// The level change.
21 | /// The microseconds timestamp.
22 | public delegate void PiGpioAlertDelegate(UserGpio userGpio, LevelChange levelChange, uint timeMicrosecs);
23 |
24 | ///
25 | /// Defines a signature for alert callbacks. Conatins the pin number, a level change and a microseconds
26 | /// timestamp. The timestamp wraps around every ~72 minutes.
27 | /// Unlike Interrupts, alerts are generated by continuously sampling the value of the pin.
28 | ///
29 | /// The user gpio.
30 | /// The level change.
31 | /// The time microsecs.
32 | /// The user data.
33 | public delegate void PiGpioAlertExDelegate(UserGpio userGpio, LevelChange levelChange, uint timeMicrosecs, UIntPtr userData);
34 |
35 | ///
36 | /// Defines a signature for ISR callbacks. Conatins the pin number, a level change and a microseconds
37 | /// timestamp. The timestamp wraps around every ~72 minutes.
38 | /// Unlike alerts, interrupts are generated with level changes. Make sure you hookup pull-down/pull-up resitors
39 | /// for interrupts to work as they depend on current flowing through the pin in order to fire consistently.
40 | ///
41 | /// The gpio.
42 | /// The level.
43 | /// The time microsecs.
44 | public delegate void PiGpioIsrDelegate(SystemGpio gpio, LevelChange level, uint timeMicrosecs);
45 |
46 | ///
47 | /// Defines a signature for ISR callbacks. Conatins the pin number, a level change and a microseconds
48 | /// timestamp. The timestamp wraps around every ~72 minutes.
49 | /// Unlike alerts, interrupts are generated with level changes. Make sure you hookup pull-down/pull-up resitors
50 | /// for interrupts to work as they depend on current flowing through the pin in order to fire consistently.
51 | ///
52 | /// The gpio.
53 | /// The level.
54 | /// The time microsecs.
55 | /// The user data.
56 | public delegate void PiGpioIsrExDelegate(SystemGpio gpio, LevelChange level, uint timeMicrosecs, UIntPtr userData);
57 |
58 | ///
59 | /// Defines a callback for a pigpio library timer
60 | /// Use built-in CLR instead.
61 | ///
62 | public delegate void PiGpioTimerDelegate();
63 |
64 | ///
65 | /// Defines a callback for a pigpio library timer
66 | /// Use built-in CLR instead.
67 | ///
68 | /// The user data.
69 | public delegate void PiGpioTimerExDelegate(UIntPtr userData);
70 |
71 | ///
72 | /// Callback for when an pigpio library event firing. This represents an event model internal
73 | /// to the pigpio library. Use the buil-in CLR constructs instead.
74 | ///
75 | /// The event identifier.
76 | /// The time microsecs.
77 | public delegate void PiGpioEventDelegate(int eventId, uint timeMicrosecs);
78 |
79 | ///
80 | /// Callback for when an pigpio library event firing. This represents an event model internal
81 | /// to the pigpio library. Use the buil-in CLR constructs instead.
82 | ///
83 | /// The event identifier.
84 | /// The tick.
85 | /// The user data.
86 | public delegate void PiGpioEventExDelegate(int eventId, uint tick, UIntPtr userData);
87 |
88 | ///
89 | /// Defines a callback to be executed when the OS sends a signal.
90 | ///
91 | /// The OS signal number.
92 | public delegate void PiGpioSignalDelegate(int signalNumber);
93 |
94 | ///
95 | /// Defines a callback to be executed when the OS sends a signal.
96 | ///
97 | /// The OS signal number.
98 | /// The user data.
99 | public delegate void PiGpioSignalExDelegate(int signalNumber, UIntPtr userData);
100 |
101 | ///
102 | /// Bulk pin sampling delegate. Not used in the managed model of this library.
103 | ///
104 | /// The samples.
105 | /// The number samples.
106 | public delegate void PiGpioGetSamplesDelegate([Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] GpioSample[] samples, int numSamples);
107 |
108 | ///
109 | /// Bulk pin sampling delegate. Not used in the managed model of this library.
110 | ///
111 | /// The samples.
112 | /// The number samples.
113 | /// The user data.
114 | public delegate void PiGpioGetSamplesExDelegate([Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] GpioSample[] samples, int numSamples, UIntPtr userData);
115 | }
116 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeMethods/Serial.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeMethods
2 | {
3 | using NativeEnums;
4 | using System;
5 | using System.Runtime.InteropServices;
6 |
7 | ///
8 | /// Exposes methods to read from a serial transmission using bit-banging (software-based UART).
9 | /// Writing requires the use of the method.
10 | ///
11 | public static class Serial
12 | {
13 | ///
14 | /// This function opens a GPIO for bit bang reading of serial data.
15 | ///
16 | /// The serial data is returned in a cyclic buffer and is read using
17 | /// .
18 | ///
19 | /// It is the caller's responsibility to read data from the cyclic buffer
20 | /// in a timely fashion.
21 | ///
22 | /// 0-31.
23 | /// 50-250000.
24 | /// 1-32.
25 | /// Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_BAD_WAVE_BAUD, PI_BAD_DATABITS, or PI_GPIO_IN_USE.
26 | [DllImport(Constants.PiGpioLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "gpioSerialReadOpen")]
27 | public static extern ResultCode GpioSerialReadOpen(UserGpio userGpio, uint baudRate, uint dataBits);
28 |
29 | ///
30 | /// This function configures the level logic for bit bang serial reads.
31 | ///
32 | /// Use PI_BB_SER_INVERT to invert the serial logic and PI_BB_SER_NORMAL for
33 | /// normal logic. Default is PI_BB_SER_NORMAL.
34 | ///
35 | /// The GPIO must be opened for bit bang reading of serial data using
36 | /// prior to calling this function.
37 | ///
38 | /// 0-31.
39 | /// 0-1.
40 | /// Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_GPIO_IN_USE, PI_NOT_SERIAL_GPIO, or PI_BAD_SER_INVERT.
41 | public static ResultCode GpioSerialReadInvert(UserGpio userGpio, bool invert)
42 | {
43 | return GpioSerialReadInvertUnmanaged(userGpio, invert ? DigitalValue.True : DigitalValue.False);
44 | }
45 |
46 | ///
47 | /// Wrapper for the native .
48 | ///
49 | /// The user gpio.
50 | /// The buffer.
51 | /// Length of the read.
52 | /// The amount of bytes read.
53 | public static int GpioSerialRead(UserGpio userGpio, byte[] buffer, int readLength)
54 | {
55 | var result = BoardException.ValidateResult(GpioSerialReadUnmanaged(userGpio, buffer, (uint)readLength));
56 | return result;
57 | }
58 |
59 | ///
60 | /// Wrapper for the native .
61 | ///
62 | /// The user gpio.
63 | /// Length of the read.
64 | /// The array containing the bytes that were read.
65 | public static byte[] GpioSerialRead(UserGpio userGpio, int readLength)
66 | {
67 | var buffer = new byte[readLength];
68 | var result = BoardException.ValidateResult(GpioSerialReadUnmanaged(userGpio, buffer, (uint)readLength));
69 |
70 | if (result == buffer.Length)
71 | return buffer;
72 |
73 | var outputBuffer = new byte[result];
74 | Buffer.BlockCopy(buffer, 0, outputBuffer, 0, result);
75 | return outputBuffer;
76 | }
77 |
78 | ///
79 | /// This function closes a GPIO for bit bang reading of serial data.
80 | ///
81 | ///
82 | /// 0-31, previously opened with .
83 | /// Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_NOT_SERIAL_GPIO.
84 | [DllImport(Constants.PiGpioLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "gpioSerialReadClose")]
85 | public static extern ResultCode GpioSerialReadClose(UserGpio userGpio);
86 |
87 | #region Unmanaged Methods
88 |
89 | ///
90 | /// This function copies up to bufSize bytes of data read from the
91 | /// bit bang serial cyclic buffer to the buffer starting at buf.
92 | ///
93 | /// The bytes returned for each character depend upon the number of
94 | /// data bits data bits specified in the command.
95 | ///
96 | /// For data bits 1-8 there will be one byte per character.
97 | /// For data bits 9-16 there will be two bytes per character.
98 | /// For data bits 17-32 there will be four bytes per character.
99 | ///
100 | /// 0-31, previously opened with .
101 | /// an array to receive the read bytes.
102 | /// >=0.
103 | /// Returns the number of bytes copied if OK, otherwise PI_BAD_USER_GPIO or PI_NOT_SERIAL_GPIO.
104 | [DllImport(Constants.PiGpioLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "gpioSerialRead")]
105 | private static extern int GpioSerialReadUnmanaged(UserGpio userGpio, [In, MarshalAs(UnmanagedType.LPArray)] byte[] buffer, uint bufferSize);
106 |
107 | ///
108 | /// This function configures the level logic for bit bang serial reads.
109 | ///
110 | /// Use PI_BB_SER_INVERT to invert the serial logic and PI_BB_SER_NORMAL for
111 | /// normal logic. Default is PI_BB_SER_NORMAL.
112 | ///
113 | /// The GPIO must be opened for bit bang reading of serial data using
114 | /// prior to calling this function.
115 | ///
116 | /// 0-31.
117 | /// 0-1.
118 | /// Returns 0 if OK, otherwise PI_BAD_USER_GPIO, PI_GPIO_IN_USE, PI_NOT_SERIAL_GPIO, or PI_BAD_SER_INVERT.
119 | [DllImport(Constants.PiGpioLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "gpioSerialReadInvert")]
120 | private static extern ResultCode GpioSerialReadInvertUnmanaged(UserGpio userGpio, DigitalValue invert);
121 |
122 | #endregion
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/NativeMethods/Uart.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.NativeMethods
2 | {
3 | using NativeEnums;
4 | using System;
5 | using System.Runtime.InteropServices;
6 |
7 | ///
8 | /// Provides access to hardware based UART (Serial Port).
9 | ///
10 | public static class Uart
11 | {
12 | ///
13 | /// This function opens a serial device at a specified baud rate
14 | /// and with specified flags. The device name must start with
15 | /// /dev/tty or /dev/serial.
16 | ///
17 | /// The baud rate must be one of 50, 75, 110, 134, 150,
18 | /// 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200,
19 | /// 38400, 57600, 115200, or 230400.
20 | ///
21 | /// No flags are currently defined. This parameter should be set to zero.
22 | ///
23 | /// the serial device to open.
24 | /// the baud rate in bits per second, see below.
25 | /// Returns a handle (>=0) if OK, otherwise PI_NO_HANDLE, or PI_SER_OPEN_FAILED.
26 | public static UIntPtr SerOpen(string sertty, UartRate baud)
27 | {
28 | var result = BoardException.ValidateResult(SerOpenUnmanaged(sertty, (uint)baud, 0));
29 | return new UIntPtr((uint)result);
30 | }
31 |
32 | ///
33 | /// This function closes the serial device associated with handle.
34 | ///
35 | ///
36 | /// >=0, as returned by a call to .
37 | /// Returns 0 if OK, otherwise PI_BAD_HANDLE.
38 | [DllImport(Constants.PiGpioLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "serClose")]
39 | public static extern ResultCode SerClose(UIntPtr handle);
40 |
41 | ///
42 | /// This function reads a byte from the serial port associated with handle.
43 | ///
44 | /// If no data is ready PI_SER_READ_NO_DATA is returned.
45 | ///
46 | /// >=0, as returned by a call to .
47 | /// Returns the read byte (>=0) if OK, otherwise PI_BAD_HANDLE, PI_SER_READ_NO_DATA, or PI_SER_READ_FAILED.
48 | [DllImport(Constants.PiGpioLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "serReadByte")]
49 | public static extern int SerReadByte(UIntPtr handle);
50 |
51 | ///
52 | /// This function writes bVal to the serial port associated with handle.
53 | /// PI_SER_WRITE_FAILED.
54 | ///
55 | /// >=0, as returned by a call to .
56 | /// The byte value.
57 | ///
58 | /// Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or PI_SER_WRITE_FAILED.
59 | ///
60 | [DllImport(Constants.PiGpioLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "serWriteByte")]
61 | public static extern ResultCode SerWriteByte(UIntPtr handle, uint byteValue);
62 |
63 | ///
64 | /// This function reads up count bytes from the the serial port
65 | /// associated with handle and writes them to buf.
66 | ///
67 | /// If no data is ready zero is returned.
68 | ///
69 | /// >=0, as returned by a call to .
70 | /// an array to receive the read data.
71 | /// the maximum number of bytes to read.
72 | /// Returns the number of bytes read (>0=) if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or PI_SER_READ_NO_DATA.
73 | [DllImport(Constants.PiGpioLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "serRead")]
74 | public static extern int SerRead(UIntPtr handle, [In, MarshalAs(UnmanagedType.LPArray)] byte[] buffer, uint count);
75 |
76 | ///
77 | /// This function writes count bytes from buf to the the serial port
78 | /// associated with handle.
79 | ///
80 | /// PI_SER_WRITE_FAILED.
81 | ///
82 | /// >=0, as returned by a call to .
83 | /// the array of bytes to write.
84 | /// the number of bytes to write.
85 | /// Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or PI_SER_WRITE_FAILED.
86 | [DllImport(Constants.PiGpioLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "serWrite")]
87 | public static extern ResultCode SerWrite(UIntPtr handle, [In, MarshalAs(UnmanagedType.LPArray)] byte[] buffer, uint count);
88 |
89 | ///
90 | /// This function returns the number of bytes available
91 | /// to be read from the device associated with handle.
92 | ///
93 | /// otherwise PI_BAD_HANDLE.
94 | ///
95 | /// >=0, as returned by a call to .
96 | /// Returns the number of bytes of data available (>=0) if OK, otherwise PI_BAD_HANDLE.
97 | [DllImport(Constants.PiGpioLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "serDataAvailable")]
98 | public static extern int SerDataAvailable(UIntPtr handle);
99 |
100 | #region Unmanaged Methods
101 |
102 | ///
103 | /// This function opens a serial device at a specified baud rate
104 | /// and with specified flags. The device name must start with
105 | /// /dev/tty or /dev/serial.
106 | ///
107 | /// The baud rate must be one of 50, 75, 110, 134, 150,
108 | /// 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200,
109 | /// 38400, 57600, 115200, or 230400.
110 | ///
111 | /// No flags are currently defined. This parameter should be set to zero.
112 | ///
113 | /// the serial device to open.
114 | /// the baud rate in bits per second, see below.
115 | /// 0.
116 | /// Returns a handle (>=0) if OK, otherwise PI_NO_HANDLE, or PI_SER_OPEN_FAILED.
117 | [DllImport(Constants.PiGpioLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "serOpen")]
118 | private static extern int SerOpenUnmanaged(string sertty, uint baud, uint serFlags);
119 |
120 | #endregion
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/ManagedModel/BoardTimingService.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.ManagedModel
2 | {
3 | using NativeEnums;
4 | using NativeMethods;
5 | using System;
6 | using System.Threading;
7 | using RaspberryIO.Abstractions;
8 |
9 | ///
10 | /// Provides timing, date and delay functions.
11 | /// Also provides access to registered timers.
12 | ///
13 | public class BoardTimingService : ITiming
14 | {
15 | private const long SecondsToMicrosFactor = 1000000L;
16 | private const long MillisToMicrosFactor = 1000L;
17 |
18 | ///
19 | /// Initializes a new instance of the class.
20 | ///
21 | internal BoardTimingService()
22 | {
23 | Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
24 | }
25 |
26 | ///
27 | /// Gets the Linux Epoch (Jan 1, 1970) in UTC.
28 | ///
29 | public DateTime Epoch { get; }
30 |
31 | ///
32 | /// Gets the timestamp tick.
33 | /// Useful to calculate offsets in Alerts or ISR callbacks.
34 | ///
35 | public uint TimestampTick => Utilities.GpioTick();
36 |
37 | ///
38 | /// Gets the number of seconds elapsed since the Epoc (Jan 1, 1970).
39 | ///
40 | public double TimestampSeconds => Utilities.TimeTime();
41 |
42 | ///
43 | /// Gets a timestamp since Jan 1, 1970 in microseconds.
44 | ///
45 | public long TimestampMicroseconds => EllapsedMicroseconds(TimeType.Absolute);
46 |
47 | ///
48 | /// Gets the elapsed time since the Epoc (Jan 1, 1970).
49 | ///
50 | public TimeSpan Timestamp => TimeSpan.FromSeconds(TimestampSeconds);
51 |
52 | ///
53 | public uint Milliseconds => Convert.ToUInt32(EllapsedMicroseconds(TimeType.Relative) / MillisToMicrosFactor);
54 |
55 | ///
56 | public uint Microseconds => Convert.ToUInt32(EllapsedMicroseconds(TimeType.Relative));
57 |
58 | ///
59 | /// Sleeps for the given amount of microseconds.
60 | /// Waits of 100 microseconds or less use busy waits.
61 | /// Returns the real elapsed microseconds.
62 | ///
63 | /// The micro seconds.
64 | /// Returns the real elapsed microseconds.
65 | public long SleepMicros(long microsecs)
66 | {
67 | if (microsecs <= 0)
68 | return 0L;
69 |
70 | if (microsecs <= uint.MaxValue)
71 | return Threads.GpioDelay(Convert.ToUInt32(microsecs));
72 |
73 | var componentSeconds = microsecs / SecondsToMicrosFactor;
74 | var componentMicrosecs = microsecs % SecondsToMicrosFactor;
75 |
76 | if (componentSeconds <= int.MaxValue && componentMicrosecs <= int.MaxValue)
77 | {
78 | BoardException.ValidateResult(
79 | Threads.GpioSleep(
80 | TimeType.Relative,
81 | Convert.ToInt32(componentSeconds),
82 | Convert.ToInt32(componentMicrosecs)));
83 |
84 | return microsecs;
85 | }
86 |
87 | Threads.TimeSleep(componentSeconds + (componentMicrosecs / (double)SecondsToMicrosFactor));
88 | return microsecs;
89 | }
90 |
91 | ///
92 | /// Sleeps for the specified milliseconds.
93 | ///
94 | /// The milliseconds to sleep for.
95 | public void Sleep(long millis) =>
96 | SleepMicros(millis * MillisToMicrosFactor);
97 |
98 | ///
99 | /// Sleeps for the specified time span.
100 | ///
101 | /// The time span to sleep for.
102 | public void Sleep(TimeSpan timeSpan)
103 | {
104 | var micros = timeSpan.Ticks / (TimeSpan.TicksPerMillisecond / 1000);
105 |
106 | if (micros > uint.MaxValue)
107 | {
108 | throw new ArgumentOutOfRangeException(nameof(timeSpan), "Sleep length is too long.");
109 | }
110 |
111 | SleepMicroseconds((uint)micros);
112 | }
113 |
114 | ///
115 | /// Shortcut method to start a thread.
116 | /// It runs the thread automatically.
117 | ///
118 | /// The do work.
119 | /// Name of the thread.
120 | ///
121 | /// A reference to the thread object.
122 | ///
123 | public Thread StartThread(Action doWork, string threadName)
124 | {
125 | var thread = new Thread(() => { doWork?.Invoke(); })
126 | {
127 | IsBackground = true,
128 | };
129 |
130 | if (string.IsNullOrWhiteSpace(threadName) == false)
131 | thread.Name = threadName;
132 |
133 | thread.Start();
134 | return thread;
135 | }
136 |
137 | ///
138 | /// Shortcut method to start a thread.
139 | /// It runs the thread automatically.
140 | ///
141 | /// The do work.
142 | ///
143 | /// A reference to the thread object.
144 | ///
145 | public Thread StartThread(Action doWork) => StartThread(doWork, null);
146 |
147 | ///
148 | /// Starts a timer that executes a block of code with the given period.
149 | ///
150 | /// The period in milliseconds.
151 | /// The callback.
152 | /// A reference to a timer.
153 | public Timer StartTimer(int periodMilliseconds, Action callback)
154 | {
155 | return new Timer(s => { callback?.Invoke(); }, this, 0, periodMilliseconds);
156 | }
157 |
158 | ///
159 | public void SleepMilliseconds(uint millis) =>
160 | Sleep(millis);
161 |
162 | ///
163 | public void SleepMicroseconds(uint micros) =>
164 | SleepMicros(micros);
165 |
166 | private long EllapsedMicroseconds(TimeType type)
167 | {
168 | BoardException.ValidateResult(
169 | Utilities.GpioTime(type, out var seconds, out var microseconds));
170 |
171 | return (seconds * SecondsToMicrosFactor) + microseconds;
172 | }
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio.Workbench/Runners/DhtSensor.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.Workbench.Runners
2 | {
3 | using ManagedModel;
4 | using NativeEnums;
5 | using Swan.Logging;
6 | using Swan.Threading;
7 | using System;
8 | using System.Collections;
9 | using System.Collections.Generic;
10 | using System.Text;
11 | using System.Threading;
12 |
13 | internal class DhtSensor : RunnerBase
14 | {
15 | private readonly List> _pulses = new List>(1024);
16 | private uint _lastTick;
17 | private GpioPin _pin;
18 |
19 | public DhtSensor(bool isEnabled)
20 | : base(isEnabled) { }
21 |
22 | protected override void OnSetup()
23 | {
24 | _pin = Board.Pins[27];
25 | _pin.PullMode = GpioPullMode.Off;
26 | _pin.Alerts.TimeoutMilliseconds = 200;
27 | _lastTick = Board.Timing.TimestampTick;
28 | _pin.Alerts.Start((pin, level, tick) =>
29 | {
30 | // The DHT22 produces a total of 83 interrupts on the line which are interpreted as 5 bytes of data -
31 | // two bytes containing the humidity reading, two bytes containing the temperature reading, and a hash
32 | // which is the sum of the other four bytes.
33 | // The sensor starts by sending two preliminary signals, each ~80 us in length - it first pulls the line LOW,
34 | // then releases it back to HIGH.
35 | if (level == LevelChange.NoChange)
36 | return;
37 |
38 | var elapsed = tick - _lastTick;
39 | var value = level != LevelChange.LowToHigh; // THE DHT signal is active-low
40 | var pulse = new Tuple(value, elapsed);
41 | _pulses.Add(pulse);
42 | _lastTick = tick;
43 | });
44 | }
45 |
46 | protected override void DoBackgroundWork(CancellationToken ct)
47 | {
48 | while (ct.IsCancellationRequested == false)
49 | {
50 | // The DHT22 must be manually triggered with a specific signal as follows:
51 | // 1. Line is initially kept HIGH (it is active when it is LOW). 250 ms.
52 | _pin.Value = true;
53 | Board.Timing.Sleep(250);
54 |
55 | // 2. Pull the line LOW for at least 1 ms.In this driver, the triggering signal is set to 10 ms
56 | _pin.Value = false;
57 | Board.Timing.Sleep(18);
58 |
59 | // 3. Stop pulling LOW, allowing the line to return to HIGH and wait between 20 and 40 us.
60 | _pin.Value = true;
61 |
62 | // Board.Timing.SleepMicros(30);
63 | // time to read. The alrets should fire ok now.
64 | _pin.Direction = PinDirection.Input;
65 |
66 | // Reading the data
67 | _lastTick = Board.Timing.TimestampTick;
68 |
69 | // Wait for the data to be read.
70 | Board.Timing.Sleep(1000);
71 |
72 | DebugPulses(_pulses);
73 | var bits = DecodeBits(_pulses);
74 | if (bits.Count >= 40)
75 | {
76 | DebugBits(bits);
77 | var bitArray = new BitArray(bits.ToArray());
78 | var bytes = new byte[bits.Count / 8];
79 | bitArray.CopyTo(bytes, 0);
80 |
81 | $"Bytes Received: {BitConverter.ToString(bytes).Replace("-", " ")}".Info(Name);
82 |
83 | var humidity = BitConverter.ToUInt16(bytes, 0);
84 | var temperature = BitConverter.ToUInt16(bytes, 2);
85 | var checksum = (byte)(bytes[0] + bytes[1] + bytes[2] + bytes[3]);
86 | $"Read Results - Humidity: {humidity / 10d:0.0} % | Temp: {temperature / 10d: 0.0} C | Computed CS: {checksum:X} vs RX: {bytes[4]:X}".Info(Name);
87 | }
88 |
89 | _pulses.Clear();
90 |
91 | // Wait 3 seconds for the next read.
92 | var startSleep = Board.Timing.TimestampSeconds;
93 | while (Board.Timing.TimestampSeconds - startSleep < 3.0d)
94 | {
95 | if (ct.IsCancellationRequested)
96 | break;
97 |
98 | Board.Timing.Sleep(50);
99 | }
100 | }
101 | }
102 |
103 | protected override void Cleanup()
104 | {
105 | // TODO: Stopping the alerts for some reason hangs the thread...
106 | _pin.Alerts.Stop();
107 | Board.Timing.Sleep(500);
108 | }
109 |
110 | private static List DecodeBits(IReadOnlyList> pulses)
111 | {
112 | // For each bit, there are two signals - one preparatory (50 us LOW) and one containing the actual bit value.
113 | // The bit value is signalled by a HIGH signal, the length of the signal determines whether it is '0' or '1' - a '0'
114 | // is about 28 us and a '1' is about 70 us.
115 | if (pulses.Count < 82)
116 | return new List(0);
117 |
118 | var startPulseIndex = pulses.Count - 80 - 1;
119 | var dataBits = new List(5 * 8); // 40 bit is 8 bytes
120 |
121 | for (var pulseIndex = startPulseIndex; pulseIndex < pulses.Count; pulseIndex += 2)
122 | {
123 | var p0 = pulses[pulseIndex + 0];
124 | var p1 = pulses[pulseIndex + 1];
125 | dataBits.Add(p1.Item2 > 50);
126 | if (dataBits.Count >= 40)
127 | break;
128 | }
129 |
130 | // dataBits.Reverse();
131 | return dataBits;
132 | }
133 |
134 | private void DebugPulses(IReadOnlyList> pulses)
135 | {
136 | var builder = new StringBuilder();
137 |
138 | for (var i = 0; i < pulses.Count; i++)
139 | {
140 | var p = pulses[i];
141 | builder.Append($"| {(p.Item1 ? "H" : "L")}: {p.Item2,12} ");
142 | if ((i + 1) % 4 == 0)
143 | builder.AppendLine("|");
144 | }
145 |
146 | $"Pulses Received: {pulses.Count}\r\n{builder}".Debug(Name);
147 | }
148 |
149 | private void DebugBits(IReadOnlyList bits)
150 | {
151 | var builder = new StringBuilder();
152 |
153 | for (var i = 0; i < bits.Count; i++)
154 | {
155 | builder.Append(bits[i] ? "1" : "0");
156 | if ((i + 1) % 4 == 0)
157 | builder.Append(" ");
158 | }
159 |
160 | $"Bits: {bits.Count}\r\n{builder}".Debug(Name);
161 | }
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/ManagedModel/GpioPin.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.ManagedModel
2 | {
3 | using NativeEnums;
4 | using NativeMethods;
5 | using System;
6 |
7 | ///
8 | /// A class representing a GPIO port (pin).
9 | ///
10 | public sealed class GpioPin
11 | {
12 | private GpioPullMode m_PullMode;
13 |
14 | ///
15 | /// Initializes a new instance of the class.
16 | ///
17 | /// The gpio.
18 | internal GpioPin(SystemGpio gpio)
19 | {
20 | PinGpio = gpio;
21 | PinNumber = (int)gpio;
22 | IsUserGpio = gpio.GetIsUserGpio(Board.BoardType);
23 | PadId = Constants.GetPad(PinGpio);
24 | m_PullMode = Constants.GetDefaultPullMode(PinGpio);
25 |
26 | // Instantiate the pin services
27 | Alerts = new GpioPinAlertService(this);
28 | Interrupts = new GpioPinInterruptService(this);
29 | Servo = new GpioPinServoService(this);
30 | SoftPwm = new GpioPinSoftPwmService(this);
31 | Clock = new GpioPinClockService(this);
32 | Pwm = new GpioPinPwmService(this);
33 | }
34 |
35 | ///
36 | /// Gets the BCM pin identifier.
37 | ///
38 | public int PinNumber { get; }
39 |
40 | ///
41 | /// Gets the pin number as a system GPIO Identifier.
42 | ///
43 | public SystemGpio PinGpio { get; }
44 |
45 | ///
46 | /// Gets a value indicating whether this pin is a user gpio (0 to 31)
47 | /// and also available on the current board type.
48 | ///
49 | public bool IsUserGpio { get; }
50 |
51 | ///
52 | /// Gets the electrical pad this pin belongs to.
53 | ///
54 | public GpioPadId PadId { get; }
55 |
56 | ///
57 | /// Gets or sets the resistor pull mode in input mode.
58 | /// You typically will need to set this to pull-up mode
59 | /// for most sensors to perform reliable reads.
60 | ///
61 | public GpioPullMode PullMode
62 | {
63 | get => m_PullMode;
64 | set
65 | {
66 | BoardException.ValidateResult(IO.GpioSetPullUpDown(PinGpio, value));
67 | m_PullMode = value;
68 | }
69 | }
70 |
71 | ///
72 | /// Gets or sets the direction of the pin.
73 | ///
74 | ///
75 | /// The direction.
76 | ///
77 | /// Unable to set the pin mode to an alternative function.
78 | public PinDirection Direction
79 | {
80 | get
81 | {
82 | var result = IO.GpioGetMode(PinGpio);
83 | if (result == PinMode.Input || result == PinMode.Output)
84 | return (PinDirection)result;
85 |
86 | return PinDirection.Alternative;
87 | }
88 | set
89 | {
90 | if (value != PinDirection.Input && value != PinDirection.Output)
91 | throw new InvalidOperationException("Unable to set the pin mode to an alternative function.");
92 |
93 | BoardException.ValidateResult(
94 | IO.GpioSetMode(PinGpio, (PinMode)value));
95 | }
96 | }
97 |
98 | ///
99 | /// Gets the current pin mode.
100 | ///
101 | public PinMode Mode => IO.GpioGetMode(PinGpio);
102 |
103 | ///
104 | /// Gets or sets the digital value of the pin.
105 | /// This call actively reads or writes the pin.
106 | ///
107 | public bool Value
108 | {
109 | get => IO.GpioRead(PinGpio);
110 | set => BoardException.ValidateResult(IO.GpioWrite(PinGpio, value));
111 | }
112 |
113 | ///
114 | /// Provides GPIO change alert services.
115 | /// This provides more sophisticated notification settings
116 | /// but it is based on sampling.
117 | ///
118 | public GpioPinAlertService Alerts { get; }
119 |
120 | ///
121 | /// Provides GPIO Interrupt Service Routine services.
122 | /// This is hardware-based input-only notifications.
123 | ///
124 | public GpioPinInterruptService Interrupts { get; }
125 |
126 | ///
127 | /// Gets the servo pin service.
128 | /// This is a standard 50Hz PWM servo that operates
129 | /// in pulse widths between 500 and 2500 microseconds.
130 | /// Use the PWM service instead if you wish further flexibility.
131 | ///
132 | public GpioPinServoService Servo { get; }
133 |
134 | ///
135 | /// Provides a sfotware based PWM pulse generator.
136 | /// This and the servo functionality use the DMA and PWM or PCM peripherals
137 | /// to control and schedule the pulse lengths and dutycycles. Using hardware based
138 | /// PWM is preferred.
139 | ///
140 | public GpioPinSoftPwmService SoftPwm { get; }
141 |
142 | ///
143 | /// Gets a hardware-based clock service. A clock channel spans multiple
144 | /// pins and therefore, clock frequency is not necessarily a per-pin setting.
145 | ///
146 | public GpioPinClockService Clock { get; }
147 |
148 | ///
149 | /// Gets the hardware-based PWM services associated to the pin.
150 | /// Hardware PWM groups several pins by their PWM channel.
151 | ///
152 | public GpioPinPwmService Pwm { get; }
153 |
154 | ///
155 | /// Pulsates the pin for the specified micro seconds.
156 | /// The value is the start value of the pulse.
157 | ///
158 | /// The micro secs.
159 | /// if set to true [value].
160 | public void Pulsate(int microSecs, bool value)
161 | {
162 | BoardException.ValidateResult(
163 | IO.GpioTrigger((UserGpio)PinNumber, Convert.ToUInt32(microSecs), value));
164 | }
165 |
166 | ///
167 | /// The fastest way to read from the pin.
168 | /// No error checking is performed.
169 | ///
170 | /// Returns a 0 or a 1 for success. A negative number for error.
171 | public int Read() => IO.GpioReadUnmanaged(PinGpio);
172 |
173 | ///
174 | /// The fastest way to write to the pin.
175 | /// Anything non-zero is a high. No error checking is performed.
176 | ///
177 | /// The value.
178 | /// The result code. 0 (OK) for success.
179 | public ResultCode Write(int value) => IO.GpioWriteUnmanaged(PinGpio, (DigitalValue)(value == 0 ? 0 : 1));
180 | }
181 | }
182 |
--------------------------------------------------------------------------------
/Unosquare.PiGpio/ManagedModel/GpioBank.cs:
--------------------------------------------------------------------------------
1 | namespace Unosquare.PiGpio.ManagedModel
2 | {
3 | using NativeEnums;
4 | using NativeMethods;
5 | using System;
6 | using System.Collections;
7 | using System.Linq;
8 | using System.Text;
9 |
10 | ///
11 | /// Provides access to bulk GPIO read and write operations.
12 | ///
13 | public sealed class GpioBank
14 | {
15 | private readonly SetClearBitsDelegate _setBitsCallback;
16 | private readonly SetClearBitsDelegate _clearBitsCallback;
17 | private readonly ReadBitsDelegate _readBitsCallback;
18 |
19 | #region Constructors
20 |
21 | ///
22 | /// Initializes a new instance of the class.
23 | ///
24 | /// The bank number. Must be 1 or 2.
25 | /// Bank number can only be either 1 or 2 - bankNumber.
26 | internal GpioBank(int bankNumber)
27 | {
28 | if (bankNumber != 1 && bankNumber != 2)
29 | throw new ArgumentException("Bank number can only be either 1 or 2", nameof(bankNumber));
30 |
31 | BankNumber = bankNumber;
32 |
33 | _setBitsCallback = bankNumber == 1 ?
34 | IO.GpioWriteBits00To31Set :
35 | new SetClearBitsDelegate(IO.GpioWriteBits32To53Set);
36 |
37 | _clearBitsCallback = bankNumber == 1 ?
38 | IO.GpioWriteBits00To31Clear :
39 | new SetClearBitsDelegate(IO.GpioWriteBits32To53Clear);
40 |
41 | _readBitsCallback = bankNumber == 1 ?
42 | IO.GpioReadBits00To31 :
43 | new ReadBitsDelegate(IO.GpioReadBits32To53);
44 |
45 | if (bankNumber == 1)
46 | {
47 | MinGpioIndex = 0;
48 | MaxGpioIndex = 31;
49 | }
50 | else
51 | {
52 | MinGpioIndex = 32;
53 | MaxGpioIndex = 53;
54 | }
55 |
56 | GpioCount = MaxGpioIndex - MinGpioIndex + 1;
57 | }
58 |
59 | #endregion
60 |
61 | #region Delegates
62 |
63 | private delegate ResultCode SetClearBitsDelegate(BitMask bitMask);
64 | private delegate uint ReadBitsDelegate();
65 |
66 | #endregion
67 |
68 | #region Properties
69 |
70 | ///
71 | /// Gets the bank number; 1 or 2.
72 | ///
73 | public int BankNumber { get; }
74 |
75 | ///
76 | /// Gets the minimum index of the gpio bank.
77 | ///
78 | public int MinGpioIndex { get; }
79 |
80 | ///
81 | /// Gets the maximum index of the gpio bank.
82 | ///
83 | public int MaxGpioIndex { get; }
84 |
85 | ///
86 | /// Gets the number of gpio pins for this bank.
87 | ///
88 | public int GpioCount { get; }
89 |
90 | #endregion
91 |
92 | #region Static Methods
93 |
94 | ///
95 | /// Returns a series of 0s and 1s from MSB to LSB.
96 | /// Please note the output of the Bit Array is reversed.
97 | ///
98 | /// The bits.
99 | /// A string containing 0s and 1s.
100 | public static string ToBinLiteral(BitArray bits)
101 | {
102 | var builder = new StringBuilder(32);
103 |
104 | for (var i = bits.Length - 1; i >= 0; i--)
105 | {
106 | builder.Append(bits[i] ? '1' : '0');
107 | }
108 |
109 | return builder.ToString();
110 | }
111 |
112 | ///
113 | /// Returns a series of hexadecimal chars from MSB to LSB.
114 | /// Please note the output of the byte array is reversed.
115 | ///
116 | /// The bytes.
117 | /// A string containing the hexadecimal chars.
118 | public static string ToHexLiteral(byte[] bytes)
119 | {
120 | var output = bytes.Reverse().ToArray();
121 | return BitConverter.ToString(output).Replace("-", string.Empty);
122 | }
123 |
124 | #endregion
125 |
126 | #region Instance Methods
127 |
128 | ///
129 | /// Clears the bits according to the bit mask.
130 | /// For bank 1, the starting index is GPIO 00.
131 | /// For bank 2, the starting index is GPIO 32.
132 | /// This means that for bank 2, bit 33 is addressed as Bit01 in the bit mask.
133 | ///
134 | /// The bit mask.
135 | public void ClearBits(BitMask bitMask)
136 | {
137 | BoardException.ValidateResult(_clearBitsCallback(bitMask));
138 | }
139 |
140 | ///
141 | /// Sets the bits according to the bit mask.
142 | /// For bank 1, the starting index is GPIO 00.
143 | /// For bank 2, the starting index is GPIO 32.
144 | /// This means that for bank 2, bit 33 is addressed as Bit01 in the bit mask.
145 | ///
146 | /// The bit mask.
147 | public void SetBits(BitMask bitMask)
148 | {
149 | BoardException.ValidateResult(_setBitsCallback(bitMask));
150 | }
151 |
152 | ///
153 | /// Reads the value of all the GPIO pins at once as an unsigned, 32-bit integer.
154 | ///
155 | /// The current value of all pins.
156 | public uint ReadValue() => _readBitsCallback();
157 |
158 | ///
159 | /// Reads the value of all the GPIO pins at once as an array of 4 bytes.
160 | /// The 0th index of the result is the Least Significant Byte (low index pins pins).
161 | /// The 3rd index of the result is the Most Significant Byte (high index pins).
162 | ///
163 | /// The bytes that were read.
164 | public byte[] ReadBytes() => BitConverter.GetBytes(ReadValue());
165 |
166 | ///
167 | /// Reads the value of all the GPIO pins at once, where the 0th index of the array
168 | /// is the lowest pin index (LSB) and the 31st index of the array is the highes pin index (MSB).
169 | ///
170 | /// The bits read.
171 | public BitArray ReadBits() => new BitArray(ReadBytes());
172 |
173 | ///
174 | /// Reads from the bank and returns a series of 0s and 1s from MSB to LSB.
175 | /// Please note the output of the Bit Array is reversed so that the MSB is the first character.
176 | ///
177 | /// A string containing 0s and 1s.
178 | public string ReadBinLiteral() => ToBinLiteral(ReadBits());
179 |
180 | ///
181 | /// Reads from the bank and returns a series of hexadecimal chars from MSB to LSB.
182 | /// Please note the output of the byte array is reversed so that the left-most characters are the MSB.
183 | ///
184 | /// A string containing the hexadecimal chars.
185 | public string ReadHexLiteral() => ToHexLiteral(ReadBytes());
186 |
187 | #endregion
188 | }
189 | }
190 |
--------------------------------------------------------------------------------