-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathdsputil.cpp
418 lines (363 loc) · 12.3 KB
/
dsputil.cpp
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
/**********************************************************
* dsputil.c - Functions to simplify using the DSP chip
* rev 1 - april 2022 - shabaz
**********************************************************/
// includes
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
//extern "C" {
#include <wiringPi.h>
//}
#include "dsputil.h"
#include "i2cfunc.h"
#include <math.h>
// globals
int dsp_handle; // I2C handle for DSP chip
char do_log = 1;
// function to open I2C communication with the DSP
void dsp_open(void) {
dsp_handle = i2c_open(I2CBUS, DSP_ADDR);
}
// function to close I2C communication with the DSP
void dsp_close(void) {
i2c_close(dsp_handle);
}
// put integer into a char array, with the correct order
// (most significant byte first)
void swap_order(char* res, int n)
{
*res = *(((char*)&n)+1);
*(res+1) = *((char*)&n);
}
// program the EEPROM on the DSP board with a .bin application file
int ee_prog(char* fname) {
FILE *fptr = NULL;
char fbuf[BLOCKSIZE+2];
size_t bytesRead = 0;
unsigned int addr = 0x0000;
int ee_handle;
if ((fptr = fopen(fname, "rb")) == NULL) {
if (do_log) {
printf("file '%s' not found!\n", fname);
} else {
printf("error\n");
}
return(1);
}
if (do_log) printf("setting WP low\n");
wiringPiSetupGpio();
pinMode(WPGPIO, OUTPUT);
digitalWrite(WPGPIO, 0);
ee_handle = i2c_open(I2CBUS, EE_ADDR);
memset(&fbuf[2], 0xff, BLOCKSIZE);
while ((bytesRead = fread(&fbuf[2], 1, BLOCKSIZE, fptr)) > 0)
{
if (do_log) printf("writing block to addr 0x%04x\n", addr);
fbuf[0]=(char)((addr>>8) & 0x00ff);
fbuf[1]=(char)(addr & 0x00ff);
i2c_write(ee_handle, (unsigned char*)fbuf, BLOCKSIZE+2);
delay_ms(200);
memset(fbuf, 0xff, BLOCKSIZE);
addr = addr + BLOCKSIZE;
}
i2c_close(ee_handle);
pinMode(WPGPIO, INPUT);
return(0);
}
// 5.23 format used by DSP
// parameters: v is the decimal input, bytes is a 4-byte array
void
double_to_5_23_format(double v, char* bytes) {
int decscaled;
char tb;
decscaled = (int)( v * TWOPOW23 );
memcpy((void*)bytes, (const void*)&decscaled, 4);
bytes[3] &= 0x0f; // we only want 28 bits, not 32
// flip the bytes ordering
tb = bytes[0];
bytes[0]=bytes[3];
bytes[3]=tb;
tb=bytes[1];
bytes[1]=bytes[2];
bytes[2]=tb;
}
// 5.19 format used by DSP (e.g. for Readback)
// parameters: v is the decimal result, bytes is the 3-byte array to be converted
void
dsp_5_19_format_to_double(double *v, char* bytes) {
int unscaled;
char* iptr = (char*)&unscaled;
*iptr = 0x00; // we only have 24 bits
*(iptr+1) = bytes[2];
*(iptr+2) = bytes[1];
*(iptr+3) = bytes[0];
unscaled = unscaled >> 4;
*v = ((double)unscaled) / TWOPOW23;
}
// set the frequency for the DSP Sine Tone object
void
set_freq(int addr, int f) {
char buf[6];
// sin_lookupAlg19401mask
swap_order(buf, addr); // store addr into start of buffer
buf[2] = 0x00;
buf[3] = 0x00;
buf[4] = 0x00;
buf[5] = 0xff;
if (do_log) printf("writing to address 0x%02x%02x\n", buf[0], buf[1]);
i2c_write(dsp_handle, (unsigned char*)buf, 6);
// sin_lookupAlg19401increment
addr++;
swap_order(buf, addr);
double_to_5_23_format( ((double)f)/24000.0, &buf[2] );
if (do_log) printf("writing to address 0x%02x%02x\n", buf[0], buf[1]);
i2c_write(dsp_handle, (unsigned char*)buf, 6);
// sin_lookupAlg19401ison
addr++;
swap_order(buf, addr);
buf[2] = 0x00;
buf[3] = 0x80;
buf[4] = 0x00;
buf[5] = 0x00;
if (do_log) printf("writing to address 0x%02x%02x\n", buf[0], buf[1]);
i2c_write(dsp_handle, (unsigned char*)buf, 6);
}
// set the frequency for the DSP Sine with Phase and Gain object
// (Sources->Oscillators->With Phase->Sine Tone with Phase and Gain)
void
set_sinphase_freq(int addr, int f) {
char buf[6];
// sin_lookupPhaseNincrement
swap_order(buf, addr); // store addr into start of buffer
double_to_5_23_format( ((double)f)/24000.0, &buf[2] );
if (do_log) printf("writing to address 0x%02x%02x\n", buf[0], buf[1]);
i2c_write(dsp_handle, (unsigned char*)buf, 6);
}
// set the gain value of the object
void
set_sinphase_gain(int addr, double amp)
{
char buf[6];
addr=addr+2;
// sin_lookupPhaseNGain_0
swap_order(buf, addr); // store addr into start of buffer
double_to_5_23_format( amp, &buf[2] );
if (do_log) printf("writing to address 0x%02x%02x\n", buf[0], buf[1]);
i2c_write(dsp_handle, (unsigned char*)buf, 6);
}
// set the phase value of the object
void
set_sinphase_phase(int addr, int ang)
{
char buf[6];
double acalc;
char angc;
addr=addr+3;
acalc = ((double)ang)/1.411764; // get 0-360 deg into 0-255 range
acalc = roundf(acalc);
angc=(char)acalc;
// sin_lookupPhaseNGain_0
swap_order(buf, addr); // store addr into start of buffer
buf[2] = 0x00;
buf[3] = 0x80;
buf[4] = 0x00;
buf[5] = angc;
if (do_log) printf("writing to address 0x%02x%02x\n", buf[0], buf[1]);
i2c_write(dsp_handle, (unsigned char*)buf, 6);
}
// DSP General 2nd Order Filter
// (Filters->Second Order->Double Precision->1 Ch->General (2nd order))
// coeff is pointer array of five double values b0, b1, b2, a1, a2
void
set_gen_2nd_order_filter(int addr, double* coeff) {
char buf[6];
int i;
double c;
for (i=0; i<5; i++) {
// EQ1940Singlex0b1 to EQ1940Singlex2a1
swap_order(buf, addr+i); // store addr into start of buffer
c = coeff[i];
if (i>=3) {
c = 0-c; // a1 and a2 need opposite sign, don't know why
}
double_to_5_23_format( c, &buf[2] );
if (do_log) printf("writing to address 0x%02x%02x coeff 0x%02x,%02x,%02x,%02x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
i2c_write(dsp_handle, (unsigned char*)buf, 6);
}
}
// set the amplitude for the DSP Single Volume object
void
set_amp(int addr, double a) {
char buf[6];
// Gain1940AlgNS1
swap_order(buf, addr); // store addr into start of buffer
double_to_5_23_format( a, &buf[2] );
if (do_log) printf("writing to address 0x%02x%02x values 0x%02x,%02x,%02x,%02x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
i2c_write(dsp_handle, (unsigned char*)buf, 6);
}
// set the DC integer (28.0) value for the DSP DC Input Entry object
// (Sources->DC->DC Input Entry)
// v is a value 0 to 0xffff
void
set_dc_int(int addr, int v) {
char buf[6];
swap_order(buf, addr); // store addr into start of buffer
// DCInpAlg1
buf[2] = 0; // really we should handle a 4-byte integer, but for now restrict to 2-bytes
buf[3] = 0;
swap_order(&buf[4], v); // store integer into the buffer
if (do_log) printf("writing to address 0x%02x%02x values 0x%02x,%02x,%02x,%02x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
i2c_write(dsp_handle, (unsigned char*)buf, 6);
}
// set the DC float (28.0) value for the DSP DC Input Entry object
// (Sources->DC->DC Input Entry)
// v is a double value
void
set_dc_float(int addr, double v) {
char buf[6];
swap_order(buf, addr); // store addr into start of buffer
// DCInpAlg1
double_to_5_23_format( v, &buf[2] );
if (do_log) printf("writing to address 0x%02x%02x values 0x%02x,%02x,%02x,%02x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
i2c_write(dsp_handle, (unsigned char*)buf, 6);
}
// safeload version of set_dc_float
void
set_dc_float_safeload(int addr, double v) {
char buf[7];
// set data for safeload operation
swap_order(buf, SAFE_DATA0); // data operation
buf[2]=0; // this byte is always zero for any safeload data operation
// DCInpAlg1
double_to_5_23_format( v, &buf[3] );
if (do_log) printf("writing to address 0x%02x%02x values 0x%02x,%02x,%02x,%02x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
i2c_write(dsp_handle, (unsigned char*)buf, 7);
// set addr for safeload operation
swap_order(buf, SAFE_ADDR0); // address operation
swap_order(&buf[2], addr); // store addr
if (do_log) printf("writing to address 0x%02x%02x values 0x%02x,%02x,%02x,%02x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
i2c_write(dsp_handle, (unsigned char*)buf, 4);
// initiate the safeload transfer
swap_order(buf, SAFE_INITIATE); // safeload initiate operation
swap_order(&buf[2], SAFE_SET_IST);
if (do_log) printf("writing to address 0x%02x%02x values 0x%02x,%02x,%02x,%02x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
i2c_write(dsp_handle, (unsigned char*)buf, 4);
}
// enable or disable mute (set mute to 1 to mute the signal)
// (Volume Controls->Mute->No Slew (Standard)->Mute)
void
set_mute(int addr, char mute) {
char buf[6];
buf[2] = 0x00;
buf[3] = 0x00;
buf[4] = 0x00;
buf[5] = 0x00;
if (mute==0) buf[3] = 0x80;
// MuteNoSlewAlg1mute
swap_order(buf, addr); // store addr into start of buffer
if (do_log) printf("writing to address 0x%02x%02x\n", buf[0], buf[1]);
i2c_write(dsp_handle, (unsigned char*)buf, 6);
}
// set the pitch for the DSP Pitch Transposer object
// (ADI Algorithms->Pitch Modification->Pitch Transposer)
void
set_pitch(int addr, double p) {
char buf[6];
// PitchShiftsAlg1freq
swap_order(buf, addr); // store addr into start of buffer
double_to_5_23_format( p, &buf[2] );
if (do_log) printf("writing to address 0x%02x%02x\n", buf[0], buf[1]);
i2c_write(dsp_handle, (unsigned char*)buf, 6);
}
// set the switch on or off
// (Sources->Switch(0,1)->28_0 Format->On/Off Switch)
// v=0 represents OFF, and v>0 represents ON.
void
set_switch(int addr, int v) {
char buf[6];
// SwitchAlg28Nison
swap_order(buf, addr); // store addr into start of buffer
buf[2]=0;
buf[3]=0;
buf[4]=0;
if (v) {
buf[5] = 1;
} else {
buf[5] = 0;
}
if (do_log) printf("writing to address 0x%02x%02x\n", buf[0], buf[1]);
i2c_write(dsp_handle, (unsigned char*)buf, 6);
}
// set the Double Precision Nth Order Filter (2-Channel)
// (Filters->Nth Order->Double Precision->2 Channels->Nth Order Filter)
void
set_dfilter6(int addr, double* coeff) {
char buf[6];
int i;
double c;
for (i=0; i<15; i++) {
// NthOrderDouble2xxxx
swap_order(buf, addr+i); // store addr into start of buffer
c = coeff[i];
double_to_5_23_format( c, &buf[2] );
if (do_log) printf("writing to address 0x%02x%02x coeff 0x%02x,%02x,%02x,%02x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
i2c_write(dsp_handle, (unsigned char*)buf, 6);
}
}
// bypass the Double Precision Nth Order Filter (2-Channel)
void
set_dfilter6_bypass (int addr) {
char buf[6];
int i;
for (i=0; i<15; i++) {
// NthOrderDouble2xxxx
swap_order(buf, addr+i); // store addr into start of buffer
buf[2]=0x00;
buf[3]=0x00;
buf[4]=0x00;
buf[5]=0x00;
if ((i==0) || (i==5) || (i==10)) {
buf[3]=0x80;
}
if (do_log) printf("writing to address 0x%02x%02x coeff 0x%02x,%02x,%02x,%02x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
i2c_write(dsp_handle, (unsigned char*)buf, 6);
}
}
// performs DSP readback (data capture register)
// addr should be 0x081a or 0x081b for ADAU1401 DSP
// node is a 16-bit value
// The code returns a decimal number
double
readback(int addr, int node) {
int ret;
char buf[6];
char r[3];
double v;
// ReadBackAlg
swap_order(buf, addr); // store addr into start of buffer
swap_order(&buf[2], node); // store node into buffer
if (do_log) printf("writing to address 0x%02x%02x node 0x%02x%02x\n", buf[0], buf[1], buf[2], buf[3]);
i2c_write(dsp_handle, (unsigned char*)buf, 4);
delay_ms(100);
ret=i2c_write_read(dsp_handle, DSP_ADDR, (unsigned char*)buf, 2, DSP_ADDR, (unsigned char*)r, 3);
if (do_log) printf("read %d bytes: 0x%02x, %02x, %02x\n", ret, *r, *(r+1), *(r+2));
dsp_5_19_format_to_double(&v, r);
return(v);
}
// performs mean square to V RMS conversion
double
ms_to_rms(double ms) {
return(sqrt(ms) * 2);
}
// performs mean square to V p-p conversion
double
ms_to_pp(double ms) {
return( SQROOT2 * ms_to_rms(ms) );
}
// perform mean square to dBu conversion
double
ms_to_dbu(double ms) {
return(log10(ms_to_rms(ms) / sqrt(0.001*600)) * 20);
}