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