summaryrefslogtreecommitdiff
path: root/src/bindings/csharp/IOBuffer.cs
blob: 1697f6ef45c3d54795399eeb22f2f42eb3aea341 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
 * libiio - Library for interfacing industrial I/O (IIO) devices
 *
 * Copyright (C) 2015 Analog Devices, Inc.
 * Author: Paul Cercueil <paul.cercueil@analog.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace iio
{
    /// <summary><see cref="iio.IOBuffer"/> class:
    /// The class used for all I/O operations.</summary>
    public class IOBuffer : IDisposable
    {
        private bool circular_buffer_pushed;

        [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern IntPtr iio_device_create_buffer(IntPtr dev, uint samples_count,
                                  [MarshalAs(UnmanagedType.I1)] bool circular);

        [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern void iio_buffer_destroy(IntPtr buf);

        [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern int iio_buffer_refill(IntPtr buf);

        [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern int iio_buffer_push_partial(IntPtr buf, uint samples_count);

        [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern IntPtr iio_buffer_start(IntPtr buf);

        [DllImport("libiio.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern IntPtr iio_buffer_end(IntPtr buf);

        internal IntPtr buf;

        /// <summary>The size of this buffer, in samples.</summary>
        public readonly uint samples_count;

        /// <summary>If <c>true</c>, the buffer is circular.</summary>
        public readonly bool circular;

        /// <summary>Initializes a new instance of the <see cref="iio.IOBuffer"/> class.</summary>
        /// <param name="dev">The <see cref="iio.Device"/> object that represents the device
        /// where the I/O operations will be performed.</param>
        /// <param name="samples_count">The size of the buffer, in samples.</param>
        /// <param name="circular">If set to <c>true</c>, the buffer is circular.</param>
        /// <exception cref="System.Exception">The buffer could not be created.</exception>
        public IOBuffer(Device dev, uint samples_count, bool circular = false)
        {
            this.samples_count = samples_count;
            this.circular = circular;
            this.circular_buffer_pushed = false;

            buf = iio_device_create_buffer(dev.dev, samples_count, circular);
            if (buf == IntPtr.Zero)
                throw new Exception("Unable to create buffer");
        }

        ~IOBuffer()
        {
            if (buf != IntPtr.Zero)
                Dispose(false);
        }

        /// <summary>Fetch a new set of samples from the hardware.</summary>
        /// <exception cref="System.Exception">The buffer could not be refilled.</exception>
        public void refill()
        {
            int err = iio_buffer_refill(this.buf);
            if (err < 0)
                throw new Exception("Unable to refill buffer: err=" + err);
        }

        /// <summary>Submit the samples contained in this buffer to the hardware.</summary>
        /// <exception cref="System.Exception">The buffer could not be pushed.</exception>
        public void push(uint samples_count)
        {
            if (circular && circular_buffer_pushed)
                throw new Exception("Circular buffer already pushed\n");

            int err = iio_buffer_push_partial(this.buf, samples_count);
            if (err < 0)
                throw new Exception("Unable to push buffer: err=" + err);
            circular_buffer_pushed = true;
        }

        public void push()
        {
            push(this.samples_count);
        }

        /// <summary>Releases all resource used by the <see cref="iio.IOBuffer"/> object.</summary>
        /// <remarks>Call <see cref="Dispose"/> when you are finished using the <see cref="iio.IOBuffer"/>. The
        /// <see cref="Dispose"/> method leaves the <see cref="iio.IOBuffer"/> in an unusable state. After calling
        /// <see cref="Dispose"/>, you must release all references to the <see cref="iio.IOBuffer"/> so the garbage
        /// collector can reclaim the memory that the <see cref="iio.IOBuffer"/> was occupying.</remarks>
        public void Dispose()
        {
            Dispose(true);
        }

        private void Dispose(bool clean)
        {
            if (buf != IntPtr.Zero)
            {
                if (clean)
                    GC.SuppressFinalize(this);
                iio_buffer_destroy(buf);
                buf = IntPtr.Zero;
            }
        }

        /// <summary>Copy the given array of samples inside the <see cref="iio.IOBuffer"/> object.</summary>
        /// <param name="array">A <c>byte</c> array containing the samples that should be written.</param>
        /// <remarks>The number of samples written will not exceed the size of the buffer.</remarks>
        public void fill(byte[] array)
        {
            int length = (int) iio_buffer_end(buf) - (int) iio_buffer_start(buf);
            if (length > array.Length)
                length = array.Length;
            Marshal.Copy(array, 0, iio_buffer_start(buf), length);
        }
    }
}