Check-in [957d720ccc]

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

Overview
Comment:Merged packet recording and adjustable threshold features to trunk for today's blog post.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 957d720ccc643f30beca9e27f0584aff5d93e62b
User & Date: rberteig 2015-07-01 23:14:17
Context
2015-07-02
22:05
Added notes on FlashMagic configuration to the LPC project's documentation. Leaf check-in: 5aebb7287d user: rberteig tags: trunk
2015-07-01
23:14
Merged packet recording and adjustable threshold features to trunk for today's blog post. check-in: 957d720ccc user: rberteig tags: trunk
21:06
Add the q command to set the EEK threshold used for e mode and GPIO13 pulsing. Clean up some leftover unused code from the packet mode development. Leaf check-in: 38353e8e2f user: rberteig tags: packets
2015-06-25
21:36
Change scared delta SPL threshold to 12dB from 6dB. check-in: dd66d0e331 user: rberteig tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Added LPCWorkspace/PDMSPL/src/crc8.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
/*
 * crc8.c
 *
 * 8 bit CRC, choice of polynomial at compile time.
 *
 * Candidate polynomials documented here are chosen according
 * to Table 3 in Koopman et al 2004.
 *
 * HD  Poly   Fwd    Rev    Covers
 * --  -----  ----   ----   ------
 *  2  0x14D  0xA6   0xB2    2048+
 *  3  0x14D  0xA6   0xB2     247
 *  4  0x12F  0x97   0xF4     119
 *  5  0x139  0x9C   0x9C       9
 *                           Number of message bits covered at HD
 *                   Reversed poly for table gen
 *            Koopman form poly with implicit 1 shifted off
 *     Complete polynomial, 1 more bit than CRC length
 * Hamming Distance detected all errors
 *
 * Modeled after the table-driven code given in this answer at Stack Overflow:
 *   http://stackoverflow.com/a/15171925/68204
 * with cosmetic tweaks for use with the table in ROM for this project.
 *
 */

#define FPOLY 0x97
#define RPOLY 0xF4


#ifdef STANDALONE
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#endif
#include "splear.h"
#include "stddef.h"


