SH-2A 基板に AC97 コーデックをつなぐ (7)
外部回路により SSIWS / SYNC を発生する方式についても実験してみます。
ATmega48/88/168/328 や ATtiny2313 は手持ちがあるのですが、さすがに 28 ピンや 20 ピンの IC を実装して実験する気にはなれなかったので、8 ピンの ATtiny13 を買ってきて使うことにしました。
ATtiny13 には PWM 波形を発生できる 8 ビットタイマがひとつしか内蔵されていないので、SYNC 信号の立ち上がり、あるいは立ち下がりの、いずれかのエッジが SSIWS のエッジと一致する形式の信号しか発生できません。
具体的には下の図のようになります。
C ソースプログラムを下に示します。
/****************************************************/ /* ac97gen.c : SYNC / SSIWS generator */ /* for SH-2A - AC97 link using ATtiny13 */ /* */ /* +-+_+-+ */ /* (from SH-2A) AC97RES# -|1 8|- Vcc (3.3V) */ /* (from AC97) BIT_CLK -|2 7|- POS_SEL */ /* ENABLE -|3 6|- SYNC (to AC97) */ /* GND -|4 5|- SSIWS (to SH-2A) */ /* +-----+ */ /* */ /* 2010-06-24 created by pcm1723 */ /****************************************************/ #include <avr/io.h> // include file for AVR #include <avr/sleep.h> FUSES = { // fuse definition in .elf file .low = (FUSE_SPIEN & FUSE_SUT1 & FUSE_SUT0 & FUSE_CKSEL1 & FUSE_CKSEL0), // external clock .high = HFUSE_DEFAULT }; #define SYNC_WIDTH (16) #define WS_PERIOD (512) #define POS_SEL_BIT (PINB2) // SYNC pos sel bit = PINB4 #define ENABLE_BIT (PINB4) // Hi-Z control int main() { PORTB = _BV(PORTB5) | _BV(PORTB4) | _BV(PORTB2); // enable pullup if (_BV(ENABLE_BIT) & PINB) { // enabled TCCR0A = _BV(COM0A0) // toggle OC0A on OCR0A match | _BV(WGM01) | _BV(WGM00); // WGM02:01:00 = 1:1:1 (fast PWM) OCR0A = (WS_PERIOD / 2) - 1; // TOP count if (_BV(POS_SEL_BIT) & PINB) {// SYNC falls on SSIWS edge TCCR0A |= _BV(COM0B1); // OC0B = L on OCR0B match OCR0B = (SYNC_WIDTH-1);// SYNC pulse width } else { // SYNC rises on SSIWS edge TCCR0A |= _BV(COM0B1) | _BV(COM0B0); // OC0B = H on OCR0B match OCR0B = 256-SYNC_WIDTH-1; // SYNC pulse width } // if (_BV(POS_SEL_BIT) & PINB) ... TCCR0B = _BV(CS00) // CS02:01:00 = 0:0:1 (1/1 clk) | _BV(WGM02); // WGM02:01:00 = 1:1:1 (fast PWM) DDRB = _BV(PORTB0) // PB0/OC0A is output | _BV(PORTB1); // PB1/OC0B is output } // if (_BV(ENABLE_BIT) & PINB) ... set_sleep_mode(SLEEP_MODE_IDLE); // sleep CPU only do { sleep_mode(); // sleep forever } while (1); }
オブジェクトのサイズは、フラッシュ上のプログラムが 106 バイトで、RAM は 1 バイトも使っていません。
フューズビットは、
- 外部クロック入力
- スタートアップ・ディレイ最小、
- リセット入力有効
の設定にします。
具体的には、 L バイトが 0x70、H バイトが 0xFF です。
ATtiny13 のリセット入力には、SH-2A の出力ポートが接続され、初期化プログラムからソフトウェア・リセットをかけるので、リセット後の ms 単位のディレイが付いていると邪魔になりますから、ディレイのないモードに設定します。
最も簡単な構成での SH-2A との接続を下に示します。
SSIWS0 への出力および SYNC への出力が 10 kΩ の抵抗でプルダウンしてあるのは、ATtiny13 がリセットされて、各ピンがハイインピーダンス状態の場合にプルダウンにより「L」レベルを確定させるためです。
AC97 コーデックは、RESET# 信号が H になる時点、つまり、リセットが解除される時点で SDATA_OUT および SYNC 信号が共に L レベルであれば通常動作しますが、いずれか一方でも H レベルになっていればテストモードに入ってしまいます。
意図しないテストモードに入ることを避けるために、わざわざ SH-2A 側が AC97 コーデックのリセット信号をコントロールしており、リセット解除時には各信号のレベルを確定させています。
実際に実験に使う回路は、上の構成を含めて 3 種の構成が可能なものを考えており、次回に説明したいと思います。