家庭菜園のニンジン、よく育っているのだけど、隣にもよく育っているのがあ
るので(育ってないところはどれも育ってない。土の関係なのだろうか)、泣く
泣く間引きした一本。まだまだ小さいけれどかなりニンジンっぽくなってきて
ます。洗って食べてみました。こんなに小さくてもニンジンの風味がする。

ノギスを使ってフライス用のDROをAKI-H8/3052ボードで作ってみる計画の続きです。
ノギスのデータラインもLM339Nで増幅させて、PortAの0に接続しました。Port Aもシュミット入力。
まずはポーリングでデータをとってみました。クロックの立ち下がりでデータ を読みます。
H8のタイマユニット(ITU)を使っていろいろ測ってみます。これはSH3のとは まったく違って、パルス出力のための仕組みが入っていたりしてH8らしいデバ イスだ。
ITU0のTSRはread modify writeじゃないと挙動が不安定になるのにちょっとは まった。(全部クリアだから..といきなり0を書きこんで失敗)
ということで、ノギスデータ読みこみの後半24clockだけポーリングして読むこ とにしました。
信号の最初の立ち下がりをIRQ0で受けてタイマーを起動。タイマーのコンペア の二つは読み出すべきデータの直前(A)と、その後(B)に設定。データ前のタイ マA割りこみで最初の立ち下がりを検出するためにIRQ0をオン。IRQの最初の立 ち下がりでIRQ0の割りこみをオフにして、そのまま割りこみハンドラの中で24 クロック、ポーリングでデータ読みこみ。読み込み終わって十分たった所でタ イマBの割りこみが入るのでここでまたIRQ0をオンにして次のデータ信号のトリ ガを待つ。

