ネットワークD/Aコンバータ [ColdFire V2]
PWM出力の応用として、D/Aコンバータを作ります。
UDPで受信したデータに従って、PWMを制御すると、ネットワーク越しにアナログ出力の電圧を可変することが出来るはずです。
UDPで受信したデータを表示する
まずは、UDPで受信したデータを表示するプログラムを作成します。
main(){ char socket; int errcode; char *buf; char value; socket = CreateSocket(0); // UDP socket Bind(socket, 30049, 1); // Bind to port #stop 0 for(;;){ if(Getc(0)=='q')break; errcode = RecvFrom(socket, 2); if(errcode >= 1){ buf=GetReceiveBuffer(socket,1); value=buf[0]; MemoryFree(buf); PrHexByte(value);PrStr(" "); } } CloseSocket(socket); }
UDPで受信したデータを16進数の数値として延々と表示し続けます。 ポート番号には、おなじみの30049番を使っていますが、UDP電圧計とは異なり、今回はColdFireがこのポート番号でパケットを待ちます。
データを送り込むためのPC側のプログラムは、Javaで書きました。 サイン波を作っているつもりです。
package org.noritan.networkdac; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.SocketException; public class UdpSine implements Runnable { byte theta = 0; public UdpSine() { try { for (;;) { Thread.sleep(10); new Thread(this).run(); } } catch (InterruptedException e) { System.exit(0); } } @Override public void run() { byte value = (byte)(Math.sin(theta * Math.PI / 6) * 100 + 128); byte[] buf = new byte[2]; DatagramPacket packet = new DatagramPacket(buf, buf.length); try { DatagramSocket socket; socket = new DatagramSocket(); try { SocketAddress address = new InetSocketAddress("192.168.1.10", 30049); socket.connect(address); buf[0] = value; socket.send(packet); } catch (IOException e) { // Failed to connect/send e.printStackTrace(); } finally { socket.close(); } } catch (SocketException e) { // Failed to open a socket e.printStackTrace(); } if (++theta >= 12) theta = 0; } public static void main(String[] args) { new UdpSine(); } }
ほとんどコメントがありませんが、ご勘弁を。 10m秒ごとにサイン波に相当するデータを送信しています。 一周期が12データで構成されているので、期待される出力の周波数は、8.3Hzです。 双方のプログラムを実行すると、このような表示が現れます。
run 80 b2 d6 e4 d6 b2 80 4e 29 1c 29 4d 80 b2 d6 e4 d6 b2 80 4e 29 1c 29 4d 80 b2 d6 e4 d6 b2 80 4e 29 1c 29 4d 80 b2 d6 e4 d6 b2 80 4e 29 1c 29 4d 80 b2 d6 e4 d6 b2 80 4e 29 1c 29 4d 80 b2 d6 e4 d6 b2 80 4e 29 1c 29 4d 80 b2 d6 e4 d6 b2 80 4e 29 1c 29 4d 80 b2 d6 e4 d6 b2 80 4e 29 1c 29 4d
データが到着していることが確認できたので、こんどは、これをPWMのデューティーに設定してやります。
ネットワークD/Aコンバータ
データを表示していた部分をデューティー・レジスタへの代入に変更しました。 SilentCのプログラムは、送られてきた値を延々とPWMのデューティレジスタに入れるだけです。
main(){ int *pnqpar = 0x40100068; char *pwme = 0x401b0000; char *pwmclk = 0x401b0002; char *pwmprclk = 0x401b0003; char *pwmcnt1 = 0x401b000d; char *pwmper1 = 0x401b0015; char *pwmdty1 = 0x401b001d; char socket; int errcode; char *buf; char value; *pnqpar |= 0x000C; // PNQPAR1=11 (tertiary:PWM) *pwmclk = 0x00; // PCLK1=0 (clock A) *pwmprclk = 0x00; // PCKA=000 (x1) *pwmper1 = 0xFF; // PWMPER1=255 *pwmdty1 = 0x7F; // PWMDTY1=127 (50%) *pwme |= 0x02; // PWME1=1 (enable) socket = CreateSocket(0); // UDP socket Bind(socket, 30049, 1); // Bind to port #stop 0 for(;;){ if(Getc(0)=='q')break; errcode = RecvFrom(socket, 2); if(errcode >= 1){ buf=GetReceiveBuffer(socket,1); value=buf[0]; MemoryFree(buf); *pwmdty1 = value; } } CloseSocket(socket); }
クリスタルイヤホンで聞くと美しくない音が聞こえてきました。 さすがに、これでPCMが出来るなんて、夢にも思いませんが。
参考文献
Interface (インターフェース) 2008年 09月号 [雑誌]
- 作者:
- 出版社/メーカー: CQ出版
- 発売日: 2008/07/25
- メディア: 雑誌
コメント 0