ATtiny10 用プログラム (3)

DDA (Digital Differential Analyzer) を利用して、サイン/コサイン波形を出力する ATtiny10 用プログラム「var_test.c」を下に示します。
8 ビット phase correct PWM を利用していて、PB0 (ピン 1) および PB1 (ピン 3) から PWM 繰り返し周波数 15.625 kHz で出力されます。
LED を接続していると 1 秒足らずの周期で明滅を繰り返します。
グローバル変数を使った例として示しており、プログラム自体に特に意味はありません。
「var_test.c」

/*********************************************/
/* var_test.c: ATtiny10 global variable test */
/*             for AVR GCC Toolchain 3.3.0   */
/*                                           */
/* 2011/12/21: Created by pcm1723            */
/*********************************************/

#include <avr/io.h>
#include <avr/interrupt.h>

int16_t cos_acc, sin_acc;

void attiny10_port_setup( void )
{
// set clock prescaler to 1/1 (8 MHz clock)
  CCP    = 0xD8; // set protection signature
  CLKPSR = 0;    // clock prescale = 1/1 (8 MHz clock)
// timer mode = 8 bit phase correct PWM (WGM0[3:0] = 0001)
  TCCR0A  = _BV(WGM00); // WGM01:WGM00 = 01
  TCCR0B  = _BV(CS00);  // WGM03:WGM02 = 00, CS00 = 1 (clk/1)
// set compare output mode to clear at up, set at down
  TCCR0A |= (_BV(COM0B1) | _BV(COM0A1)); // COM0x1:COM0x0=10 
  DDRB   |= _BV(DDB0);  // set OC0A (pin 1) to output
  DDRB   |= _BV(DDB1);  // set OC0B (pin 3) to output
} // void attiny10_port_setup()

int main() 
{
  attiny10_port_setup(); 
  sin_acc = 0;
  cos_acc = 0x7e00; // initial radius
  for (;;) { // infinite loop
    while (!(_BV(TOV0) & TIFR0)) {} // OVerflow occurred?
    TIFR0 |= _BV(TOV0); // clear Timer OVerflow flag
// sin/cos generation by DDA (Digital Differential Analyzer)
    cos_acc -= (sin_acc >> 11);
    sin_acc += (cos_acc >> 11);
// convert 2's comp to unsigned and set PWM duty
    OCR0AL = (0x80 ^ ((0xff00 & sin_acc) >> 8));
    OCR0BL = (0x80 ^ ((0xff00 & cos_acc) >> 8));
  } // for (;;)
} // int main()

LED の光の明滅として認識するため、周波数を低くしてありますが、main() 関数内の DDA 処理部で sin_acc / cos_acc を右シフトしているシフト量を「11」から「3」にすると、周波数は 300 Hz 程度となり、PWM 出力を LPF に通せば、音として聞くことができます。
コンパイル結果の HEX ファイル「var_test.hex」を下に示します。
当然、(正しくない) 2 バイト LDS/STS が生成されているので、正しく動作しません。
「var_test.hex」

    :100000000AC019C018C017C016C015C014C013C04C
    :1000100012C011C010C011271FBFCFE5D0E0DEBF56
    :10002000CDBF10E0A0E4B0E001C01D93A434B1073F
    :10003000E1F70ED046C0E4CF88ED8CBF16BF81E05B
    :100040008EBD8DBD8EB5806A8EBD089A099A0895C1
    :10005000F3DF109343001093420080E09EE79093FB
    :100060004100809340008AB580FFFDCF8AB5816052
    :100070008ABD2091420030914300422F532F6BE004
    :10008000559547956A95E1F7809140009091410020
    :10009000841B950B90934100809340004BE0959515
    :1000A00087954A95E1F7820F931F909343008093C1
    :1000B0004200892F805886BD80914100805884BDC0
    :0600C000D2CFF894FFCF3F
    :00000001FF

