Check-in [1d38441bbc]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Added a mu-Law codec to the record over UART feature to provide for 14-bit effective dynamic range in the captured recordings, which matches the dynamic range actually produced by the PDM to PCM conversion as implemented.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 1d38441bbc47e83d63d6ed9b65b0a8d22108803b
User & Date: rberteig 2015-03-17 00:48:23
Context
2015-03-27
01:04
Added second sonar driving the blue LED. The GRN sonar is active low during PCM sample processing. The BLU sonar is active low in the main loop. check-in: 1fe01e0ab5 user: rberteig tags: trunk
2015-03-17
00:48
Added a mu-Law codec to the record over UART feature to provide for 14-bit effective dynamic range in the captured recordings, which matches the dynamic range actually produced by the PDM to PCM conversion as implemented. check-in: 1d38441bbc user: rberteig tags: trunk
2015-03-10
22:54
Replaced subtracting average sample value with a simple single pole IIR high pass filter rolling off at 20Hz. Added mechanism for dumping scaled 8-bit PCM samples to the UART for analysis on the PC. Tested with recording of room audio. check-in: 5218c33e38 user: rberteig tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to LPCWorkspace/PDMSPL/src/main.c.

22
23
24
25
26
27
28

29
30
31
32
33
34
35
#include <string.h>
#include <stdlib.h>
#include "splear.h"
#include "iap.h"
#include "lg2.h"
#include "pwm.h"
#include "pdmspi.h"



/* Systick timer tick rate, to change duty cycle */
#define TICKRATE_HZ     1000		/* 1 ms Tick rate */

/*
 * SPL parameters







>







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <string.h>
#include <stdlib.h>
#include "splear.h"
#include "iap.h"
#include "lg2.h"
#include "pwm.h"
#include "pdmspi.h"
#include "mulaw.h"


/* Systick timer tick rate, to change duty cycle */
#define TICKRATE_HZ     1000		/* 1 ms Tick rate */

/*
 * SPL parameters
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
		//ssq += (pcm-avg)*(pcm-avg);
		sabs += pcm > 0 ? pcm : -pcm;

		// Finish SPL and apply it at each complete SPL window interval
		++n;
		if (monitor & PRINT_SAMPLES) {
			extern void putLineUARTn(const uint8_t *, size_t);
			int s =  (pcm + 8192) >> 6;

			//s = n & 0xff;

			sbuf[n & 63] = s <= 0 ? 0 : s >=255 ? 255 : s;
			if ((n&31) == 31)
				putLineUARTn(sbuf + (n & 32), 32);
		}
		if (n == WINDOWSIZE) {







|
|







210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
		//ssq += (pcm-avg)*(pcm-avg);
		sabs += pcm > 0 ? pcm : -pcm;

		// Finish SPL and apply it at each complete SPL window interval
		++n;
		if (monitor & PRINT_SAMPLES) {
			extern void putLineUARTn(const uint8_t *, size_t);
			//int s =  (pcm + 8192) >> 6;
			int s =  linear14_ulaw(pcm);
			//s = n & 0xff;

			sbuf[n & 63] = s <= 0 ? 0 : s >=255 ? 255 : s;
			if ((n&31) == 31)
				putLineUARTn(sbuf + (n & 32), 32);
		}
		if (n == WINDOWSIZE) {

Added LPCWorkspace/PDMSPL/src/mulaw.c.



































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * mulaw.c
 *
 *  Created on: Mar 13, 2015
 *      Author: Ross
 *
 * Good source for g711.c seems to be from pulseaudio sources where
 * they are deliberately starting with 14-bit samples. The referenced
 * page also has a complete lookup table set for doing both a-Law and
 * µ-Law to and from linear coding with lookup tables. 256 entries for
 * the decoder. 8K entries for aLaw encoder and 16K entries for µ-Law
 * encoder, so we won't be implementing the encoder with tables.
 *
 * https://fossies.org/linux/pulseaudio/src/pulsecore/g711.c
 */
#include <stdint.h>

#if (!defined(USE_TABLE_LOOKUP) || !defined(USE_CLZ_EMULATED))
#define USE_TABLE_LOOKUP
//#define USE_CLZ_EMULATED
#endif


#ifdef USE_TABLE_LOOKUP
/*
 * Table of thresholds for implementing count of leading zeros for computing
 * the segment number from the biased 14 bit sample value.
 */
static int16_t seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF};
static int16_t search(
		      int16_t        val,
		      int16_t *table,
		      int size)
{
    int i;

    for (i = 0; i < size; i++) {
	if (val <= *table++)
	    return (i);
    }
    return (size);
}
static unsigned int segment14(unsigned short x)
{
	return search(x, seg_uend, 8);
}

