タイマーカウンター0、1を組み合わせる / AM波を送信する

https://github.com/ti-nspire/AVR/tree/master/amRadio

タイマー0で搬送波を生成し、タイマー1から割り込みをかけて搬送波の出力をon/offする(要するに振幅変調のようなものをかける)。

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "scale16.h"

static inline void initTimer0(){ // タイマーカウンター0で1 MHzの搬送波を生成する。
    TCCR0A |= (1 << WGM01);      // CTCモードにする。
    TCCR0A |= (1 << COM0B0);     // OC0B (PD5)からトグル出力することにする。
    TCCR0B |= (1 << CS00);       // クロック周波数8 MHzを分周せずにカウントすることにする。
    OCR0A = 3;                   // コンペア値Aを設定する。
                                 // トグル周波数 = CPUクロック / (2 * 分周比 * (1 + コンペア値)) = 1 MHz
}

static inline void initTimer1(){ // タイマーカウンター1で搬送波をon/offする(振幅変調のようなものをかける)。
    TCCR1B |= (1 << WGM12);      // CTCモードにする。
    TCCR1B |= (1 << CS10);       // クロック周波数8 MHzを分周せずにカウントすることにする。
    TIMSK1 |= (1 << OCIE1A);     // コンペア値Aに一致したときに割り込んで、対応するISRを実行する。(※)

                                 // (※)タイマーカウンター1の値がコンペア値Aに一致すると、
                                 // TIFR1 (Timer/Counter1 Interrupt Flag Register)レジスタの
                                 // OCF1A (Timer/Counter1 Output Compare A Match Flag)ビットがセットされて、
                                 // 対応する割り込みベクタTIMER1_COMPA_vectが実行される。
}

ISR(TIMER1_COMPA_vect){ // タイマーカウンター1がコンペア値Aに一致したときに、
    DDRD ^= (1 << PD5); // PD5 (OC0B)からトグル出力されていたらそれを停止し、停止していたら再開する。
                        // 要するにタイマーカウンター1がコンペア一致するたびに搬送波のon/offを切り換える。
}

static inline void txNote(uint16_t note, uint16_t duration){
    OCR1A = note;                  // 音程を決めるパルス幅を設定して、
    sei();                         // 割り込みを許可して、
    for(int i=0; i<duration; i++){ // 一定期間だけ搬送波に振幅変調のようなものをかけて、
        _delay_ms(1);
    }                              // 一定期間が過ぎたら、
    cli();                         // 割り込みを禁止して、
    DDRD |= (1 << PD5);            // 変調されない搬送波だけが出力される状態に戻す。
}

int main(){
    // don't tell me you love me
    const uint16_t Notes[] = {B1,E2,Dx2,B1,
                              A1,E2,Cx2,A1,};
    const uint16_t NumOfNotes = (sizeof(Notes) / sizeof(uint16_t)); // ノートの数を取得しておく。

    initTimer0();
    initTimer1();
    
    while(1){
        for(int i=0; i<NumOfNotes; i++){
            txNote(Notes[i], 180);
        }
    }

    return 0;
}

このような感じで振幅変調されている。
f:id:ti-nspire:20190704143932p:plain:w500
f:id:ti-nspire:20190704144614p:plain:h280 f:id:ti-nspire:20190704175052p:plain:h280