1 /* 2 * libiio - Library for interfacing industrial I/O (IIO) devices 3 * 4 * Copyright (C) 2015 Analog Devices, Inc. 5 * Author: Paul Cercueil <paul.cercueil@analog.com> 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * */ 18 19 using System; 20 using System.Collections.Generic; 21 using System.Linq; 22 using System.Runtime.InteropServices; 23 using System.Runtime.Remoting.Contexts; 24 using System.Security.Authentication.ExtendedProtection; 25 using System.Text; 26 using System.Threading.Tasks; 27 28 namespace iio 29 { 30 /// <summary><see cref="iio.IOBuffer"/> class: 31 /// The class used for all I/O operations.</summary> 32 public class IOBuffer : IDisposable 33 { 34 private bool circular_buffer_pushed; 35 36 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_create_buffer(IntPtr dev, uint samples_count, [MarshalAs(UnmanagedType.I1)] bool circular)37 private static extern IntPtr iio_device_create_buffer(IntPtr dev, uint samples_count, 38 [MarshalAs(UnmanagedType.I1)] bool circular); 39 40 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_buffer_destroy(IntPtr buf)41 private static extern void iio_buffer_destroy(IntPtr buf); 42 43 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_buffer_refill(IntPtr buf)44 private static extern int iio_buffer_refill(IntPtr buf); 45 46 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_buffer_push_partial(IntPtr buf, uint samples_count)47 private static extern int iio_buffer_push_partial(IntPtr buf, uint samples_count); 48 49 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_buffer_start(IntPtr buf)50 private static extern IntPtr iio_buffer_start(IntPtr buf); 51 52 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_buffer_end(IntPtr buf)53 private static extern IntPtr iio_buffer_end(IntPtr buf); 54 55 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_buffer_get_poll_fd(IntPtr buf)56 private static extern int iio_buffer_get_poll_fd(IntPtr buf); 57 58 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_buffer_set_blocking_mode(IntPtr buf, bool blocking)59 private static extern int iio_buffer_set_blocking_mode(IntPtr buf, bool blocking); 60 61 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_buffer_cancel(IntPtr buf)62 private static extern void iio_buffer_cancel(IntPtr buf); 63 64 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_buffer_first(IntPtr buf, IntPtr chn)65 private static extern IntPtr iio_buffer_first(IntPtr buf, IntPtr chn); 66 67 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_buffer_step(IntPtr buf)68 private static extern long iio_buffer_step(IntPtr buf); 69 70 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_get_context(IntPtr dev)71 private static extern IntPtr iio_device_get_context(IntPtr dev); 72 73 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_buffer_get_device(IntPtr buf)74 private static extern IntPtr iio_buffer_get_device(IntPtr buf); 75 76 internal IntPtr buf; 77 78 /// <summary>The size of this buffer, in samples.</summary> 79 public readonly uint samples_count; 80 81 /// <summary>If <c>true</c>, the buffer is circular.</summary> 82 public readonly bool circular; 83 84 /// <summary>Initializes a new instance of the <see cref="iio.IOBuffer"/> class.</summary> 85 /// <param name="dev">The <see cref="iio.Device"/> object that represents the device 86 /// where the I/O operations will be performed.</param> 87 /// <param name="samples_count">The size of the buffer, in samples.</param> 88 /// <param name="circular">If set to <c>true</c>, the buffer is circular.</param> 89 /// <exception cref="System.Exception">The buffer could not be created.</exception> IOBuffer(Device dev, uint samples_count, bool circular = false)90 public IOBuffer(Device dev, uint samples_count, bool circular = false) 91 { 92 this.samples_count = samples_count; 93 this.circular = circular; 94 this.circular_buffer_pushed = false; 95 96 buf = iio_device_create_buffer(dev.dev, samples_count, circular); 97 if (buf == IntPtr.Zero) 98 { 99 throw new Exception("Unable to create buffer"); 100 } 101 } 102 ~IOBuffer()103 ~IOBuffer() 104 { 105 if (buf != IntPtr.Zero) 106 { 107 Dispose(false); 108 } 109 } 110 111 /// <summary>Fetch a new set of samples from the hardware.</summary> 112 /// <exception cref="System.Exception">The buffer could not be refilled.</exception> refill()113 public void refill() 114 { 115 int err = iio_buffer_refill(this.buf); 116 if (err < 0) 117 { 118 throw new Exception("Unable to refill buffer: err=" + err); 119 } 120 } 121 122 /// <summary>Submit the samples contained in this buffer to the hardware.</summary> 123 /// <exception cref="System.Exception">The buffer could not be pushed.</exception> push(uint samples_count)124 public void push(uint samples_count) 125 { 126 if (circular && circular_buffer_pushed) 127 { 128 throw new Exception("Circular buffer already pushed\n"); 129 } 130 131 int err = iio_buffer_push_partial(this.buf, samples_count); 132 if (err < 0) 133 { 134 throw new Exception("Unable to push buffer: err=" + err); 135 } 136 circular_buffer_pushed = true; 137 } 138 139 /// <summary>Submit all the samples contained in this buffer to the hardware.</summary> push()140 public void push() 141 { 142 push(this.samples_count); 143 } 144 145 /// <summary>Releases all resource used by the <see cref="iio.IOBuffer"/> object.</summary> 146 /// <remarks>Call <see cref="Dispose"/> when you are finished using the <see cref="iio.IOBuffer"/>. The 147 /// <see cref="Dispose"/> method leaves the <see cref="iio.IOBuffer"/> in an unusable state. After calling 148 /// <see cref="Dispose"/>, you must release all references to the <see cref="iio.IOBuffer"/> so the garbage 149 /// collector can reclaim the memory that the <see cref="iio.IOBuffer"/> was occupying.</remarks> Dispose()150 public void Dispose() 151 { 152 Dispose(true); 153 } 154 Dispose(bool clean)155 private void Dispose(bool clean) 156 { 157 if (buf != IntPtr.Zero) 158 { 159 if (clean) 160 { 161 GC.SuppressFinalize(this); 162 } 163 iio_buffer_destroy(buf); 164 buf = IntPtr.Zero; 165 } 166 } 167 168 /// <summary>Copy the given array of samples inside the <see cref="iio.IOBuffer"/> object.</summary> 169 /// <param name="array">A <c>byte</c> array containing the samples that should be written.</param> 170 /// <remarks>The number of samples written will not exceed the size of the buffer.</remarks> fill(byte[] array)171 public void fill(byte[] array) 172 { 173 long length = (long) iio_buffer_end(buf) - (long) iio_buffer_start(buf); 174 if (length > array.Length) 175 { 176 length = array.Length; 177 } 178 Marshal.Copy(array, 0, iio_buffer_start(buf), (int)length); 179 } 180 181 /// <summary>Extract the samples from the <see cref="iio.IOBuffer"/> object.</summary> 182 /// <param name="array">A <c>byte</c> array containing the extracted samples.</param> read(byte[] array)183 public void read(byte[] array) 184 { 185 long length = (long) iio_buffer_end(buf) - (long) iio_buffer_start(buf); 186 if (length > array.Length) 187 { 188 length = array.Length; 189 } 190 Marshal.Copy(iio_buffer_start(buf), array, 0, (int)length); 191 } 192 193 /// <summary>Returns poll file descriptor for the current buffer.</summary> get_poll_fd()194 public int get_poll_fd() 195 { 196 return iio_buffer_get_poll_fd(buf); 197 } 198 199 /// <summary>Sets the blocking behavior of the current buffer.</summary> 200 /// <param name="blocking">true if blocking buffer, otherwise false</param> set_blocking_mode(bool blocking)201 public int set_blocking_mode(bool blocking) 202 { 203 return iio_buffer_set_blocking_mode(buf, blocking); 204 } 205 206 /// <summary>Cancels the current buffer.</summary> cancel()207 public void cancel() 208 { 209 iio_buffer_cancel(buf); 210 } 211 212 /// <summary>Gets the device of the current buffer.</summary> 213 /// <returns>The device of the current buffer.</returns> get_device()214 public Device get_device() 215 { 216 IntPtr dev = iio_buffer_get_device(buf); 217 return new Device(new Context(iio_device_get_context(dev)), dev); 218 } 219 220 /// <summary>Gets a pointer to the first sample from the current buffer for a specific channel.</summary> 221 /// <param name="ch">The channel for which to find the first sample.</param> first(Channel ch)222 public IntPtr first(Channel ch) 223 { 224 if (ch == null) 225 { 226 throw new System.Exception("The channel should not be null!"); 227 } 228 return iio_buffer_first(buf, ch.chn); 229 } 230 231 /// <summary>Gets the step size of the current buffer.</summary> step()232 public long step() 233 { 234 return iio_buffer_step(buf); 235 } 236 } 237 } 238