PHD Guiding でオートガイドしたくなったので Meade LX200 エミュレータを作る (ASCOM対応LX200エミュレータ)


– 20070709 —

最近 PHD Guiding というフリーのソフトによるオートガイド環境の構築がはやっているようでして、私もやってみようと思っています。ただし、私の環境ではリレーボックスがあれば簡単になるのでPHD Guiding ではASCOMのドライバを使用するようにして、ASCOMの設定でLX200用のシリアル出力するようにします。(撮影用のノートパソコンにはパラレルポートが無いのでこの方法を選択しています)

大雑把な仕様はPCのシリアルポートから出力される LX200用のコマンド文字列をAVRマイコンで受けます。東西南北の移動コマンドが来れば対応するポートをON/OFFさせることでリレーを動かします。リレーは昔作成したのがあるので、今回はマイコン部分のみが作成対象になります。使用するマイコンはAVRマイコンです。(手持ち在庫の関係です)

※表現としてリレーと言ってますが、トラジスタのスイッチングでも全然問題はありません。


開発環境の確認

AVRマイコンに対応する gcc があります。今回はこのWebサーバーにコンパイラをインストールして環境の作成をします。このWebサーバーは Debian/GNU Linux etch で稼動していますのでdebパッケージがあれば簡単です。パッケージがあるか確認してみます。

# apt-cache search avr
ava - Algebraical Virtual Assembler for Atmel's AVR MCUs
avarice - use GDB with Atmel's JTAG ICE for the AVR
avr-libc - Standard C library for Atmel AVR development
avra - Assembler for Atmel AVR microcontrollers
avrdude - software for programming Atmel AVR microcontrollers
avrdude-doc - documentation for avrdude
avrp - Programmer for Atmel AVR microcontrollers
avrprog - Programmer for Atmel AVR microcontrollers
binutils-avr - Binary utilities that support Atmel's AVR targets.
gcc-avr - The GNU C compiler (cross compiler for avr)
gdb-avr - The GNU Debugger for avr
libgringotts2 - encapsulate data in an encrypted and compressed file
sdcc - Small Device C Compiler
sdcc-doc - Small Device C Compiler (documentation)
sdcc-libraries - Small Device C Compiler (libraries)
simulavr - Atmel AVR simulator
traceroute-nanog - Determine route of packets in TCP/IP networks (NANOG variant)
uisp - Micro In-System Programmer for Atmel's AVR MCUs
#

apt-cache の結果、gcc-avr と avr-libc がありましたので apt-get install でインストールすれば c言語で開発出来るようになります。コンパイル出来るかどうか確認するために、サンプルデモをコンパイルしてみます。

$ cp -a /usr/share/doc/avr-libc/examples/demo .
$ cd demo
$ gzip -d iocompat.h.gz
$ make
avr-gcc -g -Wall -O2 -mmcu=atmega8 -c -o demo.o demo.c
avr-gcc -g -Wall -O2 -mmcu=atmega8 -Wl,-Map,demo.map -o demo.elf demo.o
avr-objdump -h -S demo.elf > demo.lst
avr-objcopy -j .text -j .data -O ihex demo.elf demo.hex
avr-objcopy -j .text -j .data -O binary demo.elf demo.bin
avr-objcopy -j .text -j .data -O srec demo.elf demo.srec
avr-objcopy -j .eeprom --change-section-lma .eeprom=0 -O ihex demo.elf demo_eeprom.hex \
|| { echo empty demo_eeprom.hex not generated; exit 0; }
avr-objcopy -j .eeprom --change-section-lma .eeprom=0 -O binary demo.elf demo_eeprom.bin \
|| { echo empty demo_eeprom.bin not generated; exit 0; }
avr-objcopy -j .eeprom --change-section-lma .eeprom=0 -O srec demo.elf demo_eeprom.srec \
|| { echo empty demo_eeprom.srec not generated; exit 0; }
$ ls
Makefile demo.c demo.hex demo.map demo.srec demo_eeprom.hex iocompat.h
demo.bin demo.elf demo.lst demo.o demo_eeprom.bin demo_eeprom.srec
$

まぁ、demo.hex とかが作成されているので問題無いでしょう。


ASCOM がLX200を認識する条件を確認

— 20070713 —

ASCOM のLX200ドライバが接続を認識するために、何らかのコマンドをLX200に送信して、返ってくるレスポンスをもとに判断しているものと思われます。ので、どんなやりとりをやってるのか確認してみました。結果は以下のようなやりとりをしていました。これは、ASCOM 4.1 と LX200 3.34L の組合せの場合です。

***Generic LX200 Type Scopes の場合

ASCOM LX200
#:GR#
15:15.6#
#:GD#
-00゚01#
#:GR#
15:15.6#
#:U#
#:GR#
15:15:37#
#:GR#
15:15:37#
#:GD#
-00゚01:03#

***Meade Telescope and Focuser の場合
ASCOM LX200
#:GS#
15:25:32#
:GVF#
無応答
ACK
P
:Sw 3#
1
:GZ#
004゚17#
:GZ#
004゚17#
:U#
:GZ#
004゚17:51#
:GR#
15:15:37#
:GD#
-00゚01:03#
:GZ#
004゚17:51#
:Gt#
+35゚19#
:GA#
+54゚35:22#
:GZ#
004゚18:00#
:GD#
-00゚01:03#

というやりとりした結果 connected となりました。

上記シーケンスの中で’゚’の記号は 0xdf ACKと書いてるのは 0x06 のコードです。これを見るとこれから作成するエミュレータには、Get系のコマンドに応答出来るような仕込みが必要と思います。


とりあえず作成開始

— 20070714 —

さて、3連休なのですが台風4号が来るとのことですので、家で工作することにしました。物は以下の写真のようになりました。ピンボケですが撮り直しは気が向いたらします。