ノギスを使ってフライス用のDROをAKI-H8/3052ボードで作ってみる計画の続きです。
ノギスのデータラインもLM339Nで増幅させて、PortAの0に接続しました。Port Aもシュミット入力。
まずはポーリングでデータをとってみました。クロックの立ち下がりでデータ を読みます。
void
test ()
{
int read_data, clock_cnt, bank, phase_start;
int i, k;
uint32_t data[2];
int d0, d1;
SCI_PRINTF("polling mode\n");
#define CLOCK 0x1
#define DATA 0x1
P8->DDR = 0;
PA->DDR = 0;
// Digital caliper clock signal
// (A)BC C C C D C C C E (F)
//
// ---------___|_|_...|_|____|_|_...|____--------
//
read_data = 0, bank = 0, clock_cnt = 0;
phase_start = 0;
while (/*CONSTCOND*/1)
{
/* Wait for falling edge (2 pattern) */
// C C // (A)
// v // v
// +--+ +--+ or -------------+
// | | | | // |
//_____| |___| |___// |____
//
for (i = 0; (P8->DR & CLOCK); i++) /* HIGH */
;
/* Now falling edge */
// C C // (A)
// v // v
// +--+ +--+ or -------------+
// | | | | // |
//_____| |___| |___// |____
//
if (read_data)
{
if (PA->DR & DATA)
data[bank] |= (1 << clock_cnt);
clock_cnt++;
}
phase_start = i > 0x2000; // (A) new phase
/* Wait for rising edge (3 pattern) */
// C C // D // E (F) // (A) B
// v // v // v // v
// +--+ +--+ or -+ +--+ or +--+ +---------- or ---------+ +--+
// | | | | // | | | // | | | // | | |
//_____| |___| |___// |_____________| |_ // _| |_______| // |________| |__
//
for (k = 0; !(P8->DR & CLOCK); k++) /* LOW */
;
/* Now rising edge */
// C C // D // E (F) // (A) B
// v // v // v // v
// +--+ +--+ or -+ +--+ or +--+ +---------- or ---------+ +--+
// | | | | // | | | // | | | // | | |
//_____| |___| |___// |_____________| |_ // _| |_______| // |________| |__
//
if (k < 50)
continue; // clock signal pattern.
if (read_data) // D region(k = 212) or E region(k = 131).
{
if (bank == 0) // (D-region)
bank = 1, data[bank] = 0, clock_cnt = 0;
else // (E-region)
{
read_data = 0;
d0 = data[0];
d1 = data[1];
if (d0 & (1 << 23))
d0 |= 0xff000000;
if (d1 & (1 << 23))
d1 |= 0xff000000;
SCI_PRINTF ("%d %d %d %d\n",d0 + d1, d0 >> 3, d1 >> 3, clock_cnt);
}
}
if (phase_start) // B-region(k = 98).
{
read_data = 1;
bank = 0, data[bank] = 0, clock_cnt = 0;
}
}
}
結果
-6617 -3173 2345 24
-6617 -3711 2883 24
-6617 -3731 2903 24
-6617 -3730 2902 24
-6617 -3731 2903 24
-6617 -3730 2902 24
-6617 -3731 2903 24
-6617 -3731 2903 24
-6617 -3731 2903 24
-6617 -3731 2903 24
-6617 -3731 2903 24
-6617 -3730 2902 24
-29840 -3730 -1 24←ここでノギスのzero reset.
-29840 -3730 -1 24
-29840 -3730 -1 24
-29840 -3730 -1 24
-29840 -3730 -1 24
-29840 -3730 -1 24
-29840 -3730 -1 24
-29840 -3730 -1 24
-29840 -3761 30 24
-29840 -4239 509 24
-29840 -4533 802 24
100mmで10078
50mmで5038
リニアにずれる。
d1はノギス値*8
d0+d1が固定になるようにd0は選ばれる。ゼロリセットでd0の値は変わらない。
なんとか読めた!一軸ならこれでもいいのだけれど、XYZ三軸とりこみたいので
割りこみドリブンにしてみます。
H8のタイマユニット(ITU)を使っていろいろ測ってみます。これはSH3のとは まったく違って、パルス出力のための仕組みが入っていたりしてH8らしいデバ イスだ。
ITU0のTSRはread modify writeじゃないと挙動が不安定になるのにちょっとは まった。(全部クリアだから..といきなり0を書きこんで失敗)
#pragma interrupt
void
itu0_a ()
{
t0 = ITU0->TCNT;
ITU0->TSR &= ~ITU0_TSR_IMFA; // clear flag.
}
このt0によって、GRAとコンペアマッチしてからどのくらいの時間で割り込み
処理を開始できるか測ってみたところ、モニタ上で9.6us、ロム上でも3.2us
かかっていた。しかしこのコードは-Oでオプティマイズをかけていても
000fe566 <_itu0_a>: fe586: 01 00 6d f2 01 00 6d f2 mov.l er2,@-er7 fe58a: 01 00 6d f3 01 00 6d f3 mov.l er3,@-er7 fe58e: 2a 68 2a 68 mov.b @0x68:8,r2l fe590: 0d a3 0d a3 mov.w e2,r3 fe592: 0c b3 0c b3 mov.b r3l,r3h fe594: 0c 2b 0c 2b mov.b r2h,r3l fe596: 0c a2 0c a2 mov.b r2l,r2h fe598: 18 aa 18 aa sub.b r2l,r2l fe59a: 0d 3a 0d 3a mov.w r3,e2 fe59c: 7a 62 00 00 7a 62 00 00 ff 00 and.l #0xff00,er2 fe5a0: ff 00 fe5a2: 2b 69 2b 69 mov.b @0x69:8,r3l fe5a4: 14 ba 14 ba or.b r3l,r2l fe5a6: 6b a2 00 0f 6b a2 00 0f e6 48 mov.w r2,@0xfe648:32 fe5aa: e6 48 fe5ac: 7f 67 72 00 7f 67 72 00 bclr #0x0,@0x67:8 fe5b0: 01 00 6d 73 01 00 6d 73 mov.l @er7+,er3 fe5b4: 01 00 6d 72 01 00 6d 72 mov.l @er7+,er2 fe5b8: 56 70 56 70 rteこんなコードを吐かれてしまう。アセンブラで書き直し。 bset, bclr, bnot, bst, bist命令はバイト単位でread modify writeする 命令なので、ITU0->TSRのフラグクリアはこれだけでいい。
.global _itu0_a _itu0_a: mov.l er0, @-er7 mov.w @0xff68:16, r0 mov.w r0, @_t0 bclr #0x0, @0x67:8 mov.l @er7+, er0 rteこれにすると1.28us縮まる。なのでロム上で1.92us。データシートによると割 り込み応答時間 19〜41 実行中の命令が終了するまでの待ちに依存。なので (.76us〜1.64us)で割り込み処理に入るということなのでまぁそんなとこかな。 なんにしろ、1クロック13usのノギスの信号毎に割り込み入れるのはちょっと無 理。一軸でもギリギリなのに三軸にしたらまったく時間的余裕がない。
ということで、ノギスデータ読みこみの後半24clockだけポーリングして読むこ とにしました。
信号の最初の立ち下がりをIRQ0で受けてタイマーを起動。タイマーのコンペア の二つは読み出すべきデータの直前(A)と、その後(B)に設定。データ前のタイ マA割りこみで最初の立ち下がりを検出するためにIRQ0をオン。IRQの最初の立 ち下がりでIRQ0の割りこみをオフにして、そのまま割りこみハンドラの中で24 クロック、ポーリングでデータ読みこみ。読み込み終わって十分たった所でタ イマBの割りこみが入るのでここでまたIRQ0をオンにして次のデータ信号のトリ ガを待つ。
24clock 24clock
----+ +-+ +-+ +-+ +-+ +-+ +-+ +-------〜330ms---
| | | | | | | | | | | | | | ↑
| | | | | | | | | | | | | | [TimerB割り込み]
+-52us-+ +-+ +....+ +---112us---+ +-+ +...+ +--70us-+ IRQ0割り込みON
| ↑ ↑ タイマOFF
↓ [TimerA割り込み]| |
[IRQ0割り込み] IRQ0割り込みON | |
IRQ0割り込みOFF | [IRQ0割り込み] |
タイマを起動 | IRQ割り込みOFF |
+-----------------------+ 24clockポーリングでデータ読みこみ |
| |
+-------------------------------------------------------------+
という方針でこれ。GRAの1200(384us)とGRBの4000(1280us)はちょうどいいとこ
を狙って設定。クロックの最初のトリガでデータを読みこむのはタイミング的
にどうしても辛いので、スキップしてclock_cntは1から。データの下3bitは
0.001mm以下のところになるので問題ない。最終的に捨ててしまうし。このあた
りの設定は泥くさいけれど、仕方ない。モニタからロムに持っていったところ
で多少パラメータの修正もいるかも。
int data_phase, clock_cnt;
int dro0;
void
test ()
{
SCI_PRINTF("interrupt mode\n");
// DRO0 clock signal connected to Port 8:0
P8->DDR = 0;
// DRO0 data signal connected to Port A:0
PA->DDR = 0;
// External interrupt setting.
*ISCR |= 0x1; // Falling edge.
*IER |= IER_IRQ0E; // interrupt enable.
// DRO0 Timer
ITU->TSTR &= ~ITU_TSTR_STR0; // timer 0 stop
// Internal clocl/8, Don't clear TCNT.
ITU0->TCR = ITU0_TCR_ICLK8;
ITU0->TIOR = 0; // compare match. don't output.
ITU0->TIER = 0; // disable interrupt here.
ITU0->TCNT = 0;
ITU0->GRA = 1200;
ITU0->GRB = 4000;
ITU->TSTR |= ITU_TSTR_STR0; // timer 0 start
data_phase = 0;
clock_cnt = 0;
intr_enable ();
while (/*CONSTCOND*/1)
asm volatile ("sleep");
}
#pragma interrupt
void
irq0 ()
{
// Disable IRQ0 interrupt.
*IER &= ~IER_IRQ0E;
if (data_phase)
{
// Data sampling. skip 1st bit.
for (clock_cnt = 1, dro0 =0; clock_cnt < 24; clock_cnt++)
{
while (!(P8->DR & 0x1)) /* LOW */
;
/* Wait for falling edge */
while (P8->DR & 0x1) /* HIGH */
;
if (PA->DR & 0x1)
dro0 |= 1 << clock_cnt;
/* Wait for rising edge */
}
}
else
{
data_phase = 1;
// TSR must be read modify write.
ITU0->TSR &= ~(ITU0_TSR_IMFA | ITU0_TSR_IMFB | ITU0_TSR_OVF);
ITU0->TCNT = 0;
// Enable ITU0
ITU0->TIER = ITU0_TIER_IMIEA | ITU0_TIER_IMIEB;
// Timer 0 start.
ITU->TSTR |= ITU_TSTR_STR0;
}
}
#pragma interrupt
void
itu0_a ()
{
// Enable IRQ0 for sampling data.
*ISR &= ~IER_IRQ0E;
*IER |= IER_IRQ0E;
ITU0->TSR &= ~ITU0_TSR_IMFA; // clear flag.
}
#pragma interrupt
void
itu0_b ()
{
ITU0->TIER =0; // Disable ITU0 interrupt until next irq0()
ITU0->TSR &= ~ITU0_TSR_IMFB; // clear flag.
ITU->TSTR &= ~ITU_TSTR_STR0; // timer 0 stop
if (dro0 & (1 << 23))
dro0 |= 0xff000000;
SCI_PRINTF ("%d %d\n", dro0 >> 3, clock_cnt);
// Enable IRQ0
*IER |= IER_IRQ0E;
data_phase = 0;
}
なんとかものになりそうな気がしてきた!