/* Table for CRC polynomial 0x12F, generated by -DSTANDALONE */
/* Compare FPOLY to 0x97 */
/* Compare RPOLY to 0xf4 */
static const uint8_t crc8_table[256] = {
    0x00, 0xc7, 0x67, 0xa0, 0xce, 0x09, 0xa9, 0x6e, 0x75, 0xb2, 0x12, 0xd5,
    0xbb, 0x7c, 0xdc, 0x1b, 0xea, 0x2d, 0x8d, 0x4a, 0x24, 0xe3, 0x43, 0x84,
    0x9f, 0x58, 0xf8, 0x3f, 0x51, 0x96, 0x36, 0xf1, 0x3d, 0xfa, 0x5a, 0x9d,
    0xf3, 0x34, 0x94, 0x53, 0x48, 0x8f, 0x2f, 0xe8, 0x86, 0x41, 0xe1, 0x26,
    0xd7, 0x10, 0xb0, 0x77, 0x19, 0xde, 0x7e, 0xb9, 0xa2, 0x65, 0xc5, 0x02,
    0x6c, 0xab, 0x0b, 0xcc, 0x7a, 0xbd, 0x1d, 0xda, 0xb4, 0x73, 0xd3, 0x14,
    0x0f, 0xc8, 0x68, 0xaf, 0xc1, 0x06, 0xa6, 0x61, 0x90, 0x57, 0xf7, 0x30,
    0x5e, 0x99, 0x39, 0xfe, 0xe5, 0x22, 0x82, 0x45, 0x2b, 0xec, 0x4c, 0x8b,
    0x47, 0x80, 0x20, 0xe7, 0x89, 0x4e, 0xee, 0x29, 0x32, 0xf5, 0x55, 0x92,
    0xfc, 0x3b, 0x9b, 0x5c, 0xad, 0x6a, 0xca, 0x0d, 0x63, 0xa4, 0x04, 0xc3,
    0xd8, 0x1f, 0xbf, 0x78, 0x16, 0xd1, 0x71, 0xb6, 0xf4, 0x33, 0x93, 0x54,
    0x3a, 0xfd, 0x5d, 0x9a, 0x81, 0x46, 0xe6, 0x21, 0x4f, 0x88, 0x28, 0xef,
    0x1e, 0xd9, 0x79, 0xbe, 0xd0, 0x17, 0xb7, 0x70, 0x6b, 0xac, 0x0c, 0xcb,
    0xa5, 0x62, 0xc2, 0x05, 0xc9, 0x0e, 0xae, 0x69, 0x07, 0xc0, 0x60, 0xa7,
    0xbc, 0x7b, 0xdb, 0x1c, 0x72, 0xb5, 0x15, 0xd2, 0x23, 0xe4, 0x44, 0x83,
    0xed, 0x2a, 0x8a, 0x4d, 0x56, 0x91, 0x31, 0xf6, 0x98, 0x5f, 0xff, 0x38,
    0x8e, 0x49, 0xe9, 0x2e, 0x40, 0x87, 0x27, 0xe0, 0xfb, 0x3c, 0x9c, 0x5b,
    0x35, 0xf2, 0x52, 0x95, 0x64, 0xa3, 0x03, 0xc4, 0xaa, 0x6d, 0xcd, 0x0a,
    0x11, 0xd6, 0x76, 0xb1, 0xdf, 0x18, 0xb8, 0x7f, 0xb3, 0x74, 0xd4, 0x13,
    0x7d, 0xba, 0x1a, 0xdd, 0xc6, 0x01, 0xa1, 0x66, 0x08, 0xcf, 0x6f, 0xa8,
    0x59, 0x9e, 0x3e, 0xf9, 0x97, 0x50, 0xf0, 0x37, 0x2c, 0xeb, 0x4b, 0x8c,
    0xe2, 0x25, 0x85, 0x42,
};

uint8_t crc8(uint8_t crc, const void *data_, size_t len)
{
	const uint8_t *data = (const uint8_t *)data_;
    const uint8_t *end;

    if (len == 0)
        return crc;
    crc ^= 0xff;
    end = data + len;
    do {
        crc = crc8_table[crc ^ *data++];
    } while (data < end);
    return crc ^ 0xff;
}


#ifdef STANDALONE

uint8_t crc8_slow(uint8_t crc, uint8_t *data, size_t len)
{
    uint8_t *end;

    if (len == 0)
        return crc;
    crc ^= 0xff;
    end = data + len;
    do {
        crc ^= *data++;
        crc = crc & 1 ? (crc >> 1) ^ RPOLY : crc >> 1;
        crc = crc & 1 ? (crc >> 1) ^ RPOLY : crc >> 1;
        crc = crc & 1 ? (crc >> 1) ^ RPOLY : crc >> 1;
        crc = crc & 1 ? (crc >> 1) ^ RPOLY : crc >> 1;
        crc = crc & 1 ? (crc >> 1) ^ RPOLY : crc >> 1;
        crc = crc & 1 ? (crc >> 1) ^ RPOLY : crc >> 1;
        crc = crc & 1 ? (crc >> 1) ^ RPOLY : crc >> 1;
        crc = crc & 1 ? (crc >> 1) ^ RPOLY : crc >> 1;
    } while (data < end);
    return crc ^ 0xff;
}

void samples(void)
{
	char *samples[] = {
			" ",
			"Hello, world.",
			"0123456789",
			"1123456789",
			NULL,
	};
	int n;

	for (n=0; samples[n]; ++n) {
		uint8_t crct, crcs;
		crct = crc8(0, samples[n], strlen(samples[n]));
		crcs = crc8_slow(0, samples[n], strlen(samples[n]));
		printf("%02X %02X '%s'\n", crct, crcs, samples[n]);
	}
}