使用したチップは AT90S2313 が手持ちでありましたのでそれを使用しています。とにかく、ASCOMのドライバと通信しないといけないのでUART付きのマイコンを使用すれば大丈夫です。

パソコンとの接続はシリアルになるわけですが、ノートパソコンにはRS232Cのポートが無いのでUSB-シリアル変換基板を大須のタケイムセンで買ってきました。FTDIのFT232RLが乗っているやつです。あとは AVRマイコンと接続させればOKです。

本日作成したのは、上記の写真までで、リレー側の出力はまだ配線していませんが早速PHD Guiding + ASCOM の LX200 ドライバで接続出来るか確認した結果、Generic LX200 Type Scopes で LXP Connected と Meade Telescope and Focuser で LX200 Connected というのが PHD Guiding のウィンドウの左下のステータス領域に出たので第一段階はクリアしましたということでしょう。


とりあえず作成開始(その2)

— 20070716 —

新潟県中越沖地震が発生しました。これ以上被害が広がることが無ければいいと思います。

さて、3連休も最終日です。ある程度は形にしておこうということで、残りの配線をしました。写真のような感じになっちゃいました。
最初はマイコン部分だけ作って、リレーボックスはpictor 201xt互換のものを使用するつもりでしたが、基板に余裕があったので、フォトカプラを付けました。フォトカプラにミニDIN 6ピンのコネクタを付けて、タカハシのオートガイダー端子に直接差せるようにしておきました。しかしながら私のは EM200b なのでオートガイダーの端子は無いため、ハンドコントローラからコネクタを分岐させて、それと接続しました。6ピンなのでPS/2 のケーブルが使用可能です。

動作確認はパソコンの端末ソフトから LX200のコマンドを手入力して行いました。東西南北の移動コマンドを入れていきます。赤道儀に耳を付けてモーター音が変化すればOKということですが、ちゃんとそのような動きをしていたので一安心です。あとはケースに入れないとだめですね。


晴れたので動作確認をしました。

7月23日薄曇のコンディションでしたが、久し振りの晴れです。
作った LX200エミュレータが動くか確認しました。
ガイド鏡とかは以下のとおりです。

  • ガイド鏡: Meade 60mm/F11
  • ガイド用カメラ: Meade DSIPro
  • ノートパソコン(PHDGuiding 1.5/ASCOM 4.1)
  • 自作 LX200エミュレータ
  • EM-200b

ベランダに赤道儀を出してテストしました。
下のグラフのように、補正しながら稼動しました。
とりあえず、赤道儀を南向きのベランダに出した状態でテストしましたので、極軸はズレたままです。この状態でも、PHDGuiding の画面ではガイド星は動かなかったので一安心です。

今回は作ったハードが動くかどうかの確認ですので
目的は達成出来ました。


今回作った ASCOM 対応 LX200 エミュレータのソース

/* ——————————————————————————–

— Source name: lx200emu.c
— Version: 0.1(20070714)
— Author: Masahiro Kusunoki

— PHD Guiding –> ASCOM ドライバ –> LX200 コマンド出力 –> 当マイコンボックス –> EM-200b

— AT90S2313
— 01 RESET
— 02 PD0(RXD)
— 03 PD1(TXD)
— 04 XTAL2
— 05 XTAL1
— 06 PD2(INT0)
— 07 PD3(INT1)
— 08 PD4(T0)
— 09 PD5(T1)
— 10 GND
— 11 PD6(ICP)
— 12 PB0(AIN0)
— 13 PB1(AIN1)
— 14 PB2
— 15 PB3(OC1)
— 16 PB4
— 17 PB5(MOSI)
— 18 PB6(MISO)
— 19 PB7(SCK)
— 20 VCC

— シリアル回線については、9600/8N1 で接続

— 問題は、ASCOM にしても DSI にしても、どこまで返事を返せば
— 接続 OK として認識してくれるのかが不明

——————————————————————————– */

#include
#include

#define west PB0
#define east PB1
#define north PB2
#define south PB3

void commandCheck_start(unsigned char);
void commandCheck_Major(unsigned char);
void commandCheck_MandDirection(unsigned char);
void commandCheck_QandDirection(unsigned char);
void commandCheck_Get(unsigned char);
void uartPutChar(unsigned char);
void resRA(void);
void resDec(void);
void resAzi(void);
void resTrack(void);
void resSite(void);
int main(void);

/*
commandStatus = 0 “:” が来るのを待つ
commandStatus = 1 “M” “Q” の判定
commandStatus = 2 “M” に続く方角の文字判定とリレー制御
commandStatus = 3 “Q” に続く方角の文字判定とリレー制御
commandStatus = 4 “G” に続く方角の文字判定とリレー制御
*/
unsigned char commandStatus = 0;
unsigned char longFormat = 0;

/* ——————————————————————————–
— UART 受信割り込み処理(1文字来た)
——————————————————————————– */
SIGNAL(SIG_UART_RECV) {
unsigned char ch01 = UDR;
switch(commandStatus) {
case 0:
commandCheck_start(ch01);
break;
case 1:
commandCheck_Major(ch01);
break;
case 2:
commandCheck_MandDirection(ch01);
break;
case 3:
commandCheck_QandDirection(ch01);
break;
case 4:
commandCheck_Get(ch01);
break;
}
return;
}

/* ——————————————————————————–
— コマンド文字列開始判定
——————————————————————————– */
void commandCheck_start(unsigned char ch01) {
if(ch01 == ‘:’) {
commandStatus = 1;
} else if(ch01 == 0x06) { //ACK が来たら無条件に’P'(赤道儀モード)を返す
uartPutChar(‘P’);
}
}

