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.IO; 22 using System.Linq; 23 using System.Runtime.InteropServices; 24 using System.Text; 25 using System.Threading.Tasks; 26 27 namespace iio 28 { 29 /// <summary><see cref="iio.Channel"/> class: 30 /// Contains the representation of an input or output channel.</summary> 31 public class Channel 32 { 33 private class ChannelAttr : Attr 34 { 35 private IntPtr chn; 36 37 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_attr_read(IntPtr chn, [In()] string name, [Out()] StringBuilder val, uint len)38 private static extern int iio_channel_attr_read(IntPtr chn, [In()] string name, [Out()] StringBuilder val, uint len); 39 40 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_attr_write(IntPtr chn, [In()] string name, string val)41 private static extern int iio_channel_attr_write(IntPtr chn, [In()] string name, string val); 42 43 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_attr_get_filename(IntPtr chn, [In()] string attr)44 private static extern IntPtr iio_channel_attr_get_filename(IntPtr chn, [In()] string attr); 45 ChannelAttr(IntPtr chn, string name)46 public ChannelAttr(IntPtr chn, string name) : base(name, Marshal.PtrToStringAnsi(iio_channel_attr_get_filename(chn, name))) 47 { 48 this.chn = chn; 49 } 50 read()51 public override string read() 52 { 53 StringBuilder builder = new StringBuilder(1024); 54 int err = iio_channel_attr_read(chn, name, builder, (uint) builder.Capacity); 55 if (err < 0) 56 { 57 throw new Exception("Unable to read channel attribute " + err); 58 } 59 return builder.ToString(); 60 } 61 write(string str)62 public override void write(string str) 63 { 64 int err = iio_channel_attr_write(chn, name, str); 65 if (err < 0) 66 { 67 throw new Exception("Unable to write channel attribute " + err); 68 } 69 } 70 } 71 72 /// <summary><see cref="iio.Channel.ChannelModifier"/> class: 73 /// Contains the available channel modifiers.</summary> 74 public enum ChannelModifier 75 { 76 IIO_NO_MOD, 77 IIO_MOD_X, 78 IIO_MOD_Y, 79 IIO_MOD_Z, 80 IIO_MOD_X_AND_Y, 81 IIO_MOD_X_AND_Z, 82 IIO_MOD_Y_AND_Z, 83 IIO_MOD_X_AND_Y_AND_Z, 84 IIO_MOD_X_OR_Y, 85 IIO_MOD_X_OR_Z, 86 IIO_MOD_Y_OR_Z, 87 IIO_MOD_X_OR_Y_OR_Z, 88 IIO_MOD_LIGHT_BOTH, 89 IIO_MOD_LIGHT_IR, 90 IIO_MOD_ROOT_SUM_SQUARED_X_Y, 91 IIO_MOD_SUM_SQUARED_X_Y_Z, 92 IIO_MOD_LIGHT_CLEAR, 93 IIO_MOD_LIGHT_RED, 94 IIO_MOD_LIGHT_GREEN, 95 IIO_MOD_LIGHT_BLUE, 96 IIO_MOD_QUATERNION, 97 IIO_MOD_TEMP_AMBIENT, 98 IIO_MOD_TEMP_OBJECT, 99 IIO_MOD_NORTH_MAGN, 100 IIO_MOD_NORTH_TRUE, 101 IIO_MOD_NORTH_MAGN_TILT_COMP, 102 IIO_MOD_NORTH_TRUE_TILT_COMP, 103 IIO_MOD_RUNNING, 104 IIO_MOD_JOGGING, 105 IIO_MOD_WALKING, 106 IIO_MOD_STILL, 107 IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z, 108 IIO_MOD_I, 109 IIO_MOD_Q, 110 IIO_MOD_CO2, 111 IIO_MOD_VOC, 112 IIO_MOD_LIGHT_UV, 113 IIO_MOD_LIGHT_DUV, 114 IIO_MOD_PM1, 115 IIO_MOD_PM2P5, 116 IIO_MOD_PM4, 117 IIO_MOD_PM10, 118 IIO_MOD_ETHANOL, 119 IIO_MOD_H2 120 } 121 122 /// <summary><see cref="iio.Channel.ChannelType"/> class: 123 /// Contains the available channel types.</summary> 124 public enum ChannelType 125 { 126 IIO_VOLTAGE, 127 IIO_CURRENT, 128 IIO_POWER, 129 IIO_ACCEL, 130 IIO_ANGL_VEL, 131 IIO_MAGN, 132 IIO_LIGHT, 133 IIO_INTENSITY, 134 IIO_PROXIMITY, 135 IIO_TEMP, 136 IIO_INCLI, 137 IIO_ROT, 138 IIO_ANGL, 139 IIO_TIMESTAMP, 140 IIO_CAPACITANCE, 141 IIO_ALTVOLTAGE, 142 IIO_CCT, 143 IIO_PRESSURE, 144 IIO_HUMIDITYRELATIVE, 145 IIO_ACTIVITY, 146 IIO_STEPS, 147 IIO_ENERGY, 148 IIO_DISTANCE, 149 IIO_VELOCITY, 150 IIO_CONCENTRATION, 151 IIO_RESISTANCE, 152 IIO_PH, 153 IIO_UVINDEX, 154 IIO_ELECTRICALCONDUCTIVITY, 155 IIO_COUNT, 156 IIO_INDEX, 157 IIO_GRAVITY, 158 IIO_POSITIONRELATIVE, 159 IIO_PHASE, 160 IIO_MASSCONCENTRATION, 161 IIO_CHAN_TYPE_UNKNOWN = Int32.MaxValue 162 } 163 164 internal IntPtr chn; 165 private uint sample_size; 166 167 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_get_id(IntPtr chn)168 private static extern IntPtr iio_channel_get_id(IntPtr chn); 169 170 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_get_name(IntPtr chn)171 private static extern IntPtr iio_channel_get_name(IntPtr chn); 172 173 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_get_attrs_count(IntPtr chn)174 private static extern uint iio_channel_get_attrs_count(IntPtr chn); 175 176 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_get_attr(IntPtr chn, uint index)177 private static extern IntPtr iio_channel_get_attr(IntPtr chn, uint index); 178 179 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] 180 [return: MarshalAs(UnmanagedType.I1)] iio_channel_is_output(IntPtr chn)181 private static extern bool iio_channel_is_output(IntPtr chn); 182 183 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] 184 [return: MarshalAs(UnmanagedType.I1)] iio_channel_is_scan_element(IntPtr chn)185 private static extern bool iio_channel_is_scan_element(IntPtr chn); 186 187 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_enable(IntPtr chn)188 private static extern void iio_channel_enable(IntPtr chn); 189 190 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_disable(IntPtr chn)191 private static extern void iio_channel_disable(IntPtr chn); 192 193 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] 194 [return: MarshalAs(UnmanagedType.I1)] iio_channel_is_enabled(IntPtr chn)195 private static extern bool iio_channel_is_enabled(IntPtr chn); 196 197 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_read_raw(IntPtr chn, IntPtr buf, IntPtr dst, uint len)198 private static extern uint iio_channel_read_raw(IntPtr chn, IntPtr buf, IntPtr dst, uint len); 199 200 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_write_raw(IntPtr chn, IntPtr buf, IntPtr src, uint len)201 private static extern uint iio_channel_write_raw(IntPtr chn, IntPtr buf, IntPtr src, uint len); 202 203 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_read(IntPtr chn, IntPtr buf, IntPtr dst, uint len)204 private static extern uint iio_channel_read(IntPtr chn, IntPtr buf, IntPtr dst, uint len); 205 206 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_write(IntPtr chn, IntPtr buf, IntPtr src, uint len)207 private static extern uint iio_channel_write(IntPtr chn, IntPtr buf, IntPtr src, uint len); 208 209 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_get_data_format(IntPtr chn)210 private static extern IntPtr iio_channel_get_data_format(IntPtr chn); 211 212 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_get_index(IntPtr chn)213 private static extern int iio_channel_get_index(IntPtr chn); 214 215 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_get_device(IntPtr chn)216 private static extern IntPtr iio_channel_get_device(IntPtr chn); 217 218 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_device_get_context(IntPtr dev)219 private static extern IntPtr iio_device_get_context(IntPtr dev); 220 221 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_get_modifier(IntPtr chn)222 private static extern int iio_channel_get_modifier(IntPtr chn); 223 224 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_get_type(IntPtr chn)225 private static extern int iio_channel_get_type(IntPtr chn); 226 227 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_find_attr(IntPtr chn, [In] string name)228 private static extern IntPtr iio_channel_find_attr(IntPtr chn, [In] string name); 229 230 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_convert(IntPtr chn, IntPtr dst, IntPtr src)231 private static extern void iio_channel_convert(IntPtr chn, IntPtr dst, IntPtr src); 232 233 [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)] iio_channel_convert_inverse(IntPtr chn, IntPtr dst, IntPtr src)234 private static extern void iio_channel_convert_inverse(IntPtr chn, IntPtr dst, IntPtr src); 235 236 /// <summary>The name of this channel.</summary> 237 public readonly string name; 238 239 /// <summary>An identifier of this channel.</summary> 240 /// <remarks>It is possible that two channels have the same ID, 241 /// if one is an input channel and the other is an output channel.</remarks> 242 public readonly string id; 243 244 /// <summary>Contains <c>true</c> if the channel is an output channel, 245 /// <c>false</c> otherwise.</summary> 246 public readonly bool output; 247 248 /// <summary>Contains <c>true</c> if the channel is a scan element, 249 /// <c>false</c> otherwise.</summary> 250 /// <remarks>If a channel is a scan element, then it is possible to enable it 251 /// and use it for I/O operations.</remarks> 252 public readonly bool scan_element; 253 254 /// <summary>A <c>list</c> of all the attributes that this channel has.</summary> 255 public readonly List<Attr> attrs; 256 257 /// <summary>The modifier of this channel.</summary> 258 public ChannelModifier modifier { get; private set; } 259 260 /// <summary>The type of this channel.</summary> 261 public ChannelType type { get; private set; } 262 Channel(IntPtr chn)263 internal Channel(IntPtr chn) 264 { 265 this.chn = chn; 266 attrs = new List<Attr>(); 267 sample_size = (uint)Marshal.ReadInt32(iio_channel_get_data_format(this.chn)) / 8; 268 modifier = (ChannelModifier) iio_channel_get_modifier(chn); 269 type = (ChannelType) iio_channel_get_type(chn); 270 uint nb_attrs = iio_channel_get_attrs_count(chn); 271 272 for (uint i = 0; i < nb_attrs; i++) 273 { 274 attrs.Add(new ChannelAttr(this.chn, Marshal.PtrToStringAnsi(iio_channel_get_attr(chn, i)))); 275 } 276 277 IntPtr name_ptr = iio_channel_get_name(this.chn); 278 if (name_ptr == IntPtr.Zero) 279 { 280 name = ""; 281 } 282 else 283 { 284 name = Marshal.PtrToStringAnsi(name_ptr); 285 } 286 287 id = Marshal.PtrToStringAnsi(iio_channel_get_id(this.chn)); 288 output = iio_channel_is_output(this.chn); 289 scan_element = iio_channel_is_scan_element(this.chn); 290 } 291 292 /// <summary>Enable the current channel, so that it can be used for I/O operations.</summary> enable()293 public void enable() 294 { 295 iio_channel_enable(this.chn); 296 } 297 298 /// <summary>Disable the current channel.</summary> disable()299 public void disable() 300 { 301 iio_channel_disable(this.chn); 302 } 303 304 /// <summary>Returns whether or not the channel has been enabled.</summary> is_enabled()305 public bool is_enabled() 306 { 307 return iio_channel_is_enabled(this.chn); 308 } 309 310 /// <summary>Extract the samples corresponding to this channel from the 311 /// given <see cref="iio.IOBuffer"/> object.</summary> 312 /// <param name="buffer">A valid instance of the <see cref="iio.IOBuffer"/> class.</param> 313 /// <param name="raw">If set to <c>true</c>, the samples are not converted from their 314 /// hardware format to their host format.</param> 315 /// <returns>A <c>byte</c> array containing the extracted samples.</returns> 316 /// <exception cref="System.Exception">The samples could not be read.</exception> read(IOBuffer buffer, bool raw = false)317 public byte[] read(IOBuffer buffer, bool raw = false) 318 { 319 if (!is_enabled()) 320 { 321 throw new Exception("Channel must be enabled before the IOBuffer is instantiated"); 322 } 323 if (this.output) 324 { 325 throw new Exception("Unable to read from output channel"); 326 } 327 328 byte[] array = new byte[(int) (buffer.samples_count * sample_size)]; 329 MemoryStream stream = new MemoryStream(array, true); 330 GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned); 331 IntPtr addr = handle.AddrOfPinnedObject(); 332 uint count; 333 334 if (raw) 335 { 336 count = iio_channel_read_raw(this.chn, buffer.buf, addr, buffer.samples_count * sample_size); 337 } 338 else 339 { 340 count = iio_channel_read(this.chn, buffer.buf, addr, buffer.samples_count * sample_size); 341 } 342 handle.Free(); 343 stream.SetLength((long) count); 344 return stream.ToArray(); 345 346 } 347 348 /// <summary> 349 /// Write the specified array of samples corresponding to this channel into the 350 /// given <see cref="iio.IOBuffer"/> object.</summary> 351 /// <param name="buffer">A valid instance of the <see cref="iio.IOBuffer"/> class.</param> 352 /// <param name="array">A <c>byte</c> array containing the samples to write.</param> 353 /// <param name="raw">If set to <c>true</c>, the samples are not converted from their 354 /// host format to their native format.</param> 355 /// <returns>The number of bytes written.</returns> 356 /// <exception cref="System.Exception">The samples could not be written.</exception> write(IOBuffer buffer, byte[] array, bool raw = false)357 public uint write(IOBuffer buffer, byte[] array, bool raw = false) 358 { 359 if (!is_enabled()) 360 { 361 throw new Exception("Channel must be enabled before the IOBuffer is instantiated"); 362 } 363 if (!this.output) 364 { 365 throw new Exception("Unable to write to an input channel"); 366 } 367 368 GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned); 369 IntPtr addr = handle.AddrOfPinnedObject(); 370 uint count; 371 372 if (raw) 373 { 374 count = iio_channel_write_raw(this.chn, buffer.buf, addr, (uint) array.Length); 375 } 376 else 377 { 378 count = iio_channel_write(this.chn, buffer.buf, addr, (uint) array.Length); 379 } 380 handle.Free(); 381 382 return count; 383 } 384 385 /// <summary>Get the index of this channel.</summary> get_index()386 public long get_index() 387 { 388 return iio_channel_get_index(chn); 389 } 390 391 /// <summary>Finds the attribute of the current channel with the given name.</summary> 392 /// <returns><see cref="iio.Channel.ChannelAttr"/></returns> 393 /// <exception cref="System.Exception">There is no attribute with the given name.</exception> find_attribute(string attribute)394 public Attr find_attribute(string attribute) 395 { 396 IntPtr attr = iio_channel_find_attr(chn, attribute); 397 398 if (attr == IntPtr.Zero) 399 { 400 throw new Exception("There is no attribute with the given name!"); 401 } 402 403 return new ChannelAttr(chn, Marshal.PtrToStringAnsi(attr)); 404 } 405 406 /// <summary>Finds the device of the current channel.</summary> 407 /// <returns><see cref="iio.Device"/></returns> get_device()408 public Device get_device() 409 { 410 IntPtr dev_ptr = iio_channel_get_device(chn); 411 return new Device(new Context(dev_ptr), dev_ptr); 412 } 413 414 /// <summary>Converts the data from the hardware format to the format of the arhitecture on which libiio is running.</summary> convert(IntPtr dst, IntPtr src)415 public void convert(IntPtr dst, IntPtr src) 416 { 417 iio_channel_convert(chn, dst, src); 418 } 419 420 /// <summary>Converts the data from the arhitecture on which libiio is running to the hardware format.</summary> convert_inverse(IntPtr dst, IntPtr src)421 public void convert_inverse(IntPtr dst, IntPtr src) 422 { 423 iio_channel_convert_inverse(chn, dst, src); 424 } 425 } 426 } 427