int main(int argc, char **argv)
{
	unsigned i,n;
	uint8_t c, crc;

	printf("/* Table for CRC polynomial 0x%X, generated by -DSTANDALONE */\n", (FPOLY<<1)|1);
	printf("/* Compare FPOLY to 0x%02x */\n", FPOLY);
	printf("/* Compare RPOLY to 0x%02x */\n", RPOLY);
	printf("static const uint8_t crc8_table[256] = {");
	for (i=0,n=0; i<256; ++i) {
		c = i;
		crc = 0xff^crc8_slow(0xff, &c, 1);
		if (n==0) printf("\n    ");
		printf("0x%02x, ", crc);
		if (++n == 12) n=0;
	}
	printf("\n};\n");
	samples();
}

#endif

Added LPCWorkspace/PDMSPL/src/crc8.h.

























>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
/*
 * crc8.h
 *
 * Implement 8 bit CRC polynomial.
 */

#ifndef CRC8_H_
#define CRC8_H_

uint8_t crc8(uint8_t crc, const void *data, size_t len);

#endif /* CRC8_H_ */

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

23
24
25
26
27
28
29

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

extern void initUART(void);

#define EEK_PIN HW_P13
#define EEK_DELTA 16 // equivalent to 12 dB SPL

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







>







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <stdlib.h>
#include "splear.h"
#include "iap.h"
#include "lg2.h"
#include "pwm.h"
#include "pdmspi.h"
#include "mulaw.h"
#include "crc8.h"
extern void initUART(void);

#define EEK_PIN HW_P13
#define EEK_DELTA 16 // equivalent to 12 dB SPL

/* Systick timer tick rate, to change duty cycle */
#define TICKRATE_HZ     1000		/* 1 ms Tick rate */
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
}

#define PRINT_NOTHING          0
#define PRINT_MONITOR_SPL      1
#define PRINT_SCARED           2
#define PRINT_SAMPLES          4
#define PRINT_MONITOR_SPL_ALL  5


volatile int monitor = PRINT_MONITOR_SPL; //PRINT_SCARED;






































void modecheck(void)
{
	extern int ugetchar(void); // like getchar() but straight in to uartglue.c
	int c;

	c = ugetchar();
	if (c < 0) return;
	switch(c) {

	default:




	case 's': monitor = PRINT_MONITOR_SPL; break;
	case 'S': monitor = PRINT_MONITOR_SPL_ALL; break;
	case 'e': monitor = PRINT_SCARED; break;




















	case 'R': monitor = PRINT_SAMPLES; break;




	case 'n': monitor = PRINT_NOTHING; break;



	case 'V':
		introspect();
		break;

	case '?': case '/':
		printf("SPLear prints:\r\n");
		printf(" s:  peak+SPL at 0.5 Hz\r\n");
		printf(" S:  SPL 10 Hz\r\n");
		printf(" e:  Eek!\r\n");
		printf(" n:  no printing\r\n");

		printf(" R:  muLaw at 8152 Hz\r\n");



		break;
	}
}



/**
 * @brief  Main Loop
 * @return Does not return.
 */
int main(void) {
	uint8_t pcount = WINDOWSPERPRINT;
	uint32_t n = 0;
	uint32_t sabs = 0;
	int32_t sum = 0;
	int32_t sum2 = 0;
	int avg = 0;
	int spl = 0;
	int peak = 0;
	int last = 0;
	static uint8_t sbuf[64];
	uint16_t servoupdate = SERVORATE;

#if defined (__USE_LPCOPEN)
#if !defined(NO_BOARD_LIB)
    // Read clock settings and update SystemCoreClock variable
    SystemCoreClockUpdate();
    // Set up and initialize all required blocks and







>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|




>

>
>
>
>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>



>

|
<
<
|

>

>
>
>



>
>















<







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
}

