@@ -313,6 +313,133 @@ int MCP2515Class::filter(int id, int mask)
313313 return 1 ;
314314}
315315
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+
316443int MCP2515Class::filterExtended (long id, long mask)
317444{
318445 id &= 0x1FFFFFFF ;
0 commit comments