@@ -313,6 +313,133 @@ int MCP2515Class::filter(int id, int mask)
313
313
return 1 ;
314
314
}
315
315
316
+ unsigned char hammingDistance (int x, int y)
317
+ {
318
+ unsigned char distance = 0 ;
319
+ int xorXY = x ^ y;
320
+
321
+ for (int i = 0 ; i < 8 * sizeof (int ); i++) {
322
+ if (xorXY & (1 << i))
323
+ distance++;
324
+ }
325
+
326
+ return distance;
327
+ }
328
+
329
+ int MCP2515Class::multiFilter (int *ids, unsigned count)
330
+ {
331
+ long filterMasks[2 ];
332
+ long filterIds[6 ];
333
+
334
+ if (count <= 6 ) {
335
+ // the MCP2515 has enough registers to filter all ids
336
+ for (int n = 0 ; n < 2 ; n++)
337
+ filterMasks[n] = 0x7ff ;
338
+
339
+ for (int n = 0 ; n < 6 ; n++) {
340
+ if (n < count)
341
+ filterIds[n] = ids[n];
342
+ else
343
+ filterIds[n] = 0 ;
344
+ }
345
+ }
346
+ else {
347
+ // we have more ids than filters, we find the two most distant ids and use
348
+ // them as base for anding together all other ids
349
+ unsigned char maxDistance = 0 ;
350
+
351
+ for (int i = 0 ; i < count; i++) {
352
+ for (int j = i; j < count; j++) {
353
+ unsigned char distance = hammingDistance (ids[i], ids[j]);
354
+
355
+ if (distance > maxDistance) {
356
+ filterIds[0 ] = ids[i];
357
+ filterIds[2 ] = ids[j];
358
+ maxDistance = distance;
359
+ }
360
+ }
361
+ }
362
+
363
+ filterMasks[0 ] = 0x7ff ;
364
+ filterMasks[1 ] = 0x7ff ;
365
+ filterIds[1 ] = 0 ;
366
+ filterIds[3 ] = 0 ;
367
+ filterIds[4 ] = 0 ;
368
+ filterIds[5 ] = 0 ;
369
+
370
+ for (int i = 0 ; i < count; i++) {
371
+ unsigned char distance0 = hammingDistance (ids[i], filterMasks[0 ]);
372
+ unsigned char distance1 = hammingDistance (ids[i], filterMasks[1 ]);
373
+
374
+ #if 0
375
+ Serial.print("id ");
376
+ Serial.print(ids[i]);
377
+ Serial.print(" distance0: ");
378
+ Serial.print(distance0);
379
+ Serial.print(" distance1: ");
380
+ Serial.print(distance1);
381
+ Serial.println();
382
+ #endif
383
+
384
+ if (distance0 < distance1) {
385
+ filterMasks[0 ] = filterMasks[0 ] & ~(filterIds[0 ] ^ ids[i]);
386
+ filterIds[0 ] &= ids[i];
387
+ }
388
+ else {
389
+ filterMasks[1 ] = filterMasks[1 ] & ~(filterIds[2 ] ^ ids[i]);
390
+ filterIds[2 ] &= ids[i];
391
+ }
392
+ }
393
+
394
+ #if 0
395
+ Serial.print("filterMasks[0] = ");
396
+ Serial.print(filterMasks[0], 16);
397
+ Serial.print(" filterIds[0] = ");
398
+ Serial.println(filterIds[0], 16);
399
+
400
+ Serial.print("filterMasks[1] = ");
401
+ Serial.print(filterMasks[1], 16);
402
+ Serial.print(" filterIds[2] = ");
403
+ Serial.println(filterIds[2], 16);
404
+ #endif
405
+ }
406
+
407
+
408
+
409
+ // config mode
410
+ writeRegister (REG_CANCTRL, 0x80 );
411
+ if (readRegister (REG_CANCTRL) != 0x80 ) {
412
+ return 0 ;
413
+ }
414
+
415
+ for (int n = 0 ; n < 2 ; n++) {
416
+ // for now standard only (TODO: extended)
417
+ writeRegister (REG_RXBnCTRL (n), FLAG_RXM0);
418
+ writeRegister (REG_RXBnCTRL (n), FLAG_RXM0);
419
+
420
+ writeRegister (REG_RXMnSIDH (n), filterMasks[n] >> 3 );
421
+ writeRegister (REG_RXMnSIDL (n), filterMasks[n] << 5 );
422
+ writeRegister (REG_RXMnEID8 (n), 0 );
423
+ writeRegister (REG_RXMnEID0 (n), 0 );
424
+ }
425
+
426
+ for (int n = 0 ; n < 6 ; n++) {
427
+ writeRegister (REG_RXFnSIDH (n), filterIds[n] >> 3 );
428
+ writeRegister (REG_RXFnSIDL (n), filterIds[n] << 5 );
429
+
430
+ writeRegister (REG_RXFnEID8 (n), 0 );
431
+ writeRegister (REG_RXFnEID0 (n), 0 );
432
+ }
433
+
434
+ // normal mode
435
+ writeRegister (REG_CANCTRL, 0x00 );
436
+ if (readRegister (REG_CANCTRL) != 0x00 ) {
437
+ return 0 ;
438
+ }
439
+
440
+ return 1 ;
441
+ }
442
+
316
443
int MCP2515Class::filterExtended (long id, long mask)
317
444
{
318
445
id &= 0x1FFFFFFF ;
0 commit comments