Skip to content

tone() issue on SAMD51 cores #371

Open
@ZombieFodder

Description

@ZombieFodder

Hello, I am using an Adafruit ItsyBitsy M4 to generate a tone using
tone(7,25)
Note: I didn't post the entire code base because this micro is doing a lot of things and the sketch is too busy.

I expect this code should generate a 25Hz tone on pin 7, but instead I see a frequency around 64 times higher. I traced this down to some unhandled cases in the tone code.

while(ccValue > TONE_TC_TOP)
  {
    ccValue = toneMaxFrequency / frequency / (2<<i) - 1;
    i++;
    if(i == 4 || i == 6 || i == 8) //DIV32 DIV128 and DIV512 are not available
     i++;
  }
  
  switch(i-1)
  {
    case 0: prescalerConfigBits = TC_CTRLA_PRESCALER_DIV2; break;
    
    case 1: prescalerConfigBits = TC_CTRLA_PRESCALER_DIV4; break;
    
    case 2: prescalerConfigBits = TC_CTRLA_PRESCALER_DIV8; break;
    
    case 3: prescalerConfigBits = TC_CTRLA_PRESCALER_DIV16; break;
    
    case 5: prescalerConfigBits = TC_CTRLA_PRESCALER_DIV64; break;
      
    case 7: prescalerConfigBits = TC_CTRLA_PRESCALER_DIV256; break;
    
    case 9: prescalerConfigBits = TC_CTRLA_PRESCALER_DIV1024; break;
    
    default: break;
  }

Adding case 8 to 7, 6 to 5 and 4 to 3 seems to resolve the issue. This seems to be a result of the if statement in the while loop adding an extra ++ when the proper prescaler is adjacent to one of the missing ones. The -1 in the switch then puts you in the default case (while generates a "9" then switch looks for a "8"). It should be possible to re-create this issue to confirm my code works as a fix and is accurate across a large range of frequencies...

switch(i-1)
 {
   case 0: prescalerConfigBits = TC_CTRLA_PRESCALER_DIV2; break;
   
   case 1: prescalerConfigBits = TC_CTRLA_PRESCALER_DIV4; break;
   
   case 2: prescalerConfigBits = TC_CTRLA_PRESCALER_DIV8; break;
   
   case 3: case 4: prescalerConfigBits = TC_CTRLA_PRESCALER_DIV16; break;
   
   case 5: case 6: prescalerConfigBits = TC_CTRLA_PRESCALER_DIV64; break;
     
   case 7: case 8: prescalerConfigBits = TC_CTRLA_PRESCALER_DIV256; break;
   
   case 9: prescalerConfigBits = TC_CTRLA_PRESCALER_DIV1024; break;
   
   default: break;
 }

I request you consider this or another fix for the next release of the Arduino cores for the SAMD51 (or 21) devices. Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions