そのようなときに便利なのが、RP2040 を使って USB-Blaster 互換デバイスを作る方法です。
今回は、GitHub 上で公開されている thisiseth/pico-usb-blaster をベースにして、Seeed XIAO RP2040 で動作する XIAO 版 USB-Blaster を作成しました。最終的に、Quartus から MAX 10 デバイスを認識し、実際に書き込みまでできるところまで確認できました。
この記事では、どこでつまずいたか、何を修正したか、最終的にどうやって動作確認できたかをまとめます。
ベースにしたのは以下のプロジェクトです。
thisiseth/pico-usb-blaster
このプロジェクトは Raspberry Pi Pico を前提としており、RP2040 を USB-Blaster 互換デバイスとして動かすものです。ただし、そのままでは Seeed XIAO RP2040 には持っていけない部分 がありました。
最初は「GPIO の割り当てだけ変更すれば動くだろう」と考えていました。しかし、実際にはそこまで単純ではありませんでした。
問題は主に次の 2 点でした。
blaster.c が Pico 前提の GPIO 実装になっている元の実装は、GPIO が連番で並んでいることを前提にしていたり、mask による一括操作を前提にしていました。Raspberry Pi Pico では都合が良くても、XIAO RP2040 で任意の GPIO に信号を割り当てたい場合には、この前提が邪魔になります。
そのため、XIAO 版では blaster.c を 任意 GPIO に対応した形で書き直す 必要がありました。
最初は USB としては見えているのに、Quartus から実際の通信が始まらない状態に悩まされました。jtagconfig --debug では USB-Blaster として見えるのに、JTAG 信号は出ない、という状態です。
調べていくと、USB の vendor request に対する処理を tud_control_request_cb() ではなく tud_vendor_control_xfer_cb() で受ける必要がある ことが分かりました。ここが合っていないと、ホスト側からの vendor request が STALL してしまい、その先の通信に進みません。
今回使用したピン割り当ては以下の通りです。
JTAG 用途として主に重要なのは TCK / TMS / TDI / TDO / GND ですが、元実装の流れに合わせて nCE, nCS, DATAOUT/nSTATUS も割り当てています。
今回かなり役に立ったのは、USB 側と JTAG 側を分けて切り分けたことです。
最初の段階では、
jtagconfig --debug でも USB-Blaster として見えるという状態でした。
そこで、main.c にデバッグ用 GPIO を仕込んで、
main() に到達しているかを段階ごとに確認しました。
その結果、
ことが分かりました。さらに Linux 側で usbmon を見ることで、vendor request が STALL している ことも確認できました。
ここで main.c の USB control request の処理を見直し、tud_vendor_control_xfer_cb() に変更したところ、control / bulk ともに通るようになりました。
USB 通信が通ったあとも、まだ JTAG チェーンの認識には失敗していました。
原因は blaster.c の shift() 処理でした。元の考え方のままだと、条件によって TDO と DATAOUT/nSTATUS を切り替えて読んでいましたが、JTAG 用途では常に TDO を読むべきでした。
この部分を修正して、JTAG shift 時には常に TDO をサンプリングするようにしたところ、ようやくチェーン認識に成功しました。
最終的には、jtagconfig --debug で以下のようにデバイスを認識できました。
1) USB Blaster [2-2.8]
(JTAG Server Version 20.1.1 Build 720 11/11/2020 SJ Standard Edition)
0318A0DD 10M04S(A|C) (IR=10)
Captured DR after reset = (0318A0DD) [32]
Captured IR after reset = (155) [10]
Captured Bypass after reset = (0) [1]
Captured Bypass chain = (0) [1]
JTAG clock speed 6 MHz
この状態まで来たあと、Quartus Programmer から 実機への書き込みも成功 しました。
今回の XIAO 版で重要だった変更点をまとめると、次の通りです。
usb_descriptors.c は元のままでよい最初は descriptor 側を疑いましたが、結論としては GitHub 版そのままで問題ありませんでした。
main.c は vendor control transfer の受け方を修正するmain.c では、vendor control request を TUD の汎用 control callback ではなく、tud_vendor_control_xfer_cb() で受けるように変更しました。
blaster.c は XIAO 向けに実質書き直しこのあたりがポイントでした。
使い方としては、元の pico-usb-blaster のリポジトリに対して、
src/blaster.hsrc/blaster.csrc/main.cを XIAO 版に置き換え、usb_descriptors.c はそのまま使います。
ビルドは通常通りです。
mkdir -p build
cd build
cmake ..
make pico_usb_blaster
生成された UF2 を XIAO RP2040 に書き込めば動作します。
今回の移植で感じたのは、「USB として見える」ことと「USB-Blaster として実際に使える」ことは別だということです。最初は descriptor や VID/PID の問題に見えても、実際には control request の受け方や、JTAG shift の細かな実装差が本質でした。
XIAO RP2040 は小型で扱いやすく、手元に余っていることも多いので、ちょっとした USB-Blaster 互換器として使えるとかなり便利です。同じように XIAO RP2040 で pico-usb-blaster を動かしたい方の参考になれば幸いです。
XIAO RP2040 用 USB-Blaster(ビルド済みUF2+ソース一式)
pico_usb_blaster_xiao_v1.uf2 をコピーこれだけで USB-Blaster として認識されます。
src フォルダを元の pico-usb-blaster に上書きしてビルドしてください。
2023年10月にリリースされた3.569では問題なく音出しができて、2024年1月にリリースされた3.611、2月にリリースされた3.616(Hotfix Release)でも音が出ません。この間に3.601というバージョンもリリースされていましたがイメージファイルが見つからなかったのでそのバージョンでの確認はしていません。
対策としては、バージョンを3.569以前にするか/boot/config.txtの修正が必要です。
尚、修正後の動作確認はRaspberry Pi 3 Model B+で行っています。
(osamu_chidaさん、ありがとうございます)
リリースバージョン3.616の/boot/config.txtは以下のようになっています。
## DO NOT EDIT THIS FILE ### ### APPLY CUSTOM PARAMETERS TO userconfig.txt ### initramfs volumio.initrd include volumioconfig.txt include userconfig.txt #### Volumio i2s setting below: do not alter #### dtoverlay=allo-boss-dac-pcm512x-audio,slave
この最終行を以下のように変更します。
dtoverlay=allo-boss-dac-pcm512x-audio
これで音が出るようになります。
Volumio Changelogのリリースバージョン3.601のところで、
「Apply slave parameter on some DACs to work with Pi5(Pi5 で動作するように一部の DAC にスレーブ パラメータを適用する)」
とありました。Allo BOSS DACがその対象になった?
なので、Raspberry Pi 5においてはこのslaveパラメータの記述の追加が必要となるのでしょうか。Raspberry Pi 5は、すでにスイッチサイエンスに注文済なので入手次第確認しましょう。
]]>Raspberry Pi Pico C/C++ SDKをRaspberry Pi 4 以外の別のプラットフォームで使う場合など、UARTとPC間でシリアル通信をする場合にはGPピンにケーブルを直接はんだ付けし、さらにUSBシリアル変換モジュールを使うことになります。であれば、Pi Pico用のUSBシリアル変換モジュールがあると嬉しいかもということでRaspberry Pi Pico(以降Pi Pico)用USBシリアル変換基板を作りました。

このPi Picoを重ねて使用することができるPi Pico用USBシリアル変換基板を使ってUARTによるシリアル通信をします。
尚、コンパイル・書き込みはArduino IDEで行い、ボードマネージャはRaspberry Pi Pico/RP2040 by Earle F. Philhowerを使っています。
UART0、UART1のTXとRXに標準で割り当てられているGPピンは下表のようになっています。()内のGPピンを使用する場合には設定が必要です。
| UARTチャネル | TX | RX |
| UART0 | 0 (12,17) | 1 (13,18) |
| UART1 | 8 (4) | 9 (5) |
Pi Pico用USBシリアル変換基板ではTX/RXピンをGP0/GP1(UART0)とGP4/GP5(UART1)のどちらかを選択します。
Pi Pico用USBシリアル変換基板のジャンパーの設定方法です。
基板上のジャンパーにショートピンを挿入して設定します。UART0を使う時にはJP1、JP2の2-3にショートピンを挿入し、UART1を使う場合にはJP1、JP2の1-2にショートピンを挿入します。
| JP NO. | UART0 | UART1 |
| JP1 | 2-3 | 1-2 |
| JP2 | 2-3 | 1-2 |
ここではUART0を使用します。
注意!! 基板上の、シルクで書かれた表は間違っています。
このプログラムはPi Pico用USBシリアル変換基板と接続したWindows PCとデータの送受信を確認するものです。手順は
というものです。
void setup() {
Serial.begin(115200);
// Serial2.setRX(5);
// Serial2.setTX(4);
Serial1.begin(9600);
}
void loop() {
if (Serial1.available()) {
String message = Serial1.readStringUntil('\n');
if (message == "hi pico, how are you?") {
Serial.println("it's OK. how are you?");
Serial1.println("it's OK. how are you?");
}
}
}
尚、ボードマネージャーをArduino Mbed OS RP2040 Boardsとしている場合、TX/RXのGPピンの設定を標準から変更する事はできないようでコンパイル時にエラーがでます。
setup()関数で
Serial.begin(115200);
はUSB CDC(USBシリアル)の初期設定で
Serial1.begin(9600);
はUART0の初期設定(ボーレートを9600)をしています。
// Serial2.setRX(5); // Serial2.setTX(4);
コメントアウトした2行はUART1を使用する場合の設定プロブラムになります。この2行のコメントを解除し、コード中のSerial1をSerial2に変更することでUART1を使う場合のコードになります。UART0がSerial1に、UART1がSerial2となる事に注意します。
また、UART1を使う場合は基板のJP1、JP2は1-2をショートします。
loop()関数では
if (Serial1.available()) {
で、UART0の受信データがある間この次以降のコードを実行します。
String message = Serial1.readStringUntil('\n');
は、\n が来るまでの受信データをmessageバッファに代入します。
Serial.println("it's OK. how are you?");
は、Arduino IDEのシリアルモニター(USB CDC(USBシリアル))に「it’s OK. how are you?」を出力します。
Serial1.println("it's OK. how are you?");
は、PC(UART0)に「it’s OK. how are you?」を出力します。
それでは、実際にシリアル通信の確認をしましょう。
Pi PicoのマイクロUSBはArduino IDEを実行しているMacに、Pi Pico用USBシリアル変換基板のType-CコネクタはWindows PCに接続しています。

確認は以下の手順で行いました。
すると、MacのArduino IDEのシリアルモニターに「it’s OK. how are you?」が表示され、

WindowsのTeraTermの画面に「it’s OK. how are you?」と表示されるのが確認できます。


Pico用の20ピン足の長いピンソケットを使用した例です。


注意! 基板上のシルクで書かれた表は間違っています。UART0、 UART1が逆になっています。
Raspberry Pi Pico USB-シリアル変換基板は、スイッチサイエンス委託販売ページにて販売しています。
]]>
| ピンNO | 信号名 | 説明 | ピンNO | 信号名 | 説明 |
| 3 | GND | グラウンド | 38 | GND | グラウンド |
| 5 | VDD1 | N.C | 36 | VDD | 電源電圧 |
| 11 | GP8 | タクトスイッチS2に接続 | 30 | RUN | タクトスイッチS1に接続 |
| 14 | SRCLK | 74HC595のシフトクロック端子に接続 | 27 | DS1 | Digit1の選択信号。Lowアクティブ |
| 15 | SER | 74HC595のシリアルデータ入力端子に接続 | 26 | DS2 | Digit2の選択信号。Lowアクティブ |
| 16 | XOE | 74HC595の出力イネーブル端子に接続 | 25 | DS3 | Digit3の選択信号。Lowアクティブ |
| 17 | RCLK | 74HC595のラッチクロック端子に接続 | 24 | DS4 | Digit4の選択信号。Lowアクティブ |
0.1秒毎にカウントアップするMicroPythonのサンプルコード例です。
from machine import Pin, Timer
import utime
# ピンの定義
CLOCK_PIN = Pin(10, Pin.OUT)
SERIAL_PIN = Pin(11, Pin.OUT)
XOE = Pin(12, Pin.OUT)
LATCH_PIN = Pin(13, Pin.OUT)
DIGIT_1_PIN = Pin(21, Pin.OUT)
DIGIT_2_PIN = Pin(20, Pin.OUT)
DIGIT_3_PIN = Pin(19, Pin.OUT)
DIGIT_4_PIN = Pin(18, Pin.OUT)
count = 0
SEGMENTS = [
0b11000000, # 0
0b11111001, # 1
0b10100100, # 2
0b10110000, # 3
0b10011001, # 4
0b10010010, # 5
0b10000010, # 6
0b11111000, # 7
0b10000000, # 8
0b10010000 # 9
]
msTimer = Timer()
def counter(timer):
global count
count += 1
print("COUNT: " + str(count))
if count >= 10000:
count = 0
msTimer.init(period = 100, callback = counter)
# 数値を7セグメントのパターンに変換する関数
def num_to_pattern(num):
digits = [0, 0, 0, 0]
digits[0] = num // 1000
digits[1] = (num // 100) % 10
digits[2] = (num // 10) % 10
digits[3] = num % 10
patterns = [SEGMENTS[digits[i]] for i in range(4)]
return patterns
# 1桁分のパターンをシフトレジスタに送信する関数
def set_digit_pattern(pattern):
for i in range(8):
bit = pattern & 0b10000000
SERIAL_PIN.value(bit)
pattern = pattern << 1
CLOCK_PIN.value(1)
CLOCK_PIN.value(0)
# 1桁の7セグメントLEDを点灯する関数
def light_digit(digit_pin):
digit_pin.value(0)
# 1桁の7セグメントLEDを消灯する関数
def off_digit(digit_pin):
digit_pin.value(1)
# ラッチクロックを生成する関数
def data_latch():
LATCH_PIN.value(1)
LATCH_PIN.value(0)
# メインの処理
def main():
blank = 0b11111111
while True:
patterns = num_to_pattern(count)
XOE.value(0)
LATCH_PIN.value(0)
light_digit(DIGIT_1_PIN)
set_digit_pattern(patterns[0])
data_latch()
utime.sleep_ms(5)
set_digit_pattern(blank)
data_latch()
off_digit(DIGIT_1_PIN)
light_digit(DIGIT_2_PIN)
set_digit_pattern(patterns[1])
data_latch()
utime.sleep_ms(5)
set_digit_pattern(blank)
data_latch()
off_digit(DIGIT_2_PIN)
light_digit(DIGIT_3_PIN)
set_digit_pattern(patterns[2])
data_latch()
utime.sleep_ms(5)
set_digit_pattern(blank)
data_latch()
off_digit(DIGIT_3_PIN)
light_digit(DIGIT_4_PIN)
set_digit_pattern(patterns[3])
data_latch()
utime.sleep_ms(5)
set_digit_pattern(blank)
data_latch()
off_digit(DIGIT_4_PIN)
if __name__ == '__main__':
main()

Raspberry Pi Pico用4桁7セグメントディスプレイ基板は、スイッチサイエンス委託販売ページにて販売しています。
]]>SN74HC595はテキサスインスツルメンツが提供する8ビットシフトレジスタであり、出力レジスタにパラレルに入力をシフトすることができます。シリアルデータ入力と8つのパラレル出力ピンを持ち、内部レジスタにデータを蓄積している間に、出力ピンを介して前の転送の結果を保持します。SN74HC595は、マイクロコントローラやマイクロプロセッサとのインターフェースで使用され、LEDドライバーやディスプレイなどのアプリケーションで広く使用されています。
ざっくりと「74HC595の回路とテストベンチをVHDLで設計して」と頼んだら以下のコードを出力しました(テストベンチは省略)。
library IEEE;
use IEEE.std_logic_1164.all;
entity sn74hc595 is
port (
clk: in std_logic; -- クロック信号
srclr: in std_logic; -- シフトレジスタクリア信号
oe: in std_logic; -- 出力イネーブル信号
ser: in std_logic; -- シリアルデータ入力信号
srclk: in std_logic; -- シフトレジスタクロック信号
rclk: in std_logic; -- レジスタクロック信号
q: out std_logic_vector(7 downto 0) -- パラレル出力信号
);
end sn74hc595;
architecture behavioral of sn74hc595 is
signal shift_reg: std_logic_vector(7 downto 0);
begin
process (clk)
begin
if rising_edge(clk) then
if srclr = '1' then -- シフトレジスタクリア信号がアサートされた場合
shift_reg <= (others => '0'); -- シフトレジスタをクリアする
elsif oe = '0' then -- 出力イネーブルがアサートされた場合
q <= shift_reg; -- パラレル出力にシフトレジスタの内容を反映する
elsif rising_edge(srclk) then -- シフトレジスタクロックの立ち上がりエッジ
shift_reg <= ser & shift_reg(7 downto 1); -- シフトレジスタにシリアルデータを入力する
elsif rising_edge(rclk) then -- レジスタクロックの立ち上がりエッジ
q <= shift_reg; -- パラレル出力にシフトレジスタの内容を反映する
end if;
end if;
end process;
end behavioral;
そもそも、74HC595はクロック信号としてシフトクロック(srclk)とストレージレジスタのラッチクロック(rclk)の2つですが、もう一つのクロック(clk)があります。また、このコードはQuartus Primeでは動きません。
そこで、入力信号は74HC595と同じになるように指定し、コンパイラも何を使うかを指定しました。こんな感じです。
「SN74HC595の回路をハードウェア記述言語のVHDLで設計し記述はrtlで。また、quartus primeでコンパイルできるようにして。
入力信号はsrclk:シフトクロック、srclr:シフトレジスタクリア、oe:出力イネーブル、rclk:パラレルデータラッチクロック、ser:シリアルデータ入力信号として出力信号はq:パラレル出力信号とする。
テストベンチはシリアルデータ”01011010″を入力してその出力を確認するような記述として。」
そこ結果が以下です。
library ieee;
use ieee.std_logic_1164.all;
entity SN74HC595 is
port (
srclk : in std_logic;
srclr : in std_logic;
oe : in std_logic;
rclk : in std_logic;
ser : in std_logic;
q : out std_logic_vector(7 downto 0)
);
end entity;
architecture rtl of SN74HC595 is
signal shift_reg : std_logic_vector(7 downto 0) := (others => '0');
begin
process (srclk, srclr)
begin
if srclr = '1' then
shift_reg <= (others => '0');
elsif rising_edge(srclk) then
shift_reg <= ser & shift_reg(7 downto 1);
end if;
end process;
process (rclk)
begin
if rising_edge(rclk) then
if oe = '1' then
q <= shift_reg;
else
q <= (others => 'Z');
end if;
end if;
end process;
end architecture;
想定していたコードを出力してくれました。
テストベンチは以下です。
library ieee;
use ieee.std_logic_1164.all;
entity testbench is
end entity;
architecture sim of testbench is
signal srclk, srclr, oe, rclk, ser : std_logic;
signal q : std_logic_vector(7 downto 0);
begin
uut : entity work.SN74LS595A
port map (
srclk => srclk,
srclr => srclr,
oe => oe,
rclk => rclk,
ser => ser,
q => q
);
stimulus : process
begin
ser <= '0';
srclr <= '1';
srclk <= '0';
oe <= '1';
rclk <= '0';
wait for 10 ns;
srclr <= '0';
wait for 10 ns;
for i in 0 to 7 loop
ser <= "01011010"(i);
srclk <= '1';
wait for 10 ns;
srclk <= '0';
wait for 10 ns;
end loop;
rclk <= '1';
wait for 10 ns;
rclk <= '0';
wait for 10 ns;
assert q = "01011010"
report "Output is incorrect"
severity error;
wait;
end process;
end architecture;
Process文のループでserにデータを入力している箇所がおかしそうです。実際、このテストベンチをコンパイルするとエラーが出ます。
そこで、ChatGPTが書いたコードとQuartusが吐き出したエラー内容をコピペして知らせると、ChatGPT自身の書いたコードのおかしなところを指摘して修正したコードを出力しました。
何度か同じようにした結果が以下のコードです。
library ieee;
use ieee.std_logic_1164.all;
entity testbench is
end entity;
architecture sim of testbench is
signal srclk, srclr, oe, rclk, ser : std_logic;
signal q : std_logic_vector(7 downto 0);
signal serial_in : std_logic_vector(7 downto 0);
begin
uut : entity work.SN74LV595A
port map (
srclk => srclk,
srclr => srclr,
oe => oe,
rclk => rclk,
ser => ser,
q => q
);
stimulus : process
begin
serial_in <= "01011010";
ser <= '0';
srclr <= '1';
srclk <= '0';
oe <= '1';
rclk <= '0';
wait for 10 ns;
srclr <= '0';
wait for 10 ns;
for i in 0 to 7 loop
ser <= serial_in(i);
srclk <= '1';
wait for 10 ns;
srclk <= '0';
wait for 10 ns;
end loop;
rclk <= '1';
wait for 10 ns;
rclk <= '0';
wait for 10 ns;
assert q = "01011010"
report "Output is incorrect"
severity error;
wait;
end process;
end architecture;
エラーの出なくなったテストベンチでシミュレーションしたのが以下です。

と言うことで、エラーの内容を知らせてあげたり対話をしながらですがChatGPTが回路とテストベンチを書いてくれました。また、人間も同じですが仕様を明確にして伝えてあげることが大事ですね。
]]>「10進カウンターの回路とテストベンチをVHDLで書いて。」
とお願いしたところ以下のようなVHDLコードを書いてくれました。

そして、VHDLテストベンチです。

説明文の最後が尻切れトンボだったので、もう一度同じ文言でお願いした(Regenerate response)ところ、今度は別のVHDLコード例を書いてくれました。
ほとんど同じ時間にお願いしたので(同じコードが出てくると思っていて)別のコードが出てきたので驚きました。


さて、ChatGPTが初めに書いてくれたVHDLコードをそのままコピペして、Quartus Primeでコンパイルしたところ以下のように「”to_unsigned”が使われているけど、宣言されていない」と怒られます。
Error (10482): VHDL error at counter_10.vhd(33): object "to_unsigned" is used but not declared
最終行の一つ前の行の
std_logic_vector(to_unsigned(count, 4))
は、integer型の count 変数を4ビットのstd_logic_vector型に変換するためのコードです。to_unsigned 関数は、引数として渡された数値をunsigned型に変換します。unsigned型は、ビット幅を指定することで任意のビット数で表現できます。この場合、count 変数をunsigned型に変換して、ビット幅を4ビットに設定しています。そして、unsigned型の値を std_logic_vector型に変換するために、std_logic_vector 型のコンストラクタに渡しています。
ここで使われている”to_unsigned”関数を有効にするにはnumeric_stdライブラリを宣言する必要があるということです。なので
use ieee.numeric_std.all;
を追加します。これでQuartus Primeのコンパイルがとおり、期待したシミュレーション結果が得られました。
そして、次のVHDLのコードですが、これは明らかに記述が足りていません。VHDL回路及びVHDLテストベンチともライブラリパッケージの宣言がありません。
必要なライブラリパッケージの宣言を追加することで、Quartus Primeでのコンパイル・シミュレーションができています。
ChatGPTで簡単な回路のVHDL記述を試しました。今回の例ではライブラリパッケージの宣言漏れはありましたが、基本的な回路記述、テストベンチの記述は修正せずに使えました。もう少し複雑な回路でも試してみようと思いますが、これは便利?ですね。
]]>ChatGPTは、OpenAIが開発した大規模な自然言語処理(NLP)モデルの1つです。ChatGPTは、膨大な量のテキストデータを学習して、自然言語理解と自然言語生成の能力を持っています。ChatGPTは、人工知能の分野である「言語モデル」に分類され、テキストの自動生成、文章の翻訳、意味理解、対話システムなどの応用が可能です。 OpenAIが公開したGPT-3は、ChatGPTの最新版で、インターネット上の巨大なデータセットから学習しており、自然な文章を生成する能力や、対話システムとしての応用が可能な高いレベルの自然言語理解を持っています。ChatGPTは、多岐にわたる分野で利用されており、自然言語処理における最先端技術の1つとして注目されています。
というようにChatGPTが自身のことを説明してくれました。そこで、そのChatGPTにPythonでLEDを点滅させるコードを書いてもらうことにします。
入力には「Raspberry piで動かすために、PythonでLEDを点滅させるプログラムを書いてください。」としています。
そして、ChatGPTが書いてくれたコードが以下になります(実際にコードをコピーして動くのを確認しています)。
コメントも日本語で書いてくれるのですね。点滅の時間は1秒なんだ。また、丁寧に説明もしてくれています。

これは最も単純なpythonプログラムの一つですが、他もいろいろ試してみましょう。
]]>

負荷電流を変化させた時の出力電圧の変動を測定。


5V(Type-C)入力±12V出力電源基板はLINUXCOMネットショップで頒布しています。また、スイッチサイエンスマーケットプレイスにて委託販売しています。
]]>
AK4493SEQを搭載したRBD-A4493Sと同様に、フロントエンドにはTIのPCM5122を使用しているので、新たにドライバーをインストールすることなくロームのハイエンド向けDACチップBD34352EKVの音を簡単に楽しむことができます。
Allo Boss(Volumio) /Allo Boss DAC(Moode Audio)ドライバを選択してください。

(Volumio)

(Moode Audio)
電源はCN7から+5V、±12Vを供給します。
| ピン番号 | 供給電圧 |
| 1 | +5V |
| 2 | GND |
| 3 | NC |
| 4 | NC |
| 5 | +12V |
| 6 | GND |
| 7 | -12V |
また、超低ノイズレギュレータのLT3045(正電源)とLT3094(負電源)を使用した専用の電源基板と接続することができます。
SW1-1のON/OFFで2種類のデジタルフィルタを選択できます。ONでシャープロールオフフィルタ、OFFでスローロールオフフィルタを選択することができます。なお、デジタルフィルタは電源のON時に決定されそれ以降にスイッチの状態を変えても反映されません。
SW1-4のON/OFFで、LEDのD2〜D4(黄)でモニターできるステータスを切り替えることができます。ONでサンプリング周波数を、OFFで設定されているデジタルフィルタをモニターできます。
LEDの状態とサンプリング周波数の関係です。●は消灯、○は点灯。
| LED | サンプリング周波数(kHz) | ||
| D4 | D3 | D2 | |
| ● | ● | ● | 32 |
| ● | ● | ○ | 44.1 |
| ● | ○ | ● | 48 |
| ● | ○ | ○ | 88.2 |
| ○ | ● | ● | 96 |
| ○ | ● | ○ | 176.4 |
| ○ | ○ | ● | 192 |
| ○ | ○ | ○ | 352.8/384 |
LEDの状態とデジタルフィルター特性の関係です。●は消灯、○は点灯。
| LED | デジタルフィルター特性 | ||
| D2 | |||
| ○ | シャープロールオフ | ||
| ● | スローロールオフ | ||
アナログ出力はCN1、CN2のピンヘッダーまたはパッドにハンダ付けして取り出すことができます。

さらにオプションのRCA端子基板を取り付けることも可能です。

ハンダ面に128×64 OLEDディスプレィ接続用としてGrove 4ピンコネクタを実装しています。表示内容はサンプリング周波数、選択されているデジタルフィルタそしてアッテネータレベルです。
秋月電子で購入できるGrove I2C OLEDディスプレイモジュールを使うことで特別な細工は必要なく使用できます。

同様に秋月電子で購入できる0.96インチ 128×64ドット有機ELディスプレイ(OLED)も使用できます。また、このOLEDを使用するにはGROVE – 4ピン-ジャンパメスケーブルが便利です。その場合、OLEDのピンヘッダーに4ピン-ジャンパメスケーブルのQIソケットを接続しますがこの接続には注意が必要で、下の画像のように白と黄色を入れ替えます。

OLEDディスプレイに表示されるのはBD34352EKVの再生状態になります。例えばVolumioのリサンプリング設定でサンプリング周波数を192kHzとしていた場合、Volumioのメインページでは音楽ソースのサンプリング周波数(例えば44.1kHz)を表示しますが、OLEDディスプレイでは実際にBD34352EKVが再生するサンプリング周波数、この場合は192と表示します。

Raspberry PiのGPIO信号を接続したコネクタ(ピンヘッダー)用ランドを用意しています( CN7)。ピン番号をGPIO番号の対応は以下です。
| ピン番号 | GPIO番号 |
| 1 | GND |
| 2 | GPIO20 |
| 3 | GPIO12 |
| 4 | GPIO7 |
| 5 | GPIO8 |
各信号はハード的にプルアップしているので、外部ではスイッチをGPIO信号とGNDに接続すれば良いです。
尚、電源基板を装着した場合は直接コネクタのランドにジャンパー線をハンダ付けする等の工夫が必要です。
参考:VolumioのGPIO Buttonsプラグインでボタン操作

リモコン受光モジュールをハンダ付けするランドを用意しています。
リモコン受光モジュールの出力はGPIO25に接続されています。秋月電子の赤外線リモコン受信モジュール GP1UXC41QSや赤外線リモコン受信モジュールOSRB38C9AA(2個入)等、動作電圧が3.3Vのジュールが使えます。
参考:VolumioのIR Remote Controllerプラグインでリモコン操作
Raspberry PiとBD34352EKVラズパイDAC基板(以下RBD-B34352)の電源の供給には順番があります。
Raspberry PiとRBD-B34352をほぼ同時かまたは、RBD-B34352を先に立ち上げその後Raspberry Piの電源をオンしてください。
ここで紹介したBD34352EKVを搭載したDAC基板はLINUXCOMネットショップで頒布しています。
]]>