• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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                     throw new Exception("Unable to read channel attribute " + err);
57                 return builder.ToString();
58             }
59 
write(string str)60             public override void write(string str)
61             {
62                 int err = iio_channel_attr_write(chn, name, str);
63                 if (err < 0)
64                     throw new Exception("Unable to write channel attribute " + err);
65             }
66         }
67 
68 
69         private IntPtr chn;
70         private uint sample_size;
71 
72         [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
iio_channel_get_id(IntPtr chn)73         private static extern IntPtr iio_channel_get_id(IntPtr chn);
74 
75         [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
iio_channel_get_name(IntPtr chn)76         private static extern IntPtr iio_channel_get_name(IntPtr chn);
77 
78         [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
iio_channel_get_attrs_count(IntPtr chn)79         private static extern uint iio_channel_get_attrs_count(IntPtr chn);
80 
81         [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
iio_channel_get_attr(IntPtr chn, uint index)82         private static extern IntPtr iio_channel_get_attr(IntPtr chn, uint index);
83 
84         [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
85         [return: MarshalAs(UnmanagedType.I1)]
iio_channel_is_output(IntPtr chn)86         private static extern bool iio_channel_is_output(IntPtr chn);
87 
88         [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
89         [return: MarshalAs(UnmanagedType.I1)]
iio_channel_is_scan_element(IntPtr chn)90         private static extern bool iio_channel_is_scan_element(IntPtr chn);
91 
92         [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
iio_channel_enable(IntPtr chn)93         private static extern void iio_channel_enable(IntPtr chn);
94 
95         [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
iio_channel_disable(IntPtr chn)96         private static extern void iio_channel_disable(IntPtr chn);
97 
98         [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
99         [return: MarshalAs(UnmanagedType.I1)]
iio_channel_is_enabled(IntPtr chn)100         private static extern bool iio_channel_is_enabled(IntPtr chn);
101 
102         [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
iio_channel_read_raw(IntPtr chn, IntPtr buf, IntPtr dst, uint len)103         private static extern uint iio_channel_read_raw(IntPtr chn, IntPtr buf, IntPtr dst, uint len);
104 
105         [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
iio_channel_write_raw(IntPtr chn, IntPtr buf, IntPtr src, uint len)106         private static extern uint iio_channel_write_raw(IntPtr chn, IntPtr buf, IntPtr src, uint len);
107 
108         [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
iio_channel_read(IntPtr chn, IntPtr buf, IntPtr dst, uint len)109         private static extern uint iio_channel_read(IntPtr chn, IntPtr buf, IntPtr dst, uint len);
110 
111         [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
iio_channel_write(IntPtr chn, IntPtr buf, IntPtr src, uint len)112         private static extern uint iio_channel_write(IntPtr chn, IntPtr buf, IntPtr src, uint len);
113 
114         [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
iio_channel_get_data_format(IntPtr chn)115         private static extern IntPtr iio_channel_get_data_format(IntPtr chn);
116 
117         /// <summary>The name of this channel.</summary>
118         public readonly string name;
119 
120         /// <summary>An identifier of this channel.</summary>
121         /// <remarks>It is possible that two channels have the same ID,
122         /// if one is an input channel and the other is an output channel.</remarks>
123         public readonly string id;
124 
125         /// <summary>Contains <c>true</c> if the channel is an output channel,
126         /// <c>false</c> otherwise.</summary>
127         public readonly bool output;
128 
129         /// <summary>Contains <c>true</c> if the channel is a scan element,
130         /// <c>false</c> otherwise.</summary>
131         /// <remarks>If a channel is a scan element, then it is possible to enable it
132         /// and use it for I/O operations.</remarks>
133         public readonly bool scan_element;
134 
135         /// <summary>A <c>list</c> of all the attributes that this channel has.</summary>
136         public readonly List<Attr> attrs;
137 
Channel(IntPtr chn)138         internal Channel(IntPtr chn)
139         {
140             this.chn = chn;
141             attrs = new List<Attr>();
142             sample_size = (uint)Marshal.ReadInt32(iio_channel_get_data_format(this.chn)) / 8;
143             uint nb_attrs = iio_channel_get_attrs_count(chn);
144 
145             for (uint i = 0; i < nb_attrs; i++)
146                 attrs.Add(new ChannelAttr(this.chn, Marshal.PtrToStringAnsi(iio_channel_get_attr(chn, i))));
147 
148             IntPtr name_ptr = iio_channel_get_name(this.chn);
149             if (name_ptr == IntPtr.Zero)
150                 name = "";
151             else
152                 name = Marshal.PtrToStringAnsi(name_ptr);
153 
154             id = Marshal.PtrToStringAnsi(iio_channel_get_id(this.chn));
155             output = iio_channel_is_output(this.chn);
156             scan_element = iio_channel_is_scan_element(this.chn);
157         }
158 
159         /// <summary>Enable the current channel, so that it can be used for I/O operations.</summary>
enable()160         public void enable()
161         {
162             iio_channel_enable(this.chn);
163         }
164 
165         /// <summary>Disable the current channel.</summary>
disable()166         public void disable()
167         {
168             iio_channel_disable(this.chn);
169         }
170 
171         /// <summary>Returns whether or not the channel has been enabled.</summary>
is_enabled()172         public bool is_enabled()
173         {
174             return iio_channel_is_enabled(this.chn);
175         }
176 
177         /// <summary>Extract the samples corresponding to this channel from the
178         /// given <see cref="iio.IOBuffer"/> object.</summary>
179         /// <param name="buffer">A valid instance of the <see cref="iio.IOBuffer"/> class.</param>
180         /// <param name="raw">If set to <c>true</c>, the samples are not converted from their
181         /// hardware format to their host format.</param>
182         /// <returns>A <c>byte</c> array containing the extracted samples.</returns>
183         /// <exception cref="System.Exception">The samples could not be read.</exception>
read(IOBuffer buffer, bool raw = false)184         public byte[] read(IOBuffer buffer, bool raw = false)
185         {
186             if (!is_enabled())
187                 throw new Exception("Channel must be enabled before the IOBuffer is instantiated");
188             if (this.output)
189                 throw new Exception("Unable to read from output channel");
190 
191             byte[] array = new byte[(int) (buffer.samples_count * sample_size)];
192             MemoryStream stream = new MemoryStream(array, true);
193             GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned);
194             IntPtr addr = handle.AddrOfPinnedObject();
195             uint count;
196 
197             if (raw)
198                 count = iio_channel_read_raw(this.chn, buffer.buf, addr, buffer.samples_count * sample_size);
199             else
200                 count = iio_channel_read(this.chn, buffer.buf, addr, buffer.samples_count * sample_size);
201             handle.Free();
202             stream.SetLength((long) count);
203             return stream.ToArray();
204 
205         }
206 
207         /// <summary>
208         /// Write the specified array of samples corresponding to this channel into the
209         /// given <see cref="iio.IOBuffer"/> object.</summary>
210         /// <param name="buffer">A valid instance of the <see cref="iio.IOBuffer"/> class.</param>
211         /// <param name="array">A <c>byte</c> array containing the samples to write.</param>
212         /// <param name="raw">If set to <c>true</c>, the samples are not converted from their
213         /// host format to their native format.</param>
214         /// <returns>The number of bytes written.</returns>
215         /// <exception cref="System.Exception">The samples could not be written.</exception>
write(IOBuffer buffer, byte[] array, bool raw = false)216         public uint write(IOBuffer buffer, byte[] array, bool raw = false)
217         {
218             if (!is_enabled())
219                 throw new Exception("Channel must be enabled before the IOBuffer is instantiated");
220             if (!this.output)
221                 throw new Exception("Unable to write to an input channel");
222 
223             GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned);
224             IntPtr addr = handle.AddrOfPinnedObject();
225             uint count;
226 
227             if (raw)
228                 count = iio_channel_write_raw(this.chn, buffer.buf, addr, (uint) array.Length);
229             else
230                 count = iio_channel_write(this.chn, buffer.buf, addr, (uint) array.Length);
231             handle.Free();
232 
233             return count;
234         }
235     }
236 }
237