PASDK-284:Merge branch 'dev_pasdk_govind_pasdk284' of ssh://bitbucket.itg.ti.com...
[processor-sdk/performance-audio-sr.git] / pasdk / test_dsp / sio_dev2 / dgn2.c
2 /*
3 Copyright (c) 2016, Texas Instruments Incorporated - http://www.ti.com/
4 All rights reserved.
6 * Redistribution and use in source and binary forms, with or without 
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the
16 * distribution.
17 *
18 * Neither the name of Texas Instruments Incorporated nor the names of
19 * its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 */
36 /*
37  *  ======== dgn2.c ========
38  *  Streaming Generator Driver
39  *
40  *  A DGN2 device is a "pseudo-device" that generates one of several
41  *  possible data streams.  For example, a DGN2 can generate sin/cos
42  *  series or white noise.  This driver can be very useful for testing
43  *  applications that require an input stream of data.
44  */
47 #include <xdc/std.h>
48 #include <xdc/runtime/Error.h>
49 #include <xdc/runtime/Memory.h>
50 #include <xdc/runtime/System.h>
51 #include <xdc/runtime/Log.h>
53 #include <stddef.h>
55 #include <ti/sysbios/knl/Queue.h>
57 #include "dgn2.h"
58 #include "dev2.h"
60 #define MAXRANGE        ((1U << (16 - 1)) - 1)
62 __FAR__ DGN2_Params DGN2_PARAMS = {
63     { 1 },                      /* constant: value */
64     { 1, -MAXRANGE, MAXRANGE }, /* rand: seed, lower, upper */
65     { MAXRANGE, 1, 0, 256 },    /* sine: gain, freq, phase, sample rate */
66     { NULL, NULL }              /* user: fxn, arg */
67 };
69 Int DGN2_close(DEV2_Handle device);
70 Int DGN2_idle(DEV2_Handle device, Bool flush);
71 Int DGN2_open(DEV2_Handle device, String name);
72 Int DGN2_ioFunc(DEV2_Handle device);
74 /*
75  *  Driver function table.
76  */
77 __FAR__ DEV2_Fxns DGN2_FXNS = {
78     DGN2_close,         /* close */
79     DEV2_CTRL,          /* ctrl */
80     DGN2_idle,          /* idle */
81     DGN2_ioFunc,        /* issue */
82     DGN2_open,          /* open */
83     DEV2_READY,         /* ready */     /* generator is always ready */
84     (DEV2_Treclaim)DEV2_zero,   /* reclaim */
85 };
87 /*
88  *  ======== DGN2_close ========
89  *  All that needs to be done to close a generator is to
90  *  free memory associated with the driver.  And return
91  *  a status when done.
92  */
93 Int DGN2_close(DEV2_Handle device)
94 {
95     Memory_free(0, device->object, sizeof(DGN2_GenObj));
96     
97     return (DEV2_OK);
98 }
100 /*
101  *  ======== DGN2_idle ========
102  *  For DGN2 idling, we don't need to do any queue manipulation since
103  *  there's no way for frames to build up on a queue (they always get
104  *  processed).
105  *  All we need to do is reset state variables.
106  */
107 Int DGN2_idle(DEV2_Handle device, Bool flush)
109     DGN2_GenObj *gen = (DGN2_GenObj *)device->object;
111     gen->seed = gen->dparams->rand.seed;
113     gen->index = 0;
115     return (DEV2_OK);
118 /*
119  *  ======== DGN2_ioFunc ========
120  *  This routine removes a frame from the 'todevice' list, fills it
121  *  with data, and moves it to the 'fromdevice' list.
122  */
123 Int DGN2_ioFunc(DEV2_Handle device)
125     DGN2_GenObj *gen;
126     DEV2_Frame  *frame;
127     
128     frame = Queue_get(device->todevice);
129     gen = (DGN2_GenObj *)device->object;
131     (*gen->fxn)(gen, frame->addr, frame->size);
133     Queue_put(device->fromdevice, (Queue_Elem *)frame);
135     return (DEV2_OK);
138 /*
139  *  ======== DGN2_open ========
140  *  This routine creates a generator object that will be used
141  *  when manipulating this device (ie. getting data, getting
142  *  status, etc.).
143  */
144 Int DGN2_open(DEV2_Handle device, String name)
146     DGN2_GenObj  *gen;
147     Int           gain;
148     Int           cnst;
149     Error_Block   eb;
151     cnst = 0;
152     Error_init(&eb);
154     /* allocate generator object */
155     if ((gen = Memory_alloc(0, sizeof(DGN2_GenObj), 0, &eb)) == NULL) {
156         Log_error0("DGN2_open: Memory_alloc() failed");
157         return (DEV2_ENOMEM);
158     }
160     gen->dparams = (device->params) ?
161       (DGN2_Params *)device->params : &DGN2_PARAMS;
163     /*
164      * bug fix MR 4493
165      * gain = gain - 1 to fix boundary case --
166      * gain of 128 was yielding values between -256 and 256
167      * gain of 16 gave -32 to 32
168      * etc.
169      */
170     gain = gen->dparams->sine.gain - 1;
171     while (gain > 0) {
172         cnst++;
173         gain >>= 1;
174     }
176     gen->shift = 16 - 1 - cnst;
177     gen->step = (256 * gen->dparams->sine.freq) / gen->dparams->sine.rate;
178     gen->index = 0;
180     gen->seed = gen->dparams->rand.seed;
182     gen->fxn = (Fxn)device->devid;
184     device->object = (Ptr)gen;
186     return (DEV2_OK);
189 /*
190  *  ======== DGN2_user ========
191  *  Fill the buffer whose address is "addr" with random values generated
192  *  "size" times.  The random values are generated using a recursive
193  *  equation.
194  */
195 Void DGN2_user(DGN2_GenObj *gen, Ptr addr, size_t size)
197     Arg         arg;
198     Fxn         fxn;
200     arg = gen->dparams->user.arg;
201     fxn = gen->dparams->user.fxn;
203     (*fxn)(arg, addr, size);
206 /*
207  *  ======== DGN2_printHex ========
208  */
209 Void DGN2_printHex(Arg arg, Ptr addr, size_t size)
211     Int16       *buf = (Int16 *)addr;
212     Int         tmp;
213         
214     size = size / sizeof(Int16);
216     for (; size > 0; size--, buf++) {
217         tmp = *buf & 0xffff;
218         System_printf("0x%04x\n", tmp);
219     }
222 /*
223  *  ======== DGN2_printInt ========
224  */
225 Void DGN2_printInt(Arg arg, Ptr addr, Uns size)
227     Int16       *buf = (Int16 *)addr;
228         
229     size = size / sizeof(Int16);
231     for (; size > 0; size--, buf++) {
232         System_printf("%d\n", *buf);
233     }
236 /*
237  *  ======== DGN2_iconst ========
238  *  Fill the buffer whose address is "addr" with constant values generated
239  *  "size" times.
240  */
241 Void DGN2_iconst(DGN2_GenObj *gen, Int16 *addr, size_t size)
243     size_t        i;
245     for (i = (size / sizeof(Int16)); i > 0; i--) {
246         *addr++ = gen->dparams->constant.value;
247     }
250 /*
251  *  ======== DGN2_irand ========
252  *  Fill the buffer whose address is "addr" with random values generated
253  *  "size" times.  The random values are generated using a recursive
254  *  equation.
255  */
256 Void DGN2_irand(DGN2_GenObj *gen, Int16 *addr, size_t size)
258     size_t      i;
259     Uns         range;
260     Uns         rnd;
261     UInt32      next;
263     range = gen->dparams->rand.upper - gen->dparams->rand.lower + 1;
264     next = gen->seed;
266     for (i = (size / sizeof(Int16)); i > 0; i--) {
267         /*
268          *      Random numbers are generated using a linear congruential
269          *  psuedo random generator using the equation:
270          *      f(n+1) = (a * f(n) + c) mod M,  for (n >= 0)
271          *  to insure the cycle length to be M = 2^N for an N-bit
272          *  binary two's complement machine:
273          *      a mod 8 == 5
274          *      c mod 2 == 1
275          *  See Knuth Vol II Seminumerical Algorithms for theory.
276          */
277         next = next * 1103515245 + 12345;
279         /*
280          *  Note the top bits are "more random" than the bottom bits
281          *  so to scale the number treat the top 16 bits as a binary
282          *  fraction (from 0.0 - < 1.0) and multiply by the desired
283          *  range and truncate the result.
284          */
285         rnd = (next >> 16);
286         if (range) {
287             rnd = (Uint16) (((UInt32) rnd * (UInt32) range) >> 16);
288         }
289         *addr++ = rnd + gen->dparams->rand.lower;
290     }
292     gen->seed = next;
295 /*
296  *  ======== DGN2_isine ========
297  *  Fill the buffer whose address is "addr" with sine values generated
298  *  "size" times.
299  *
300  *  NOTE:  If the sampling rate is not evenly divisible by the
301  *         frequency, the generated output is not a sine wave
302  *         but a sequence of a sine-like wave.
303  */
304 Void DGN2_isine(DGN2_GenObj *gen, Int16 *addr, size_t size)
306     size_t         i;
307 static __FAR__ Int16 sineTable[256] = {
308     0x0000,0x0324,0x0647,0x096A,0x0C8B,0x0FAB,0x12C8,0x15E2,
309     0x18F8,0x1C0B,0x1F19,0x2223,0x2528,0x2826,0x2B1F,0x2E11,
310     0x30FB,0x33DE,0x36BA,0x398C,0x3C56,0x3F17,0x41CE,0x447A,
311     0x471C,0x49B4,0x4C3F,0x4EBF,0x5133,0x539B,0x55F5,0x5842,
312     0x5A82,0x5CB4,0x5ED7,0x60EC,0x62F2,0x64E8,0x66CF,0x68A6,
313     0x6A6D,0x6C24,0x6DCA,0x6F5F,0x70E2,0x7255,0x73B5,0x7504,
314     0x7641,0x776C,0x7884,0x798A,0x7A7D,0x7B5D,0x7C29,0x7CE3,
315     0x7D8A,0x7E1D,0x7E9D,0x7F09,0x7F62,0x7FA7,0x7FD8,0x7FF6,
316     0x7FFF,0x7FF6,0x7FD8,0x7FA7,0x7F62,0x7F09,0x7E9D,0x7E1D,
317     0x7D8A,0x7CE3,0x7C29,0x7B5D,0x7A7D,0x798A,0x7884,0x776C,
318     0x7641,0x7504,0x73B5,0x7255,0x70E2,0x6F5F,0x6DCA,0x6C24,
319     0x6A6D,0x68A6,0x66CF,0x64E8,0x62F2,0x60EC,0x5ED7,0x5CB4,
320     0x5A82,0x5842,0x55F5,0x539B,0x5133,0x4EBF,0x4C3F,0x49B4,
321     0x471C,0x447A,0x41CE,0x3F17,0x3C56,0x398C,0x36BA,0x33DE,
322     0x30FB,0x2E11,0x2B1F,0x2826,0x2528,0x2223,0x1F19,0x1C0B,
323     0x18F8,0x15E2,0x12C8,0x0FAB,0x0C8B,0x096A,0x0647,0x0324,
324     0x0000,0xFCDB,0xF9B8,0xF695,0xF374,0xF054,0xED37,0xEA1D,
325     0xE707,0xE3F4,0xE0E6,0xDDDC,0xDAD7,0xD7D9,0xD4E0,0xD1EE,
326     0xCF04,0xCC21,0xC945,0xC673,0xC3A9,0xC0E8,0xBE31,0xBB85,
327     0xB8E3,0xB64B,0xB3C0,0xB140,0xAECC,0xAC64,0xAA0A,0xA7BD,
328     0xA57D,0xA34B,0xA128,0x9F13,0x9D0D,0x9B17,0x9930,0x9759,
329     0x9592,0x93DB,0x9235,0x90A0,0x8F1D,0x8DAA,0x8C4A,0x8AFB,
330     0x89BE,0x8893,0x877B,0x8675,0x8582,0x84A2,0x83D6,0x831C,
331     0x8275,0x81E2,0x8162,0x80F6,0x809D,0x8058,0x8027,0x8009,
332     0x8000,0x8009,0x8027,0x8058,0x809D,0x80F6,0x8162,0x81E2,
333     0x8275,0x831C,0x83D6,0x84A2,0x8582,0x8675,0x877B,0x8893,
334     0x89BE,0x8AFB,0x8C4A,0x8DAA,0x8F1D,0x90A0,0x9235,0x93DB,
335     0x9592,0x9759,0x9930,0x9B17,0x9D0D,0x9F13,0xA128,0xA34B,
336     0xA57D,0xA7BD,0xAA0A,0xAC64,0xAECC,0xB140,0xB3C0,0xB64B,
337     0xB8E3,0xBB85,0xBE31,0xC0E8,0xC3A9,0xC673,0xC945,0xCC21,
338     0xCF04,0xD1EE,0xD4E0,0xD7D9,0xDAD7,0xDDDC,0xE0E6,0xE3F4,
339     0xE707,0xEA1D,0xED37,0xF054,0xF374,0xF695,0xF9B8,0xFCDB,
340 };
342     for (i = (size / sizeof(Int16)); i > 0; i--) {
343         *addr++ = (Int16) sineTable[gen->index] >> (gen->shift); /* modified by gain */
344         gen->index += gen->step;
345         gen->index = gen->index & 0xff;                 /* count % 256 */
346     }