これを、前回の「fix_lds」プログラムで処理した結果を下に示します。
「var_test_fixed.hex」

    :100000000AC019C018C017C016C015C014C013C04C
    :1000100012C011C010C011271FBFCFE5D0E0DEBF56
    :10002000CDBF10E0A0E4B0E001C01D93A434B1073F
    :10003000E1F70ED046C0E4CF88ED8CBF16BF81E05B
    :100040008EBD8DBD8EB5806A8EBD089A099A0895C1
    :10005000F3DF13A9000012A9000080E09EE791A938
    :10006000000080A900008AB580FFFDCF8AB58160BD
    :100070008ABD22A1000033A10000422F532F6BE064
    :10008000559547956A95E1F780A1000091A1000080
    :10009000841B950B91A9000080A900004BE0959569
    :1000A00087954A95E1F7820F931F93A9000082A9D3
    :1000B0000000892F805886BD81A10000805884BD32
    :0600C000D2CFF894FFCF3F
    :00000001FF

(レコード・タイプが通常のデータである) HEX レコードは、入力された HEX レコードと同じ開始アドレス、レコード長で出力しているので、両者を比べると、どこに修正が入ったのか分かります。
後で示すコンソール・ログを見ると、lds/sts は 13 ヵ所あったことが記録されています。
この HEX ファイルを ATtiny10 に書き込めば、正常動作します。
コンパイラが出力した HEX ファイルに、もう一段、処理をかぶせるわけですが、どうせ avrosp を走らせるためにコマンド・プロンプトを立ち上げているので、バッチ・ファイルの中に変換処理も含めてしまえば手間はかかりません。
以前の「pgm_tn10.bat」に 1 行追加して次のようにしました。
「fix_tn10.bat」

    call comosp
    fix_lds < .\%1\default\%1.hex > .\%1_fixed.hex
    avrosp -cCOM1 -dATtiny10 -if%1_fixed.hex -e -pf -vf

プロジェクト・フォルダ内の「default」フォルダの下に生成された HEX ファイルを入力とし、カレント・ディレクトリの下に変換された HEX ファイルを作成し、そのファイル名は、もとの名前の拡張子の '.hex' の前に '_fixed' を追加したものになっています。
コマンド・プロンプトで実行したときの、コンソール画面のログを下に示します。

X:\WSP\AVR>fix_tn10 var_test

X:\WSP\AVR>call comosp

X:\WSP\AVR>mode com1 baud=115200 data=8 parity=n dtr=off

Status for device COM1:
-----------------------
    Baud:            115200
    Parity:          None
    Data Bits:       8
    Stop Bits:       1
    Timeout:         OFF
    XON/XOFF:        OFF
    CTS handshaking: OFF
    DSR handshaking: OFF
    DSR sensitivity: OFF
    DTR circuit:     OFF
    RTS circuit:     ON


X:\WSP\AVR>fix_lds  0<.\var_test\default\var_test.hex 1>.\var_test_fixed.hex
# 0052: 9310 0043 --> a913
# 0056: 9310 0042 --> a912
# 005e: 9390 0041 --> a991
# 0062: 9380 0040 --> a980
# 0072: 9120 0042 --> a122
# 0076: 9130 0043 --> a133
# 0088: 9180 0040 --> a180
# 008c: 9190 0041 --> a191
# 0094: 9390 0041 --> a991
# 0098: 9380 0040 --> a980
# 00aa: 9390 0043 --> a993
# 00ae: 9380 0042 --> a982
# 00b8: 9180 0041 --> a181

X:\WSP\AVR>avrosp -cCOM1 -dATtiny10 -ifvar_test_fixed.hex -e -pf -vf
AVR Open-source Programmer $Revision: 1163 $ (C) 2004 Atmel Corp.

Serial port timeout set to 5 sec.
Found AVR ISP on COM1!
Entering programming mode...
Parsing XML file for device parameters...
Parsing '.\ATtiny10.xml'...
######
Saving cached XML parameters...
Signature matches device!
Erasing chip contents...
Reading HEX input file for flash operations...
##############
Programming Flash contents...

Reading Flash contents...

Comparing Flash data...
Equal!
Leaving programming mode...