/* ——————————————————————————–
— 移動開始か移動停止コマンドかの判定
——————————————————————————– */
void commandCheck_Major(unsigned char ch01) {
switch(ch01) {
case ‘M’: // Movement Command
commandStatus = 2;
break;
case ‘Q’: // Movement Command
commandStatus = 3;
break;
case ‘G’: // Get Telescope Information
commandStatus = 4;
break;
case ‘U’: // Precision Toggle
if(longFormat == 0)
longFormat = 1;
else
longFormat = 0;
commandStatus = 0;
break;
case ‘S’: // Set command
uartPutChar(‘1’); // Setコマンドは無条件に1(true)を返す
commandStatus = 0;
default:
commandStatus = 0;
break;
}
}

/* ——————————————————————————–
— 移動開始(該当のポートを 1 にする)
——————————————————————————– */
void commandCheck_MandDirection(unsigned char ch01) {
switch(ch01) {
case ‘n’:
PORTB |= (1 << north); break; case 's': PORTB |= (1 << south); break; case 'e': PORTB |= (1 << east); break; case 'w': PORTB |= (1 << west); break; } commandStatus = 0; } /* -------------------------------------------------------------------------------- -- 移動停止(該当のポートを 0 にする) -------------------------------------------------------------------------------- */ void commandCheck_QandDirection(unsigned char ch01) { switch(ch01) { case 'n': PORTB &= ~(1 << north); break; case 's': PORTB &= ~(1 << south); break; case 'e': PORTB &= ~(1 << east); break; case 'w': PORTB &= ~(1 << west); break; case '#': PORTB &= ~((1 << north) | (1 << south) | (1 << east) | (1 << west)); break; } commandStatus = 0; } /* -------------------------------------------------------------------------------- -- Getコマンド処理 -------------------------------------------------------------------------------- */ void commandCheck_Get(unsigned char ch01) { unsigned char saveLongFormat = 0; switch(ch01) { case 'A': // Get Telescope Altitude case 'D': // Get Telescope Declination resDec(); break; case 'R': // Get Telescope RA case 'r': // Get current/target RA resRA(); break; case 'Z': // Get Telescope Azimuth resAzi(); break; case 'T': resTrack(); break; case 'S': // Get the Sideral time case 'a': // Get Telescope local time in 12Hour Format saveLongFormat = longFormat; longFormat = 1; resRA(); longFormat = saveLongFormat; break; case 't': // Get current Site Latitude saveLongFormat = longFormat; longFormat = 0; resDec(); longFormat = saveLongFormat; break; case 'M': case 'N': case 'O': case 'P': resSite(); break; } commandStatus = 0; } /* -------------------------------------------------------------------------------- -- レスポンス 赤経 -- 00:00.0# -- 00:00:00# -------------------------------------------------------------------------------- */ void resRA(void) { uartPutChar('0'); uartPutChar('0'); uartPutChar(':'); uartPutChar('0'); uartPutChar('0'); if(longFormat == 1) { uartPutChar(':'); uartPutChar('0'); } else { uartPutChar('.'); } uartPutChar('0'); uartPutChar('#'); } /* -------------------------------------------------------------------------------- -- レスポンス 赤緯 -- 対象コマンド :GR :Gr -- +00*00# -- +00*00:00# -------------------------------------------------------------------------------- */ void resDec(void) { uartPutChar('+'); uartPutChar('0'); uartPutChar('0'); uartPutChar(223); uartPutChar('0'); uartPutChar('0'); if(longFormat == 1) { uartPutChar(':'); uartPutChar('0'); uartPutChar('0'); } uartPutChar('#'); } /* -------------------------------------------------------------------------------- -- レスポンス アジマス -- 対象コマンド :GZ -- 000*00# -- 000*00:00# -------------------------------------------------------------------------------- */ void resAzi(void) { uartPutChar('0'); uartPutChar('0'); uartPutChar('0'); uartPutChar(223); uartPutChar('0'); uartPutChar('0'); if(longFormat == 1) { uartPutChar(':'); uartPutChar('0'); uartPutChar('0'); } uartPutChar('#'); } /* -------------------------------------------------------------------------------- -- レスポンス トラッキング -- 対象コマンド :GT -- 00.0# -------------------------------------------------------------------------------- */ void resTrack(void) { uartPutChar('0'); uartPutChar('0'); uartPutChar('.'); uartPutChar('0'); uartPutChar('#'); } /* -------------------------------------------------------------------------------- -- レスポンス サイト名 -- 対象コマンド :GM :GN :GO :GP -- ???# -------------------------------------------------------------------------------- */ void resSite(void) { uartPutChar('?'); uartPutChar('?'); uartPutChar('?'); uartPutChar('#'); } /* -------------------------------------------------------------------------------- -- UART 一文字出力 -------------------------------------------------------------------------------- */ void uartPutChar(unsigned char ch01) { loop_until_bit_is_set(USR, UDRE); UDR = ch01; } /* -------------------------------------------------------------------------------- -- メイン処理 -------------------------------------------------------------------------------- */ int main(void) { cli(); PORTB = 0x00; DDRB = 0xFF; PORTD = 0x00; DDRD = 0xFF; /* * UART 制御レジスタ UCR の設定 * RXCIE 受信完了割り込み * TXCIE 送信完了割り込み * UDRIE 送信データレジスタ空き割り込み * RXEN 受信許可 * TXEN 送信許可 */ UCR = (1<

リアルタイムクロックモジュール RTC-8564NB (秋月のん) のバッテリーバックアップ

リアルタイムクロックモジュール RTC-8564 はバッテリーバックアップが可能なので、マイコンボードに電池を接続してバックアップ可能にします。
RTC-8564の電源端子にマイコンからの電源供給がされて動くわけですが、マイコンの電源がOFFになったら電池に切り替えてバックアップします。この方法で一番簡単なのはダイオード一本で片付ける方法です。しかしながらダイオードの電圧降下(0.6~0.7V程度)があるためRTC-8564の電源電圧は5-0.7=4.3Vになります。一方マイコンと接続しているI2Cバスの信号ラインは5Vかかります。

問題は電源電圧より信号ラインの方が電圧が高いということです。RTC-8564のデータシートによりますと入力電圧は GND-0.5V ~ VDD+0.5V までとなっています。このことから普通のダイオードではわずかですが定格を越えます。電圧降下の低いダイオードを使用すればよいのですが買いに行くのも面倒なので、今回は下記のようにトランジスタのスイッチをバックアップ回路として作成しました。

Spartan-3A DCM を veritak で動作確認してみた。

Spartan-3A スターターキットの PDF の資料やアプリケーションノートなど見てますが
基本クロックは、50MHzの水晶が原発ですが、それ以外の
クロックが欲しいときは、DCM(Digital Clock Manager)を使用するようです。
ということで、DCM を使用する準備として veritak で確認してみました。

  • CORE Generator で DCM のコードを GUI で生成
  • テスト用の Verilog コードを書いてみる
  • veritak(シェアウェア版)でシミューレーションしてみる

CORE Generator を起動して DCM のコアを作成してみました。
今回は、 FPGA Features and Design -> Clocking -> Spartan-3E, Spartan-3A -> Single DCM_SP
とファンクションを選択して、DCM作成です。
今回は、CLK0以外に、90度づつ位相ずれた CLK90, CLK180, CLK270 なども
出力するようにしてみました。

また、PDF 文書にあった推奨リセット回路(シフトレジスタでワンショットパルスを出す)も追加しました。

生成された DCM モジュール

////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 1995-2008 Xilinx, Inc.  All rights reserved.
////////////////////////////////////////////////////////////////////////////////
//   ____  ____ 
//  /   /\/   / 
// /___/  \  /    Vendor: Xilinx 
// \   \   \/     Version : 10.1.03
//  \   \         Application : xaw2verilog
//  /   /         Filename : dcm_test01.v
// /___/   /\     Timestamp : 04/21/2009 13:34:03
// \   \  /  \ 
//  \___\/\___\ 
//
//Command: xaw2verilog -st C:\mkusunoki\\dcm_test01.xaw C:\mkusunoki\\dcm_test01
//Design Name: dcm_test01
//Device: xc3s700a-4fg484
//
// Module dcm_test01
// Generated by Xilinx Architecture Wizard
// Written for synthesis tool: XST
`timescale 1ns / 1ps

module dcm_test01(CLKFB_IN, 
                  CLKIN_IN, 
                  RST_IN, 
                  CLKIN_IBUFG_OUT, 
                  CLK0_OUT, 
                  CLK90_OUT, 
                  CLK180_OUT, 
                  CLK270_OUT, 
                  LOCKED_OUT);

    input CLKFB_IN;
    input CLKIN_IN;
    input RST_IN;
   output CLKIN_IBUFG_OUT;
   output CLK0_OUT;
   output CLK90_OUT;
   output CLK180_OUT;
   output CLK270_OUT;
   output LOCKED_OUT;
   
   wire CLKFB_IBUFG;
   wire CLKIN_IBUFG;
   wire CLK0_BUF;
   wire CLK90_BUF;
   wire CLK180_BUF;
   wire CLK270_BUF;
   wire GND_BIT;
   
   assign GND_BIT = 0;
   assign CLKIN_IBUFG_OUT = CLKIN_IBUFG;
   IBUFG CLKFB_IBUFG_INST (.I(CLKFB_IN), 
                           .O(CLKFB_IBUFG));
   IBUFG CLKIN_IBUFG_INST (.I(CLKIN_IN), 
                           .O(CLKIN_IBUFG));
   BUFG CLK0_BUFG_INST (.I(CLK0_BUF), 
                        .O(CLK0_OUT));
   BUFG CLK90_BUFG_INST (.I(CLK90_BUF), 
                         .O(CLK90_OUT));
   BUFG CLK180_BUFG_INST (.I(CLK180_BUF), 
                          .O(CLK180_OUT));
   BUFG CLK270_BUFG_INST (.I(CLK270_BUF), 
                          .O(CLK270_OUT));
   DCM_SP DCM_SP_INST (.CLKFB(CLKFB_IBUFG), 
                       .CLKIN(CLKIN_IBUFG), 
                       .DSSEN(GND_BIT), 
                       .PSCLK(GND_BIT), 
                       .PSEN(GND_BIT), 
                       .PSINCDEC(GND_BIT), 
                       .RST(RST_IN), 
                       .CLKDV(), 
                       .CLKFX(), 
                       .CLKFX180(), 
                       .CLK0(CLK0_BUF), 
                       .CLK2X(), 
                       .CLK2X180(), 
                       .CLK90(CLK90_BUF), 
                       .CLK180(CLK180_BUF), 
                       .CLK270(CLK270_BUF), 
                       .LOCKED(LOCKED_OUT), 
                       .PSDONE(), 
                       .STATUS());
   defparam DCM_SP_INST.CLK_FEEDBACK = "1X";
   defparam DCM_SP_INST.CLKDV_DIVIDE = 2.0;
   defparam DCM_SP_INST.CLKFX_DIVIDE = 1;
   defparam DCM_SP_INST.CLKFX_MULTIPLY = 4;
   defparam DCM_SP_INST.CLKIN_DIVIDE_BY_2 = "FALSE";
   defparam DCM_SP_INST.CLKIN_PERIOD = 20.000;
   defparam DCM_SP_INST.CLKOUT_PHASE_SHIFT = "NONE";
   defparam DCM_SP_INST.DESKEW_ADJUST = "SYSTEM_SYNCHRONOUS";
   defparam DCM_SP_INST.DFS_FREQUENCY_MODE = "LOW";
   defparam DCM_SP_INST.DLL_FREQUENCY_MODE = "LOW";
   defparam DCM_SP_INST.DUTY_CYCLE_CORRECTION = "TRUE";
   defparam DCM_SP_INST.FACTORY_JF = 16'hC080;
   defparam DCM_SP_INST.PHASE_SHIFT = 0;
   defparam DCM_SP_INST.STARTUP_WAIT = "FALSE";
endmodule

作成してみたテストベンチ

`default_nettype none
`timescale 1ns / 1ns

module dcm_test01_testbench;

reg CLK50MHz;
reg RST_IN;
wire CLKIN_IBUFG_OUT;
wire CLK0_OUT;
wire CLK90_OUT;
wire CLK180_OUT;
wire CLK270_OUT;
wire LOCKED_OUT;

dcm_test01 dcm01 (
	.CLKFB_IN(CLK0_OUT),
	.CLKIN_IN(CLK50MHz),
	.RST_IN(Q),
	.CLKIN_IBUFG_OUT(CLKIN_IBUFG_OUT),
	.CLK0_OUT(CLK0_OUT),
	.CLK90_OUT(CLK90_OUT),
	.CLK180_OUT(CLK180_OUT),
	.CLK270_OUT(CLK270_OUT),
	.LOCKED_OUT(LOCKED_OUT)
	);

wire Q;
//defparam U1.INIT = 16'h000F;
SRL16 #(16'h000F) U1 (
	.Q(Q),
	.A0(1),
	.A1(1),
	.A2(1),
	.A3(1),
	.CLK(CLK50MHz),
	.D(0)
);

// クロック
initial
begin
	CLK50MHz = 0;
	forever #10 CLK50MHz = ~CLK50MHz;
end

initial
begin
	#1600
	$finish;
end

always
	$monitor($time, "clkin=%b reset=%b clk0=%b clk90=%b clk180=%b clk270=%b locked=%b\n", CLK50MHz, RST_IN,CLK0_OUT,CLK90_OUT,CLK180_OUT,CLK270_OUT,LOCKED_OUT);
endmodule

で、veritakでシミューレーションしてみましたところ、各種クロックと、リセットに反応すること、と
クロックのロック状態も表示されたので実際にインプリする場合もちょっと安心ということで

にしても、ついでで DDR2 SDRAM も MIG で作成してみて veritak してみましたところ
これも動きそうな感じではあります。が、UG086 に書いてる使いかたが
まだよく理解出来ないのと、DDR/DDR2 な SDRAM の基本もわかってないので
これから余裕が出来れば、使ってみたいですね。
とりあえず、picoblaze を先に使用したいです。

PicoBlaze でキャラクタ液晶表示

今回は、Spartan-3A の PicoBlaze でキャラクタ液晶の表示を行ないました。
と言っても今回は、fpga ポートの入出力動作がうまくいかなかったので
BUSYチェックはしないで、時間待ちして表示させてます。

何のヒネリも無いので、そのままソース掲載でし。マイコンのアセンブラとVerilogです。

PicoBlaze のソース

CONSTANT        LCD_DATA,       01      ;
CONSTANT        LCD_CTRL_E,     02      ;
CONSTANT        LCD_CTRL_RS,    03      ; 0=Command, 1=Data
CONSTANT        LCD_CTRL_RW,    04      ; 0=write, 1=read
CONSTANT        LED,            05      ; LED port

                ADDRESS 000
INIT00:
                ENABLE  INTERRUPT
                CALL    LCD_INIT

MAIN00:         LOAD    s4, 50          ; P
                CALL    LCD_PUTCH
                LOAD    s4, 69          ; i
                CALL    LCD_PUTCH
                LOAD    s4, 63          ; c
                CALL    LCD_PUTCH
                LOAD    s4, 6F          ; o
                CALL    LCD_PUTCH
                LOAD    s4, 42          ; B
                CALL    LCD_PUTCH
                LOAD    s4, 6C          ; l
                CALL    LCD_PUTCH
                LOAD    s4, 61          ; a
                CALL    LCD_PUTCH
                LOAD    s4, 7A          ; z
                CALL    LCD_PUTCH
                LOAD    s4, 65          ; e
                CALL    LCD_PUTCH
                LOAD    s4, 21          ; !
                CALL    LCD_PUTCH
                LOAD    s4, 00
MAIN90:
                CALL    DELAY20ms
                CALL    DELAY20ms
                CALL    DELAY20ms
                CALL    DELAY20ms
                CALL    DELAY20ms
                CALL    DELAY20ms
                CALL    DELAY20ms
                CALL    DELAY20ms
                CALL    DELAY20ms
                CALL    DELAY20ms
                OUTPUT  s4, LED        ; LED チカチカ
                ADD     s4, 01
                JUMP    MAIN90


LCD_INIT:       CALL    DELAY20ms
                CALL    DELAY20ms
                LOAD    s4, 30
                CALL    LCD_PUTCMD
                CALL    DELAY20ms
                LOAD    s4, 30
                CALL    LCD_PUTCMD
                CALL    DELAY1ms
                LOAD    s4, 30
                CALL    LCD_PUTCMD
                CALL    DELAY1ms
                LOAD    s4, 38
                CALL    LCD_PUTCMD
                CALL    DELAY100us
                LOAD    s4, 0F
                CALL    LCD_PUTCMD
                CALL    DELAY100us
                LOAD    s4, 06
                CALL    LCD_PUTCMD
                CALL    DELAY100us
                LOAD    s4, 01
                CALL    LCD_PUTCMD
                CALL    DELAY100us
                RETURN

LCD_PUTCH:      CALL    LCD_RS_1
                CALL    LCD_RW_0
                OUTPUT  s4, LCD_DATA
                CALL    LCD_E
                RETURN

LCD_PUTCMD:     CALL    LCD_RS_0
                CALL    LCD_RW_0
                OUTPUT  s4, LCD_DATA
                CALL    LCD_E
                RETURN

LCD_RS_0:       LOAD    s0, 00
                JUMP    LCD_RS
LCD_RS_1:       LOAD    s0, 01
LCD_RS:         OUTPUT  s0, LCD_CTRL_RS
                RETURN

LCD_RW_0:       LOAD    s0, 00
                JUMP    LCD_RW
LCD_RW_1:       LOAD    s0, 01
LCD_RW:         OUTPUT  s0, LCD_CTRL_RW
                RETURN

LCD_E:          LOAD    s0, 01
                OUTPUT  s0, LCD_CTRL_E
                CALL    DELAY1us
                LOAD    s0, 00
                OUTPUT  s0, LCD_CTRL_E
                CALL    DELAY1ms
                RETURN

; ------------------------------------------------------------------------------
; -- 時間待ち
; -- 50Mhz = 20ns
; -- 1命令 2クロック = 40ns
; -- s0,s1,s2,s3 
; -- 
; ------------------------------------------------------------------------------
DELAY1us:       LOAD    s0, 16
DELAY1us00:     SUB     s0, 01
                JUMP    NZ, DELAY1us00
                RETURN

DELAY100us:     LOAD    s1, 64
DELAY100us00:   CALL    DELAY1us
                SUB     s1, 01
                JUMP    NZ, DELAY100us00
                RETURN

DELAY1ms:       LOAD     s2, 0A
DELAY1ms00:     CALL    DELAY100us
                SUB     s2, 01
                JUMP    NZ, DELAY1ms00
                RETURN

DELAY20ms:      LOAD    s3, 14
DELAY20ms00:    CALL    DELAY1ms
                SUB     s3, 01
                JUMP    NZ, DELAY20ms00
                RETURN

; ------------------------------------------------------------------------------
; -- 割り込みルーチン
; -- 
; ------------------------------------------------------------------------------
INTERRUPT:
;               &lt;<コード>>
                RETURNI ENABLE

; ------------------------------------------------------------------------------
; -- 割り込みベクタ
; -- 
; ------------------------------------------------------------------------------
                ADDRESS 3FF
                JUMP    INTERRUPT

verilog のソース

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    10:28:22 04/24/2009 
// Design Name: 
// Module Name:    picolcd 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
`default_nettype none

module picolcd (
    input   wire CLK_50MHZ,
    output  wire LCD_E,
    output  wire LCD_RS,
    output  wire LCD_RW,
    output  wire [7:0] LCD_DB,
    output  wire [7:0] LED
);

wire RESET;     // DCMのLOCKED_OUTをロジカルなリセットにするのがいい
wire DCM01_CLKIN_IBUF_OUT;
wire DCM01_CLK0_OUT;
wire DCM01_LOCKED_OUT;
wire [9:0]	CPU00_ADDRESS;
wire [17:0]	CPU00_INSTRUCTION;
wire [7:0]	CPU00_PORT_ID;
wire [7:0]	CPU00_IN_PORT;
wire [7:0]	CPU00_OUT_PORT;
wire CPU00_READ_STROBE;
wire CPU00_WRITE_STROBE;
wire CPU00_INTERRUPT;
wire CPU00_INTERRUPT_ACK;

generate_reset_pulse generate_reset_pulse (
    .clock(DCM01_CLKIN_IBUF_OUT),
    .reset_pulse(RESET)
);

dcm01 DCM01 (
	.CLKIN_IN(CLK_50MHZ), 
	.RST_IN(RESET), 
	.CLKIN_IBUFG_OUT(DCM01_CLKIN_IBUF_OUT), 
	.CLK0_OUT(DCM01_CLK0_OUT),
	.LOCKED_OUT(DCM01_LOCKED_OUT)
);

kcpsm3 CPU00 (
 	.address(CPU00_ADDRESS),
 	.instruction(CPU00_INSTRUCTION),
 	.port_id(CPU00_PORT_ID),
 	.write_strobe(CPU00_WRITE_STROBE),
 	.out_port(CPU00_OUT_PORT),
 	.read_strobe(CPU00_READ_STROBE),
 	.in_port(CPU00_IN_PORT),
 	.interrupt(CPU00_INTERRUPT),
 	.interrupt_ack(CPU00_INTERRUPT_ACK),
 	.reset(RESET),
 	.clk(DCM01_CLK0_OUT)
);

lcd CPU00ROM (
	.address(CPU00_ADDRESS),
	.instruction(CPU00_INSTRUCTION),
	.clk(DCM01_CLK0_OUT)
);

lcdport_out lcd_port_out (
    .we(CPU00_WRITE_STROBE),
    .port(CPU00_PORT_ID),
    .data(CPU00_OUT_PORT),
    .lcd_data(LCD_DB),
    .lcd_e(LCD_E),
    .lcd_rs(LCD_RS),
    .lcd_rw(LCD_RW),
    .led(LED)
);

endmodule

////////////////////////////////////////////////////////////////////////////////
//  Generate 1shot pulse 
////////////////////////////////////////////////////////////////////////////////
module generate_reset_pulse (
    input wire clock,
    output wire reset_pulse
);

SRL16 #(.INIT(16'h00FF)) SRL16_inst (
    .Q(reset_pulse),
    .A0(1'b1),
    .A1(1'b1),
    .A2(1'b1),
    .A3(1'b1),
    .CLK(clock),
    .D(1'b0)
);

endmodule

////////////////////////////////////////////////////////////////////////////////
//  CPU00(PicoBlaze)  ADDRESS DECODER
////////////////////////////////////////////////////////////////////////////////
module lcdport_out (
    input wire we,
    input wire [7:0] port,
    input wire [7:0] data,
    output reg [7:0] lcd_data,
    output reg lcd_e,
    output reg lcd_rs,
    output reg lcd_rw,
    output reg [7:0] led
);
always @(posedge we)
begin
    case(port)
        8'h01:	lcd_data = data;
        8'h02:	lcd_e  = data[0];
        8'h03:	lcd_rs = data[0];
        8'h04:	lcd_rw = data[0];
        8'h05:  led = data;
    endcase	
end

endmodule

PicoBlaze で LEDピコピコ

PicoBlaze で LEDピコピコです。

PicoBlaze については、 http://www.xilinx.com/picoblaze に関連する情報と
PicoBlaze のアセンブラなどのダウンロードがあります。

  • ロイヤリティフリーで使用可
  • 8ビットマイコン
  • 全ての命令は2クロックで実行される
  • 16個のレジスタ / SCRACH PAD RAM(64Byte) / ROM(1K x 18bit)

マイコンは、アセンブラのソース(.psm)を KCPSM3.EXE でアセンブルします。
エラーが無ければHDLのソース VHDL と Verilog のソースが出力されるので
これをトップモジュールに組み込めば動くという寸法です。

xilinx からダウンロード出来る KCPSM3.ZIP の中には資料含めて一式入ってるので
大丈夫でしょう。また ug129 のユーザーガイドには日本語版PDF(日付古いですが…)
があるので、これもダウンロードしておけばいいと思います。

アセンブラのソース

		ADDRESS	000

INIT00:
		ENABLE	INTERRUPT

MAIN00:		LOAD	s5, 00

MAIN90:
		OUTPUT	s5, 01    ; ポート1に出力する
		ADD	s5, 01
		CALL	DELAY1s
		JUMP	MAIN90


; ------------------------------------------------------------------------------
; -- 時間待ち
; -- 50Mhz = 20ns
; -- 1命令 2クロック = 40ns
; -- s0,s1,s2,s3 
; ------------------------------------------------------------------------------
DELAY1us:	LOAD	s0, 17
DELAY1us00:	SUB	s0, 01
		JUMP	NZ, DELAY1us00
		RETURN

DELAY100us:	LOAD	s1, 64
DELAY100us00:	CALL	DELAY1us
		SUB	s1, 01
		JUMP	NZ, DELAY100us00
		RETURN

DELAY1ms:	LOAD	s2, 0A
DELAY1ms00:	CALL	DELAY100us
		SUB	s2, 01
		JUMP	NZ, DELAY1ms00
		RETURN

DELAY20ms:	LOAD	s3, 14
DELAY20ms00:	CALL	DELAY1ms
		SUB	s3, 01
		JUMP	NZ, DELAY20ms00
		RETURN

DELAY1s:	LOAD	s4, 32
DELAY1s00:	CALL	DELAY20ms
		SUB	s4, 01
		JUMP	NZ, DELAY1s00
		RETURN

; ------------------------------------------------------------------------------
; -- 割り込みルーチン
; -- 
; ------------------------------------------------------------------------------
INTERRUPT:
;		&lt;<コード>>
		RETURNI ENABLE

; ------------------------------------------------------------------------------
; -- 割り込みベクタ
; -- 
; ------------------------------------------------------------------------------
		ADDRESS 3FF
		JUMP	INTERRUPT
</コード></code></pre>
<p>
Verilog のソース
</p>
<pre><code>
module main (
	input wire CLK_50MHZ,
	output wire [7:0] LED );

wire RESET;
wire CLKIN_IBUFG_OUT;
wire CLK0_OUT;
wire LOCKED_OUT;
wire 	[9:0]	address ;
wire 	[17:0]	instruction ;
wire 	[7:0]	port_id ;
wire 		write_strobe, read_strobe, interrupt_ack ;
wire 	[7:0]	out_port ;
wire 	[7:0]	in_port ;
wire		interrupt, reset, clk ;

user_reset reset00 (
	.CLOCK(),
	.RESET()
);

dcmsp00 dcmsp00 (
	.CLKIN_IN(CLK_50MHZ), 
	.RST_IN(RESET), 
	.CLKIN_IBUFG_OUT(CLKIN_IBUFG_OUT), 
	.CLK0_OUT(CLK0_OUT),
	.LOCKED_OUT(LOCKED_OUT)
);

kcpsm3 CPU00 (
 	.address(address),
 	.instruction(instruction),
 	.port_id(port_id),
 	.write_strobe(write_strobe),
 	.out_port(out_port),
 	.read_strobe(read_strobe),
 	.in_port(in_port),
 	.interrupt(interrupt),
 	.interrupt_ack(interrupt_ack),
 	.reset(RESET),
 	.clk(CLK0_OUT)
);

led CPU00LED (
	.address(address),
	.instruction(instruction),
	.clk(CLK0_OUT)
);

outp_sel outp_sel (
	.port_id(port_id),
	.write_strobe(write_strobe),
	.indata(out_port),
	.otdata(LED)
);

endmodule

//
// Generate RESET PULSE
//
module user_reset (
	input wire CLOCK,
	output wire RESET );

   
   SRL16 #(.INIT(16'h00FF))	// Initial Value of Shift Register
     SRL16_inst (
      .Q(RESET),			// SRL data output
      .A0(1'b1),			// Select[0] input
      .A1(1'b1),			// Select[1] input
      .A2(1'b1),			// Select[2] input
      .A3(1'b1),			// Select[3] input
      .CLK(CLOCK),		// Clock input
      .D(1'b0)				// SRL data input
   );

   // End of SRL16_inst instantiation
endmodule

module outp_sel (
	input wire port_id,
	input wire write_strobe,
	input wire [7:0] indata,
	output reg [7:0] otdata
);

	always @(posedge write_strobe)
		begin
			if(port_id == 1)
				otdata = indata;
		end		

endmodule

hp 200LX をハードリセット

ずっと放置したままの hp 200LXの電池交換をしましたが、放置していたのでバックアップ電池も乾電池もなくなっていたので初期化されている状態です。
私のはPCカードスロットは 48MB のコンパクトフラッシュ(Aドライブ)を入れたままの使い方なのでJKITもそのままAドライブに入れたままです。CTRL+ALT+DEL で再起動すると、C:\LXEMM.DAT が無いと言われます。う~ん 完璧に忘れてます。

ということで、LXEMM.DAT の再作成手順をググる。

シスマネ Applicationl->Terminate All でシスマネを終了してDOSプロンプトを出す。
そして、A:\JKIT\EMSINST 30 を実行して LXEMM.DAT を作成する。30はページ数のことで日本語FEPのWX2で10ページで残りはmifesとかページャとかのアプリで使う分で確保です。

あとハードリセット方法もメモっておく
CTRL+SHIFT+ON

というか、2008年2月現在でも日本hpのWEBサイトからマニュアルをスキャンしたPDFファイルがダウンロード出来るのでLX使いの人はダウンロードしときましょう。

20110306 ヴァイオリンレッスン63回目

会社の当番というのがあるので、車にスーツとカバン積んで教室へ行きました。

  • 楽器のチューニング
  • 篠崎バイオリン教本2
  • 3, 4番 ハ長調音階
  • 6, 7, 8, 9番 右手弓の練習
  • 8番 アマリリス
  • 9番 イ調短音階
  • 11番 ロシア舞曲

先週の今週で、あまり練習は出来ていません。上の右手弓の練習で、
移弦の際に余計な音は出さない。弓がちゃんと隣りの弦に移動してから
発音させましょう。あと、今日は最初から最後までネックのギター握りの指摘。
ついついやっちゃいます。

「アマリリス」は前回に続いて3回目のレッスンです。
今回も前回と同様とにかく最後まで弾いてみて、そこから先生が気になったところを修正していきます。

  • ピチカートで弦をはじく人差し指の位置。指板ENDから3センチ程度。ただ表現によって駒寄りとか場所は変化します。
  • ピチカートの方法は教本みたいに親指を指板に添えてもいいし、弓握ったまま人差し指だけでピチカートしてもいいです。

あとは、ちゃんと弦を押えきれてないところで音が弱いと注意されました。
ビブラートは、かけられるんだったら積極的にかけるようにしましょう。(音程確認のときは別)
ただし、ギターのように早めというよりかは、ゆっくりめからいきましょうということでした。
まぁ、まだちょびっとしかビブラートは出来ません。
先生のお手本も最近は普通に弾くモードでのお手本になってきてます。

「ロシア舞曲」は前回から2回目。いくつかアドバイスもらいながら3回くらい弾いてみます。
弾き方は舞曲なんでだらだら弾くんじゃなくて、もうちょっと切れのいい感じ。

教本17番「メヌエット」もう時間切れなのですが、最初の8小節だけ弾いてみました。
これはバッハのやつなので、音程含めてキッチリやりましょうとのこと。えぇ~

次回のレッスンは3月13日の予定です。

AVR Studio 5.0 Beta をインストールしましたが AVRISP MKII のファーム更新に失敗した

ATMEL のサイト久しぶりに見に行ったら、AVR Studio 5.0 Beta があったので Windows XP に導入してみました。

そうしましたところ、私のところの環境では

  • Microsoft .NET Framework 4.0 Full Profile
  • Microsoft Visual Studio Isolated Shell 10.0
  • AVR Jungo USB Driver

が必要と言わました。そのまま [Install] ボタンで全部インストールしてくれました。で、AVR Studio 5.0 Beta を起動しますと、 4.18 とは違って今時のアプリケーションのようなメインウィンドウが表示されました。

ちなみに、このバージョンはToolchain も含まれているので gcc も一緒にインストールされています。8ビットAVRマイコン用は gcc-4.5.1、 32ビットAVRマイコンは gcc-4.4.3 のようです。

んで、AVR ISP MK II のファームアップデートをやってみます。

プログラマー側は、1.d で、AVR Studio5.0 Beta には 1.e が提供されているようですね。これはアップデートしてみようとボタンをポチりましたが、

トラップを拾ったみたいでVisual Studio のデバックする? と聞いてきました。何回かやってみましたがファームの更新は出来ませんでした。

壊れたままではいやなので、AVRISP MKII を 手動でファーム更新モードにして、 AVR Studio 4.18 でファームの上書きしてOKにしました。

やっぱベータ版ですね。

こわいので、JTAGICE のファームアップデートのテストは正式版リリース後ですね。

Xilinx WebPACK 13.1 をインストールした。

Xilinx の WebPACK 13.1 を vmware の仮想マシンにインストール。とりあえず C:\Xilinx は10GB くらい使用。しかし仮想マシンのディスク20GBで設定してて残り4GBちょい、アップデートきたら足りん。仮想ディスクの増やし方を調べとこ

あとは Veritak も導入して、今日は終り。以前作成したverilogソースが通るかはまた後で。今日はもう眠い。

 

アクセスカウンタ Counterize II を導入してみた。

Counterize II は結構前からあるカウンター・アクセス解析に使用出来るもののようで数年前からリリースされているようです。
ということで、私も入れてみました

導入そのものは簡単でダッシュボードから左サイドメニューのオウラグインのところから、Counterize II を検索して、表示されたやつを
インストールするボタンを押して自動でインストール。後はプラグイン編集のところに readme があったので見てみた。
んで、テーマ編集で、.php ファイルにカウンター値を表示するように記述を追加しました。

sidebar.php の最後のほうに

Today:&lt;?php echo  counterize_gethitstoday(); ??&gt; hits and
&lt;?php  echo  counterize_getuniquehitstoday(); ??&gt; IPs&lt;br /?&gt;
Total:&lt;?php echo  counterize_getamount(); ??&gt; hits and
&lt;?php  echo  counterize_getuniqueamount(); ?&gt; IPs

を入れてみたら、カウンターが表示されました。問題は理解せずに使用しているということです…