SSブログ

ATtiny202 正弦波のノイズ問題 TCAで解決! [Arduino]

ATtiny202 正弦波のノイズ問題が解決できました。
Timer/Counter Type A (TCA) は megaTinyCore のデフォルトで millis()/micros() に使われていたため、今まで手を出さなかったのですが、TCBにはない、PERにバッファーが付いた PERBUF や、CMPnにバッファーが付いた CMPnBUF を使わないとなんともならないようでした。

そこで、以下のサンプルプログラムとデータシートを見ながら作ってみました。

Getting Started with TCA
https://www.microchip.com/content/dam/mchp/documents/MCU08/ApplicationNotes/ApplicationNotes/TB3217-Getting-Started-with-TCA-DS90003217.pdf

cmp0buf.png

★はまったところ
はまったところは、megaTinyCore特有のところでした。
・PORTMUXの代替ピンが使用されていた
   PA3 (megaTinyCore 4番ピン) → PA7 (megaTinyCore 1番ピン)
・TCAの Split Mode が使用されていた
   いくら PERBUF や CMP0BUF を変更しても値が変わらない、、
   なぜなら、Split Mode にはこれらがないから。
   TCA0.SINGLE.CTRLD = 0; でSplit Mode から Normal Mode に戻す必要があった。
   この設定は 「millis()/micros() Timer;"Disabled(save flash)"」にしても有効。
   megaTinyCoreでmillis()/micros()は使わないけど、PWMには使うから。

megaTinyCore_megaavr_extras_TakingOverTCA0.md at master · SpenceKonde_megaTinyCore · GitHub
https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/TakingOverTCA0.md

以下、スケッチ。millis()/micros() の割り込みは解除してあります。

//  megaTinyCore(mTC) ATtiny202/212/402/412 Sine Wave with TCA
#include <avr/io.h>
#include <util/delay.h>

static const uint16_t OCTAVE9[] = { 7023, 7441, 7883, 8352, 8848, 9375, 9932, 10523,11148,11811,12513,13258 };
static const uint8_t  SINE256[] = {
    0,  0,  0,  0,  1,  1,  1,  2,  2,  3,  4,  5,  5,  6,  7,  9,  10, 11, 12, 14, 15, 17, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35,
   37, 40, 42, 44, 47, 49, 52, 54, 57, 59, 62, 65, 67, 70, 73, 76,  79, 82, 85, 88, 90, 93, 97,100,103,106,109,112,115,118,121,124,
  128,131,134,137,140,143,146,149,152,155,158,162,165,167,170,173, 176,179,182,185,188,190,193,196,198,201,203,206,208,211,213,215,
  218,220,222,224,226,228,230,232,234,235,237,238,240,241,243,244, 245,246,248,249,250,250,251,252,253,253,254,254,254,255,255,255,
  255,255,255,255,254,254,254,253,253,252,251,250,250,249,248,246, 245,244,243,241,240,238,237,235,234,232,230,228,226,224,222,220,
  218,215,213,211,208,206,203,201,198,196,193,190,188,185,182,179, 176,173,170,167,165,162,158,155,152,149,146,143,140,137,134,131,
  128,124,121,118,115,112,109,106,103,100, 97, 93, 90, 88, 85, 82,  79, 76, 73, 70, 67, 65, 62, 59, 57, 54, 52, 49, 47, 44, 42, 40,
   37, 35, 33, 31, 29, 27, 25, 23, 21, 20, 18, 17, 15, 14, 12, 11,  10,  9,  7,  6,  5,  5,  4,  3,  2,  2,  1,  1,  1,  0,  0,  0 };

void setup(){           // Register Settings
  PORTA.DIRSET    = PIN7_bm;    // PA7 OUTPUT (mTC:1)
  //PORTMUX.CTRLC = 0;          // turn off TCA port multiplexer (PA7(mTC:1) to default PA3(mTC:4))
  TCA0.SINGLE.CTRLD   = 0;      // turn off split mode
  TCA0.SINGLE.CTRLC   = 0;      // PWM output pins override - disable
  TCA0.SINGLE.CTRLB   = TCA_SINGLE_CMP0EN_bm | TCA_SINGLE_WGMODE_SINGLESLOPE_gc;
  TCA0.SINGLE.INTCTRL = 0;      // turn off Arduino(mTC) time system
  TCA0.SINGLE.PERBUF  = 0xff;   // top value = 255
  TCA0.SINGLE.CMP0BUF = 0;      // output value
  TCA0.SINGLE.CTRLA   = TCA_SINGLE_CLKSEL_DIV1_gc | TCA_SINGLE_ENABLE_bm; // 20MHz / 1 / 256 -> 78,125Hz
}

void loop(){
  sineWave( 60,  500);          // C4
  sineWave( 64,  500);          // E4
  sineWave( 67,  500);          // G4
  sineWave( 72, 2000);          // C5
  _delay_ms(1000);
}

void sineWave(uint8_t midiNum, uint16_t msDuration) {
  uint16_t i, di = OCTAVE9[ midiNum % 12 ] >> (10 - midiNum / 12);  // 256 times the Wave Table subscript to advance in one cycle
  uint32_t cycDuration = F_CPU / 256 / 1000 * msDuration;           // Convert duration to number of cycles
  do {
    TCA0.SINGLE.CMP0BUF = SINE256[ (i += di) >> 8 ];        // 8bit PWM (78,125Hz)
      while( !(TCA0.SINGLE.INTFLAGS & TCA_SINGLE_OVF_bm) ); // Waiting for TCA0 overflow
      TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm;             // cleared by writing a '1'
  } while( --cycDuration );                                 // Exit if note data is 0
  TCA0.SINGLE.CMP0BUF = 0;                                  // Set output to 0
}

nice!(0)  コメント(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。