#define PRINT_NOTHING          0
#define PRINT_MONITOR_SPL      1
#define PRINT_SCARED           2
#define PRINT_SAMPLES          4
#define PRINT_MONITOR_SPL_ALL  5
#define PRINT_MONITOR_PACKETS  6

volatile int monitor = PRINT_MONITOR_SPL; //PRINT_SCARED;

extern void putBufUARTn(const uint8_t *, size_t);
uint8_t record_ok = 0;
uint8_t eek_delta = EEK_DELTA;

void deliver(uint8_t s)
{
	if (record_ok)
		putBufUARTn(&s, 1);
}

void deliverPkt(int spl)
{
	struct {
	    uint8_t headmagic;  // 'A'
	    uint8_t SPL;        // scaled log2 SPL of previous packet
	    uint8_t N_hi;       // count of audio bytes
	    uint8_t N_lo;       //   ...
	    uint8_t flags;      // TBD
	    uint8_t crc;        // CRC of five  previous bytes
	} hdr;
	hdr.headmagic = 'A';
	hdr.SPL = spl <= 0 ? 0 : spl >=255 ? 255 : spl;
	hdr.N_hi = WINDOWSIZE >> 8;
	hdr.N_lo = WINDOWSIZE & 0xff;
	hdr.flags = 0;
	hdr.crc = crc8(0, &hdr, 5);
	putBufUARTn(&hdr.headmagic, 6);
	record_ok = 1;
}

char delta2char(delta)
{
	return delta <= 9 ? '0'+delta :
			delta <= 35 ? 'a'+delta-10 :
					'A'+delta-36;
}

void modecheck(void)
{
	extern int ugetchar(void); // like getchar() but straight in to uartglue.c
	int c,n;

	c = ugetchar();
	if (c < 0) return;
	switch(c) {

	default:
		/* silently ignore unrecognized characters */
		break;

	case ' ':
	case 's': monitor = PRINT_MONITOR_SPL; break;
	case 'S': monitor = PRINT_MONITOR_SPL_ALL; break;
	case 'e': monitor = PRINT_SCARED; break;
	case 'n': monitor = PRINT_NOTHING; break;

	case 'q':
		n = 0;
		while ((c = ugetchar()) < 0) {
			if (++n > 100000) {
				c = 0;
				break;
			}
		}
		if (c>='0' && c<='9')
			eek_delta = c - '0';
		else if (c>='a' && c<='z')
			eek_delta = c - 'a' + 10;
		else if (c>='A' && c<='Z')
			eek_delta = c - 'A' + 36;
		printf("Set Eek delta %d '%c'\r\n", eek_delta, delta2char(eek_delta));
		break;

	case 'R':
		monitor = PRINT_SAMPLES;
		record_ok = 1;
		break;

	case 'P':
		monitor = PRINT_MONITOR_PACKETS;
		record_ok = 0;
		break;

	case 'V':
		introspect();
		break;

	case '?': case '/':
		printf("SPLear print modes:\r\n");


		printf(" e:  Eek!  (%d '%c')\r\n", eek_delta, delta2char(eek_delta));
		printf(" n:  no printing\r\n");
		printf(" P:  muLaw at 8152 Hz in packets\r\n");
		printf(" R:  muLaw at 8152 Hz\r\n");
		printf(" s:  peak+SPL at 0.5 Hz\r\n");
		printf(" S:  SPL 10 Hz\r\n");
		printf(" V:  Display SPLear unique ID.\r\n");
		break;
	}
}



/**
 * @brief  Main Loop
 * @return Does not return.
 */