#else
#ifdef USE_CLZ_EMULATED
#if 0
static unsigned int clz32(unsigned int x)
{
	int n = 0;

    if (x = 0)
    	return 32;
    if (!(x & 0xFFFF0000)) { n += 16; x <<= 16; }
    if (!(x & 0xFF000000)) { n += 8; x <<= 8; }
    if (!(x & 0xF0000000)) { n += 4; x <<= 4; }
    if (!(x & 0xC0000000)) { n += 2; x <<= 2; }
    if (!(x & 0x80000000)) { n += 1; /*x <<= 1;*/ }
    return n;
}
#endif
static unsigned int clz16(unsigned short x)
{
	int n = 0;

    if (x = 0)
    	return 16;
    if (!(x & 0xFF00)) { n += 8; x <<= 8; }
    if (!(x & 0xF000)) { n += 4; x <<= 4; }
    if (!(x & 0xC000)) { n += 2; x <<= 2; }
    if (!(x & 0x8000)) { n += 1; /*x <<= 1;*/ }
    return n;
}
static unsigned int segment14(unsigned short x)
{
	int n = clz16(x);
	return n >= 10 ? 0 : 10-n;
#if 0
	int n = 0;

    //if (x = 0)    	return 0;
    if (!(x & 0xFE00)) { n += 4; x <<= 4; }
    if (!(x & 0xF800)) { n += 2; x <<= 2; }
    if (!(x & 0xF000)) { n += 1; /*x <<= 1;*/ }
    return 7-n;
#endif
}
#endif
#endif

#define        BIAS                (0x84)                /* Bias for linear code. */
#define CLIP            8159

/*
 * linear2ulaw() accepts a 14-bit signed integer and encodes it as u-law data
 * stored in a unsigned char.  This function should only be called with
 * the data shifted such that it only contains information in the lower
 * 14-bits.
 *
 * In order to simplify the encoding process, the original linear magnitude
 * is biased by adding 33 which shifts the encoding range from (0 - 8158) to
 * (33 - 8191). The result can be seen in the following encoding table:
 *
 *        Biased Linear Input Code        Compressed Code
 *        ------------------------        ---------------
 *        0 0000 001w xyza                        000wxyz
 *        0 0000 01wx yzab                        001wxyz
 *        0 0000 1wxy zabc                        010wxyz
 *        0 0001 wxyz abcd                        011wxyz
 *
 *        0 001w xyza bcde                        100wxyz
 *        0 01wx yzab cdef                        101wxyz
 *
 *        0 1wxy zabc defg                        110wxyz
 *        1 wxyz abcd efgh                        111wxyz
 *
 * Each biased linear code has a leading 1 which identifies the segment
 * number. The value of the segment number is equal to 7 minus the number
 * of leading 0's. The quantization interval is directly available as the
 * four bits wxyz.  * The trailing bits (a - h) are ignored.
 *
 * Ordinarily the complement of the resulting code word is used for
 * transmission, and so the code word is complemented before it is returned.
 *
 * For further information see John C. Bellamy's Digital Telephony, 1982,
 * John Wiley & Sons, pps 98-111 and 472-476.
 */
unsigned char linear14_ulaw(
			       int16_t                pcm_val)        /* 2's complement (14-bit range) */
{
    int16_t                mask;
    int16_t                seg;
    unsigned char        uval;

	/* Have calling software do it since its already doing a shift
         * from 32-bits down to 16-bits.
         */
	/* pcm_val = pcm_val >> 2; */

	/* u-law inverts all bits */
	/* Get the sign and the magnitude of the value. */
    if (pcm_val < 0) {
	pcm_val = -pcm_val;
	mask = 0x7F;
    } else {
	mask = 0xFF;
    }
    if ( pcm_val > CLIP ) pcm_val = CLIP;                /* clip the magnitude */
    pcm_val += (BIAS >> 2);

	/* Convert the scaled magnitude to segment number. */
    seg = segment14(pcm_val);
    //seg = search(pcm_val, seg_uend, 8);

	/*
         * Combine the sign, segment, quantization bits;
         * and complement the code word.
         */
    if (seg >= 8)                /* out of range, return maximum value. */
	return (unsigned char) (0x7F ^ mask);
    else {
	uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF);
	return (uval ^ mask);
    }

}

#ifdef TEST_CODE
#include <stdio.h>

int table()
{
	int x, y;
	printf("uint8_t _st_14linear2ulaw[0x4000] = {\n  ");
	y = 0;
	for (x = 0; x < 0x4000; x++)
	{
		printf(" 0x%02x,", linear14_ulaw((-0x2000)+x));
		y++;
		if (y == 12)
		{
			y = 0;
			printf("\n  ");
		}
	}
	printf("\n};\n");

}

int sample(void)
{
	 static unsigned int b[8] = {0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF};
	 int i;

	 for (i=0; i<8; ++i) {
		 printf("%4x  %02x    %4x %02x\n", b[i], linear14_ulaw(b[i]),  0x3fff & ((-0x2000)+b[i]), linear14_ulaw(b[i]-0x2000));
		 printf("%4x  %02x    %4x %02x\n", b[i]+1, linear14_ulaw(b[i]+1), 0x3fff & (b[i]+1-0x2000), linear14_ulaw(b[i]+1-0x2000));
	 }
}

int main(int argc, char **argv)
{
//	sample();
	table();
}
#endif

Added LPCWorkspace/PDMSPL/src/mulaw.h.





























>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
 * mulaw.h
 *
 *  Created on: Mar 16, 2015
 *      Author: Ross
 */

#ifndef MULAW_H_
#define MULAW_H_
#include <stdint.h>

unsigned char linear14_ulaw(int16_t pcm_val);        /* 2's complement (14-bit range) */

#endif /* MULAW_H_ */