SSブログ

ネットワークD/Aコンバータ [ColdFire V2]このエントリーを含むはてなブックマーク#

2047506

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月号 [雑誌]

Interface (インターフェース) 2008年 09月号 [雑誌]

  • 作者:
  • 出版社/メーカー: CQ出版
  • 発売日: 2008/07/25
  • メディア: 雑誌

nice!(0)  コメント(0)  トラックバック(0)  このエントリーを含むはてなブックマーク#

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

トラックバックの受付は締め切りました