int main(void) {
	uint8_t pcount = WINDOWSPERPRINT;
	uint32_t n = 0;
	uint32_t sabs = 0;
	int32_t sum = 0;
	int32_t sum2 = 0;
	int avg = 0;
	int spl = 0;
	int peak = 0;
	int last = 0;

	uint16_t servoupdate = SERVORATE;

#if defined (__USE_LPCOPEN)
#if !defined(NO_BOARD_LIB)
    // Read clock settings and update SystemCoreClock variable
    SystemCoreClockUpdate();
    // Set up and initialize all required blocks and
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

    	// accumulate PCM and |PCM| to compute DC offset and SPL
		sum2 += pcm;
		sabs += pcm > 0 ? pcm : -pcm;

		// Finish SPL and apply it at each complete SPL window interval
		++n;
		if (monitor == PRINT_SAMPLES) {
			// This mode is effectively a muLaw audio recorder.
			extern void putBufUARTn(const uint8_t *, size_t);
			int s =  linear14_ulaw(pcm);
			sbuf[n & 63] = s <= 0 ? 0 : s >=255 ? 255 : s;
			if ((n&31) == 31)
				putBufUARTn(sbuf + (n & 32), 32);
		}
		if (n == WINDOWSIZE) {
			int avg2;

			// Compute the SPL over the window that just finished.
			spl = (lg2(sabs) - LG2WINDOWSIZE);

			// set the PWM
#if (defined(BOARD_NXP_LPCXPRESSO_812) || defined(BOARD_LPC812MAX))
			pwmSet_LED(MAXLG2SPL-spl,MAXLG2SPL);
#else
			pwmSet_LED(spl-30,MAXLG2SPL-30);
#endif
			pwmSet_OUT(spl,MAXLG2SPL);

			// track peak level
			if (peak < spl) { peak = spl; }

			// jump on large change
			if (last && last < spl && spl - last >= EEK_DELTA) {
#ifdef EEK_PIN
				Chip_GPIO_SetPinState(LPC_GPIO_PORT, 0, EEK_PIN, TRUE);
#endif
				if (monitor == PRINT_SCARED)
					printf("Eek! %d, %d, %d\r\n", spl, last, peak);
			}
#ifdef EEK_PIN







|

|

|
<
<



















|







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

    	// accumulate PCM and |PCM| to compute DC offset and SPL
		sum2 += pcm;
		sabs += pcm > 0 ? pcm : -pcm;

		// Finish SPL and apply it at each complete SPL window interval
		++n;
		if ((monitor == PRINT_SAMPLES) || (monitor == PRINT_MONITOR_PACKETS)) {
			// This mode is effectively a muLaw audio recorder.
			// int s = (s <= 0) ? 0 : (s >=255) ? 255 : s;
			int s =  linear14_ulaw(pcm);
			deliver(s);


		}
		if (n == WINDOWSIZE) {
			int avg2;

			// Compute the SPL over the window that just finished.
			spl = (lg2(sabs) - LG2WINDOWSIZE);

			// set the PWM
#if (defined(BOARD_NXP_LPCXPRESSO_812) || defined(BOARD_LPC812MAX))
			pwmSet_LED(MAXLG2SPL-spl,MAXLG2SPL);
#else
			pwmSet_LED(spl-30,MAXLG2SPL-30);
#endif
			pwmSet_OUT(spl,MAXLG2SPL);

			// track peak level
			if (peak < spl) { peak = spl; }

			// jump on large change
			if (last && last < spl && spl - last >= eek_delta) {
#ifdef EEK_PIN
				Chip_GPIO_SetPinState(LPC_GPIO_PORT, 0, EEK_PIN, TRUE);
#endif
				if (monitor == PRINT_SCARED)
					printf("Eek! %d, %d, %d\r\n", spl, last, peak);
			}
#ifdef EEK_PIN
324
325
326
327
328
329
330


331
332
333
334
335
336
337
				pcount = WINDOWSPERPRINT;
				if (monitor == PRINT_MONITOR_SPL)
					printf("%d %d %d %d\r\n", peak, spl, avg, avg2);
				peak = 0;
			}
			if (monitor == PRINT_MONITOR_SPL_ALL)
				printf("%d\r\n", spl);



			// reset accumulators and counters for the next iteration
			sum = 0;
			sum2 = 0;
			sabs = 0;
			n = 0;
		}







>
>







397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
				pcount = WINDOWSPERPRINT;
				if (monitor == PRINT_MONITOR_SPL)
					printf("%d %d %d %d\r\n", peak, spl, avg, avg2);
				peak = 0;
			}
			if (monitor == PRINT_MONITOR_SPL_ALL)
				printf("%d\r\n", spl);
			if (monitor == PRINT_MONITOR_PACKETS)
				deliverPkt(spl);

			// reset accumulators and counters for the next iteration
			sum = 0;
			sum2 = 0;
			sabs = 0;
			n = 0;
		}

