PCM2707はデバイスディスクリプタ情報をSPIインターフェース経由で変更できます。情報を変更後、USBのD+ピンを3.3V系にプルアップすると、PCからUSB機器が接続されたことが認識され、PCM2707はそのデバイスディスクリプタ情報をPCに通知します。
プログラム
CPUはATmega8Lです。以下にプログラムを示します。後ほど説明するプログラムに必要な項目も含んでいます。
※プログラムをブログにコピペすると、タブを削除したり、一部のコードが勝手に変更されてしまいます。どうなってるんでしょう?(#includeの括弧を全角に変更しています)
#define F_CPU 4.000E6 // マスタクロック4MHz
#include <avr/io.h>
volatile uint8_t I2C_data[7];
/*
PD7 O SS(PCM2707) <1>
PD6 I SSPND(PCM2707)<0>
PD5 O USB(D+) <0>
PD4 O LED, "Status" <0>
PD3 O LED, "Over modulation"<1>
PD2 I DIP SW, Left -1
PD1 I DIP SW, Left -2
PD0 I DIP SW, Left -3
PC6 I Reset
PC5 O I2C SCL(Si4710)
PC4 I/O I2C SDA(Si4710)
PC3 I DIP SW, Right -1
PC2 I DIP SW, Right -2
PC1 I DIP SW, Right -3
PC0 I DIP SW, Right -4
PB7 (Xtal)
PB6 (Xtal)
PB5 O SCLK(PCM2707) <0>
PB4 I N/A
PB3 O MOSI(PCM2707) <0>
PB2 O FSEL(PCM2707) <1>
PB1 O RESET(Si4710) <0>
PB0 I LRCK */
void init_devices(void) {
// ポート設定 0:入力, 1:出力
DDRB = 0b101110;
DDRC = 0b1100000;
DDRD = 0b10111000;
// 出力ポート初期化
// 入力ポート、1:プルアップ
PORTB = 0b010100;
PORTC = 0b1111111;
PORTD = 0b10000111;
PORTB |= _BV(1); // RESET(Si4710) => 1
// I2C SCL周波数: 100kHz (Si4710: <400khz data-blogger-escaped-span="">
// 100kHz = 4MHz/(16+2*TWBR*PRESCALER)
TWBR = 0x0C;
TWCR = 1<
// 16bit Timer/Counter
// Timer/Counter1 Control Register A
// TCCR1A = 0b00000000;
// Timer/Counter1 Control Register B
// ICES1: Rise Edge
// Clock Select: Start
// TCCR1B = 0b01000001;
// Timer/Couter Input Capture Interrupt Enable
// TIMSK |= _BV(TICIE1);
}
void init_pcm2707(void) {
// PCM2707 Device Descriptor ROM write (56bytes)
uint8_t m, n;
uint16_t SPI_PROCESS = 0x2040; // Process: Descriptor ROM address reset
uint8_t SPI_PROCESS2 = 0x10;// Process: Descriptor ROM data write
uint8_t ROMDATA[57] = {
0xBB, 0x08, // Vendor ID(2bytes): 0x08BB
0x07, 0x27, // Product ID(2bytes): 0x2707
// Product string: Product strings.(16bytes in ANSI ASCII code): "Si4710 USB FM-TX"
0x53, 0x69, 0x34, 0x37, 0x31, 0x30, 0x20, 0x55, 0x53, 0x42, 0x20, 0x46, 0x4D, 0x2D, 0x54, 0x58,
// Vendor string: Vendor strings are placed here.
// (32 bytes in ANSI ASCII code): "Burr-Brown from TI /w tamago"
0x42, 0x75, 0x72, 0x72, 0x2D, 0x42, 0x72, 0x6F, 0x77, 0x6E, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x54, 0x49, 0x20, 0x2F, 0x20, 0x74, 0x61, 0x6D, 0x61, 0x67, 0x6F, 0x20, 0x20, 0x20, 0x20, 0x20,
0xC0, // Power attribute (bmAttribute): 0x80 (Bus-powered), 0xC0(self-powered)
0x32, // Max power (maxPower): 0x0A(20mA), 0x32(100mA), 0x7D(250mA), 0xFA(500mA) 0x0A, 0x93, 0x01 // Auxiliary HID usage ID: 0x0A, 0x93, 0x01 (AL A/V capture)
};
// Note that the data bits must be sent from LSB to MSB on bus.
// This means that each data byte must be stored with its bits in reverse order.
PORTD &= ~_BV(7); // MS -> 0
for (n = 0; n < n="n+1){">
// MD write
if(bit_is_set(SPI_PROCESS, n)){
PORTB |= _BV(3);
}else{
PORTB &= ~_BV(3);
}
// MC write
PORTB |= _BV(5); // MC -> 1
PORTB &= ~_BV(5); // MC -> 0
}
PORTD |= _BV(7); // MS -> 1
PORTD &= ~_BV(7); // MS -> 0
for (m = 0; m < m="m+1){"> for (n = 0; n < n="n+1){ // MC -> 0
}
for (n = 0; n<8 data-blogger-escaped-n="n+1){ <span style=">
PORTB &= ~_BV(5); // MC -> 0
}
}
PORTD |= _BV(7); // MS -> 1
PORTD |= _BV(5); // USB(D+) -> 1
}
int main(void)
{
init_devices();
init_pcm2707();
init_si4710();
while(1); // 無限ループ
}
補足 PCM2707では、USBディスクリプタ情報のProduct StringとVendor StringをSPIで変更できるということで、上記の様な処理 init_pcm2707() を行っています。(必須の処理ではありません)
ただ、Vendor Stringは表示されませんでした。Product Stringは、当方が設定した文字列が出ているのがわかると思います。この文字列の文字コードは、ANSI ASCIIコードです。おそらくプログラムでそのまま書けると思うのですが、よくわからなかったので
このほか、USB電流の指定もでき、PC直結の場合USBルートハブのプロパティで”電力”タブを選べば確認できます。セルフパワーなのに指定することに意味があるのかは?ですが。
その他の問題
- I2S出力時にアナログ音声が出ない
内蔵のミュート回路が動作しているのかと、いろいろ原因を調べましたが問題なし。
ダメもとでググってみたら、森秀樹氏のブログのコメントにI2S出力モード(FSEL=L)では、
アナログ出力なしと書いてある。他の人のところでも同じ現象が起きるなら、それで正解か。
でもデータシートにはそんな記述は見あたらないように見える。俺の1日を返せという気分。
- アナログ出力レベルが低い
詳しく調べていませんが、お気楽オーディオキットの記事にヒントがあるかも知れません。
0 件のコメント:
コメントを投稿