Added Scared/crc8.lua.





















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
-- CRC8 for use with SPLear

local M = {}

local ok,bit = pcall(require, "bit32")
if not ok then bit = require "bit" end

local band,bor,bxor = bit.band,bit.bor,bit.bxor

--[===[
  8-bit CRC with polynomial x^8+x^5+x^3+x^2+x+1, 0x12F.
  Table for CRC polynomial 0x12F, generated by -DSTANDALONE
  Compare FPOLY to 0x97 
  Compare RPOLY to 0xf4 
--]===]
local crc8_table = { [0]=
    0x00, 0xc7, 0x67, 0xa0, 0xce, 0x09, 0xa9, 0x6e, 0x75, 0xb2, 0x12, 0xd5,
    0xbb, 0x7c, 0xdc, 0x1b, 0xea, 0x2d, 0x8d, 0x4a, 0x24, 0xe3, 0x43, 0x84,
    0x9f, 0x58, 0xf8, 0x3f, 0x51, 0x96, 0x36, 0xf1, 0x3d, 0xfa, 0x5a, 0x9d,
    0xf3, 0x34, 0x94, 0x53, 0x48, 0x8f, 0x2f, 0xe8, 0x86, 0x41, 0xe1, 0x26,
    0xd7, 0x10, 0xb0, 0x77, 0x19, 0xde, 0x7e, 0xb9, 0xa2, 0x65, 0xc5, 0x02,
    0x6c, 0xab, 0x0b, 0xcc, 0x7a, 0xbd, 0x1d, 0xda, 0xb4, 0x73, 0xd3, 0x14,
    0x0f, 0xc8, 0x68, 0xaf, 0xc1, 0x06, 0xa6, 0x61, 0x90, 0x57, 0xf7, 0x30,
    0x5e, 0x99, 0x39, 0xfe, 0xe5, 0x22, 0x82, 0x45, 0x2b, 0xec, 0x4c, 0x8b,
    0x47, 0x80, 0x20, 0xe7, 0x89, 0x4e, 0xee, 0x29, 0x32, 0xf5, 0x55, 0x92,
    0xfc, 0x3b, 0x9b, 0x5c, 0xad, 0x6a, 0xca, 0x0d, 0x63, 0xa4, 0x04, 0xc3,
    0xd8, 0x1f, 0xbf, 0x78, 0x16, 0xd1, 0x71, 0xb6, 0xf4, 0x33, 0x93, 0x54,
    0x3a, 0xfd, 0x5d, 0x9a, 0x81, 0x46, 0xe6, 0x21, 0x4f, 0x88, 0x28, 0xef,
    0x1e, 0xd9, 0x79, 0xbe, 0xd0, 0x17, 0xb7, 0x70, 0x6b, 0xac, 0x0c, 0xcb,
    0xa5, 0x62, 0xc2, 0x05, 0xc9, 0x0e, 0xae, 0x69, 0x07, 0xc0, 0x60, 0xa7,
    0xbc, 0x7b, 0xdb, 0x1c, 0x72, 0xb5, 0x15, 0xd2, 0x23, 0xe4, 0x44, 0x83,
    0xed, 0x2a, 0x8a, 0x4d, 0x56, 0x91, 0x31, 0xf6, 0x98, 0x5f, 0xff, 0x38,
    0x8e, 0x49, 0xe9, 0x2e, 0x40, 0x87, 0x27, 0xe0, 0xfb, 0x3c, 0x9c, 0x5b,
    0x35, 0xf2, 0x52, 0x95, 0x64, 0xa3, 0x03, 0xc4, 0xaa, 0x6d, 0xcd, 0x0a,
    0x11, 0xd6, 0x76, 0xb1, 0xdf, 0x18, 0xb8, 0x7f, 0xb3, 0x74, 0xd4, 0x13,
    0x7d, 0xba, 0x1a, 0xdd, 0xc6, 0x01, 0xa1, 0x66, 0x08, 0xcf, 0x6f, 0xa8,
    0x59, 0x9e, 0x3e, 0xf9, 0x97, 0x50, 0xf0, 0x37, 0x2c, 0xeb, 0x4b, 0x8c,
    0xe2, 0x25, 0x85, 0x42,
}

local function crc8(crc, data)
  if data == nil then
    crc,data = 0, crc
  end
  if #data == 0 then 
    return crc
  end
  crc = bxor(crc, 0xff)
  for i=1,#data do
    local b = data:byte(i)
    crc = crc8_table[bxor(crc, b)];
  end
  return bxor(crc,0xff)
end

local function crc_generic(crc, poly, data)
  if data == nil and poly == nil then
    -- allow for simple call with a string and default initial CRC and polynomial
    crc,poly,data = 0, 0xB2, crc
  end
  assert(crc and poly and data)
  if #data == 0 then 
    return sum
  end
  crc = bxor(crc, 0xff)
  for i=1,#data do
    local b = data:byte(i)
    --crc = crc8_table[bit.bxor(crc, b)];
    crc = bxor(crc, b)
    for j=1,8 do 
      crc = band(crc, 1) == 1 and bxor(rshift(crc,1), poly) or rshift(crc,1)
    end
  end
  return bit.bxor(crc,0xff)
end


local function sum8(sum, data)
  if data == nil then
    sum,data = 0, sum
  end
  if #data == 0 then 
    return sum
  end
  for i=1,#data do
    local b = data:byte(i)
    sum = sum + b
  end
  return bit.band(sum,0xff)
end

local function revpoly(p)
  p = bor(bit.lshift(p,1), 1)
  local r = 0
  repeat 
    r = bor(bit.lshift(r,1),band(p,1))
    p = bit.rshift(p,1)
  until p == 0
  return bit.rshift(r,1)
end


local function crc_filltable(poly)
  poly = revpoly(poly)
  for i=0,255 do
    crc8_table[i] = bxor(0xff, crc_generic(0xff, poly, string.char(i)))
  end
end


M.crc8_table = crc8_table
M.crc8 = crc8
M.sum8 = sum8
M.sumc8 = function(sum,data) 
  sum = bit.band(-sum8(sum,data),0xff)
  return sum
end

M.generic = crc_generic
M.filltable = crc_filltable

return M

Added Scared/testcrc.lua.



































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
crc = require "crc8"

function checkstring(s,f)
  f = f or crc.crc8
  if not s or #s <= 1 then return false end
  local c = s:byte(#s)
  local c2 = f(0, s, #s-1)
  
  return c2 == c
end


function randstring(n)
  if n <= 1 then return nil end
  local t = {}
  for i=1,n-1 do
    t[i] = math.random(256)-1
  end
  local s = string.char(unpack(t))
  return s
end

function sample(L,N,...)
  local f = {...}
  local ok = {}
  
  if #f == 0 then
    f[1] = crc.crc8
  end
  for i = 1, #f do 
    ok[i] = 0 
  end
  for i=1,N do
    local s = randstring(L)
    for j=1,#f do
      if checkstring(s,f[j]) then 
        ok[j] = ok[j] + 1
      end
    end
  end
  return unpack(ok)
end

local N = 100000
for len=2,32 do 
  local ok,oks,okc = sample(len, N, crc.crc8, crc.sum8, crc.sumc8)
  print(len, ("%.3f%%  %.3f%%  %.3f%%"):format(100*ok/N, 100*oks/N, 100*okc/N))
end