SBC6809ルーズキットの製作(中華HD63C09Pその後編)

2018/06/10

 前回eBayで購入したHD63C09P誤マーキング品の代替品が届きました。前回は中身がHD63C09EPでしたが、今回はどうかとドキドキしながらテストしたところ、仕入先を変えたとのことでHD63C09Pとして問題なく動作しました。

誤マーキング品のロットは、「4F1」でしたが、今回は、「4H1」でした。

別途、若松通商から正規品ロット「8B3」を入手しておきましたので、どこに差があるか調べると、

①外観

 中華HD63C09Pは、表面を削ったのち、レーザーマーキングでしたが、若松通商HD63C09Pは、印刷でした。

②電気的性能

 HD63B09PをHD63C09Pにリマーキングしているのではないかと、HD63B09PとHD63C09Pのスペックで差が出ているData Delay Time(t<sub>DDW</sub>)について、確認してみました。スペック上、HD63B09Pは、max110nS、HD63C09Pは、max70nSでしたが、常温で実測すると両者ともに15nSでした。中華HD63C09PのD0は、わずかになまりぎみですが、t<sub>DDW</sub>の有意差がないことから両者ともにHD63C09Pとみなせると思います。


このことから、リマーキングの目的は、入手元(横流元?)をわからなくさせるためにしたのではないかと推測できます。



若松通商HD63C09P(CH1:Q、CH2:D0、CH3:-WE)、Q立ち上がりからD0の立ち上がりがt<sub>DDW</sub>です。



中華HD63C09P(CH1:Q、CH2:D0、CH3:-WE)、Q立ち上がりからD0の立ち上がりがt<sub>DDW</sub>です。


最近は、他の製品もリマーキング品が横行しています。電気的性能が劣るものもあり得るかと思いますので、注意深く確認するしかないと思います。

(再クロール更新:2022/12/22)

SBC6809ルーズキットの製作(リセット不良対策編)

2018/05/08

 SBC6809を楽しんでいると、電源オンしてもROMから立ち上がらない場合が時々あることがありました。気になったので調べてみると、電源スイッチを切っても電源電圧が下がり切っていないことがわかりました。さらに調べると、USB-Serial BridgeのTXDから電源にHD63B50Pの入力寄生ダイオード経由で18mA程度の電流が回り込みしていました。


今回、全面的にCMOS化したため、わずかな消費電流がゆえに電源電圧が下がり切っていないようです。このため、CPUのリセット回路コンデンサーの電圧が下がりきれず、本来の電源が投入されてもCPUリセットがかからない状態が発生したと考えられます。


CMOSならではの問題です。NMOSのMC6850Pを使用した場合は、入力寄生ダイオードがないため、発生しないはずです。また、CMOSのHD6350Pを使用した場合でも、CPUがMC6809やTTLロジックを使っていれば、消費電流が大きいため、問題が起きにくいと考えられますが、電流が増えるため、USB-Serial Bridge側へのストレスが若干心配になります。銅箔カットが必要ですが、HD6350PのRXD入力に1K程度の直列抵抗を入れる対策も一案です。


SBC6809の電源を入れたのち、USB-Serial Bridgeに接続すれば良いのですが、ROM立ち上げメッセージを表示したい場合は、問題です。このため、対策としてダイオードD1を電圧検出器に交換することで、解決できました。良くある問題ですが、またレトロっぽくなくなりました。電圧検出器は、たまたま手持ちのSEIKO製S80830CNY(3.0V検出)を使用しました。


下記のような回路に改造することになりますが、またピンバイスとドリル刃の登場です。D1の電源側の隣に穴をあけ、S80830CNYのVSSをこの穴を通して、GNDランドにはんだ付けすれば、D1の置き換えができます。調子が良くなりました。


(再クロール更新:2022/12/22)

SBC6809ルーズキットの製作(シリアル通信速度自動設定編)

2018/05/07

 SBC6809ルーズキットには、データパックが提供されています。この中に通信クロック用のosc1536.hexが添付され、9600bps用のクロックを生成することができます。9600bpsは、レトロな雰囲気を出すぴったりの速度ですが、今後プログラムのダウンロードを考えた場合、心配が残ります。そこで、通信クロック周波数の自動検出ができるPIC12F1822プログラムを作成してみました。


下記のプログラムは、PIC12F1822の3ピンにRXDを接続し、2秒間以上の無通信区間後に、CRコードを打つと、そのマークビットの時間計測を行い、9600、19200、38400、57600、115200に対応したクロックを生成できるようにしてあります。電源投入後、30秒以内に行うことを想定しています。


ここで、115200の場合、クロック周波数偏差の問題が残ります。これは、OSCTUNEによる内部クロックの調整範囲には限界があるようで、実測では、115200の場合1940kHzで、5%強の偏差がありますが、今のところ、特に問題なく使用できています。


シリアルクロックの許容偏差は、通常の使用ではスタートビットの中央から8ビットデータの後、1ストップビットが正しく認識できるためには、9ビット分の時間経過後、0.5ビット以内の誤差が必要要件となりますので、最大許容偏差は±5.6%になります。

PIC12F1822のクロック偏差は、実測で+5.25%でしたので、あまりマージンがありません。USB-Serial Bridgeのクロック精度によっては、フレーミングエラーが発生する可能性があります。そのコントローラがPL-2303HXDの場合、クロックの最大偏差は、±2%ですので、クロック周波数がプラス動向に触れている場合は、良い方向になりますが、逆に振れるとエラーになる可能性が高くなります。したがって、五分五分ですので、実使用で安定性があるか確認し、使用できれば使用することができるレベルです。


/**************************************************************************/
/* Files to Include */
/**************************************************************************/

#if defined(__XC)
#include /* XC8 General Include File */
#elif defined(HI_TECH_C)
#include /* HiTech General Include File */
#endif

#include /* For uint8_t definition */

/**************************************************************************/
/* Configuration bits */
/**************************************************************************/

/* CONFIGURATION WORD 1 setting value */
#pragma config FOSC = INTOSC // INTOSC oscillator
#pragma config WDTE = OFF // WDT disabled
#pragma config MCLRE = ON // MCLR/VPP pin function is MCLR

/* CONFIGURATION WORD 2 setting value */
#pragma config PLLEN = ON // PLL Enable->4x PLL enabled

/**************************************************************************/
/* User Global Variable Declaration */
/**************************************************************************/

volatile uint16_t timer_tick;
uint16_t min_count;
uint16_t max_count;

/**************************************************************************/
/* Main Program (Auto Baud Rate Detection Program for MC6850) */
/**************************************************************************/

/* TIMER0 interrupt tick value */
#define IDLE_TIME 244 // idle tick of time -> 2s
#define TIMEOUT 3662 // timeout of auto detection -> 30s

/* I/O port bit assign */
#define RXD RA4 // PIN3 RA4 RXD sensing Digital Input

/* set PWM parameters */
void set_PWM(uint8_t period, uint8_t tune) {
OSCTUNE = tune; // Internal Oscillator Frequency Adjustment
PR2 = period; // set PWM Period
CCPR1L = (uint8_t)(period >> 1); // set PWM width
TMR2ON = 1; // Timer2 is on
}

/* get TIMER1 count of mark bit */
void get_mark_bit(uint8_t bits) {
uint16_t count;
while(!RXD); // wait space bit
TMR1ON = 0; // stop TIMER1 count
TMR1H = 0; TMR1L = 0; // clear TMR1H, TMR1L count
while(RXD); // wait mark bit
TMR1ON = 1; // start TIMER1 count
while(!RXD); // wait space bit
TMR1ON = 0; // stop TIMER1 count
count = ((uint16_t)TMR1H << 8) | TMR1L;
count >>= bits; // normalize count
if(count < min_count) min_count = count;
if(count > max_count) max_count = count;
}

void interrupt timer_isr(void) {
if(TMR0IF) { // timer0 interrupt
timer_tick++; // increment time tick in each 1/122 senconds
TMR0IF = 0; // clear timer0 interrupt
}
}

/* PIC12F1822 SBC6809 Baud Rate Generator with Auto Speed Detection */

#define PR2_9600 51 // PR2 value for 9600bps
#define PR2_19200 25 // PR2 value for 19200bps
#define PR2_38400 12 // PR2 value for 38400bps
#define PR2_57600 8 // PR2 value for 57600bps
#define PR2_115200 3 // PR2 value for 115200bps

#define MIN_9600 792 // min. TIMER1 count for -5% of 9600bps
#define MIN_19200 396 // min. TIMER1 count for -5% of 19200bps
#define MIN_38400 198 // min. TIMER1 count for -5% of 9600bps
#define MIN_57600 132 // min. TIMER1 count for -5% of 19200bps
#define MIN_115200 66 // min. TIMER1 count for -5% of 9600bps
#define MAX_9600 875 // max. TIMER1 count for +5% of 9600bps
#define MAX_19200 438 // max. TIMER1 count for +5% of 19200bps
#define MAX_38400 219 // max. TIMER1 count for +5% of 38400bps
#define MAX_57600 148 // max. TIMER1 count for +5% of 57600bps
#define MAX_115200 73 // max. TIMER1 count for +5% of 115200bps

/* Auto Speed Detection Sequence
* no mark bit in 2s and CR in 30s after powerup
*/

void main(void)
{
/* initialize oscillator */
OSCCON = 0b11110000; // PLL Is enabled by CONFIGURATION WORD 1
// 8 MHz or 32 MHz HF
// Clock determined by CONFIGURATION WORD 1

/* initialize PIN assignment */
CCP1SEL = 0; // PIN5 CCP1 on RA2
ANSELA = 0; // Digital I/O. Pin
TRISA = 0b11111011; // PIN3 RA4 Digital Input
// PIN5 CCP1 on RA2 Digital Output
WPUA4 = 1; // PIN3 RA4 Pull-up enabled

/* initialize timer */
OPTION_REG = 0b00000111; // Weak pull-ups are enabled
// Interrupt on falling edge of RB0/INT pin
// Internal instruction cycle clock (FOSC/4)
// Increment on low-to-high transition on T0CKI pin
// Prescaler is assigned to the Timer0 module
// Prescaler Rate Select bits (1 : 256)
T1GCONbits.TMR1GE = 0; // always counting
T1CON = 0b00000000; // Timer1 clock source is FOSC/4
// 1:1 Prescale value
// LP OSC disabled
// clock synchronization disabled
// Stops Timer1
TMR1H = 0; TMR1L = 0; // clear TMR1H, TMR1L count
timer_tick = 0; // reset timer

/* initialize interrupt setting */
PIR1 = 0; // clear peripheral interrupt flag
PIR2 = 0; // clear peripheral interrupt flag
INTCON = 0b11100000; // global interrupt enabled
// periferal interrupt enabled
// timer0 interrupt enabled
// external interrupt disabled
// interrupt-on-change disabled
// clear timer1 interrupt flag
// clear external interrupt flag
// clear interrupt-on-change flag

/* initialize PWM */
T2CONbits.T2CKPS = 0b00; // Prescaler is 1
CCP1CON = 0b00001100; // Single output; P1A modulated
// the two LSbs of the PWM duty cycle = 00
// PWM mode: P1A active-high
set_PWM(PR2_9600, 0); // start baud rate generator for 9600bps

/* sensing loop */
while(1) {
timer_tick = 0;
while(timer_tick < IDLE_TIME) { // wait for no mark bit in 10s
if(!RXD) { // if mark bit then reset timer
timer_tick = 0; // reset timer
}
}
timer_tick = 0; // reset timer
min_count = 32767; // reset min_count
max_count = 0; // reset max_count
/* CR($0D) 1-0-1011-0000-1
* 1 1 4bit */
get_mark_bit(0); // 1 mark bit
get_mark_bit(0); // 1 mark bit
get_mark_bit(2); // 4 mark bit
if(min_count > MIN_9600 && max_count < MAX_9600) {
set_PWM(PR2_9600, 0); break;
} else if(min_count > MIN_19200 && max_count < MAX_19200) {
set_PWM(PR2_19200, 0); break;
} else if(min_count > MIN_38400 && max_count < MAX_38400) {
set_PWM(PR2_38400, 0); break;
} else if(min_count > MIN_57600 && max_count < MAX_57600) {
set_PWM(PR2_57600, 31); break;
} else if(min_count > MIN_115200 && max_count < MAX_115200) {
set_PWM(PR2_115200, 32); break;
}
if(timer_tick > TIMEOUT) { // check timeout
break;
}
}
while(1); // done.
}

(再クロール更新:2022/12/22)

SBC6809ルーズキットの製作(アセンブル・動作確認編)

2018/05/03

まず、使い勝手が良い6809アセンブラを探しました。条件としては、

①ソースコードが開示されている(改良の余地あり)

②Windows上で動作可能

③HD6309の命令を扱える

④MC6800の命令を扱える

⑤できれば、マクロ命令が定義できる


比較的良いアセンブラとして"asm6809-6809 cross-assembler"が見つかりました。GPLのアセンブラで、win32、win64のバイナリも公開されています。MC6800命令対応は、マクロで記述する必要があり、例えば、INXは、

INX     MACRO
LEAX 1,X
ENDM

順番に、①ECHOBACK TEST、②MS-BASIC、③MPB6809 monitor、④CHK309をアセンブルしてみました。SBC6809対応として必要な変更箇所は、プログラムの先頭アドレスを$E000に、UART(MC6850)の先頭アドレスを$8018にすることです。

このアセンブラの欠点は、コメントを";"から始めないといけないので、ソースの修正が必要になる場合が多いことです。また、"--setdp $00"オプションを入れないと、ゼロページアドレスが16bitになってしまいます。


ホームページは、下記です。

http://www.6809.org.uk/asm6809/


さて、EEPROMに下記の4つのROMイメージを全部書き込みました。これで4つのプログラムを簡単に切り替えられます。

A14     A13     ページ切替
1 1 ECHOBACK TEST
1 0 MS-BASIC
0 1 MPB6809 monitor ver1.00
0 0 CHK309 - PROCESSOR CHECK PROGRAM

まず最初は、ECHOBACK TESTです。電源を入れても、シリアル出力がありませんでした。調べてみると、手持ちのUSB-Serial Bridgeは、RDとTXのみしかないので、CTS-、RTS-の処理が必要でした。ジャンパワイヤーで、CTS-とRTS-を接続したところ、表示が出るようになり、キー入力のコールバックも問題ありませんでした。


次は、MS-BASICです。これも問題ありませんでした。BASICの仕様が気になったので、ソースコードを調べてみると、下記のコマンドとファンクションが使えるようです。このBASICは、元々1980年に発売された"Tandy TRS-80 Color Computer"に搭載された2種類のBASIC("Extended BASIC ROM"と"Color BASIC ROM")の逆アセンブルソースを出版した"Extended BASIC Unravelled II"と"Color BASIC Unravelled II"を基にしてGrant Searleさんが、FPGA化した6809 SBC用にマージ・編集したようです。

(1)COMMAND LIST	
CLEAR CONT DATA
DEF DEL DIM
EDIT END EXEC
FOR GOTO IF
INPUT LINE LIST
NEW NEXT ON
POKE PRINT READ
REM ' ELSE
RENUM RESTOR RETURN
RUN STOP TROFF
TRON

(2)FUNCTION LIST
ABS ASC ATN
CHR$ COS EXP
FIX HEX$ INKEY$
INSTR INT LEFT$
LEN LOG MEM
MID$ PEEK POS
RIGHT$ RND SGN
SIN SQR STR$
STRING$ TAN USR
VAL VARPTR
標準的なMS-BASICのリファレンスマニュアルを見つけましたので、下記に紹介します。

http://chiclassiccomp.org/docs/content/computing/Microsoft/Microsoft_Basic_8086Xenix_Reference.pdf


次のMPB6809 monitorもクリアしました。今後、時間ができたらEEPROM書き込みコマンドを追加したいところです。最後に、CHK309ですが、判定結果は、"6309/6309E"でした(予想通りです)。


動作確認の最後に、3MHz動作時のHD63B50Pのタイミングマージンを測定しました。常温での測定ですが、動作可能範囲との結果が得られました。HD63C09EPとHD63B50Pは、結構高速ですね。


①E信号のHigh期間が、162nS

 HD63B50Pのスペックでは、min.220nSですので、マージンは、162-220=-58nSになります。

②E信号立下りからCPUアドレス遅延+74AC138遅延が、54nS

 CPUスペックのアドレス遅延110nS+74AC138スペックの遅延12nSでmax.122nSに比べ、かなり高速です。HD63B50PのE信号立上りアドレスセットアップ時間が、min.40nSですので、マージンは、162-40-54=68nSになります。

③E信号立上りからHD63B50Pのデータ遅延が、29nS

 HD63B50Pスペックのデータ遅延max.150nSに比べかなり高速です。CPUのE信号立下りデータセットアップ時間は、min.40nSですので、 マージンは、162-40-29=93nSになります。


以上、①がスペック割れですが、②と③のマージンに依存している数値と思われますので、厳しい方と相殺すれば都合68-58=14nSのマージンがあり、温度上昇等でマージンが悪化しなければ、十分動作可能になります。ROMとRAMアクセスについては、100nS品を使いましたので、問題ありません。

(再クロール更新:2022/12/22)

SBC6809ルーズキットの製作(中華HD63C09P編)

2018/05/02

 日立のCMOS LSIは、すべてeBayで調達しました。その中で心配なのは、やっぱりHD63C09Pです。基板の改造後、組み立てを行い、まずHD63C09Pからテストです。予想通りクロックが発振しません。 38pinの電圧を調べるとやはり5Vで、中身がHD63C09EPの証拠です。


eBayの出品者に返品クレーム(英語と写真で交渉)をしたところ、別の仕入れ先からの交換品を送ってくれるとのことになりました。交換品をしばらく待つ必要がありますが、待ってばかりではさびしいので、基板を追加改造してHD63C09PとHD63C09EPの両方に対応できるようにしました。


①基板へTSC(39pin)のGNDジャンパ追加

②E,Q信号発生モジュールの製作

 場所が限られていますので、小型の表面実装部品と1.27mmピッチの蛇の目基盤を使い、組立てましたが、これまたルーペを必要とする半田づけになりました。

 下記は、E,Q信号発生モジュールの回路と写真です。






③基板へE,Q信号発生モジュール用ソケット追加

 HD63C09EPを使う場合は、TSCをジャンパを有効にし、E,Q信号発生モジュールをソケットに差し込みます。下記が、追加改造後の基板と追加モジュールです。


(再クロール更新:2022/12/22)

SBC6809ルーズキットの製作(改造編)

2018/05/01

 最近SBC6809ルーズキットを知り、6809が懐かしく早速スイッチサイエンスさんから基板を購入しました。せっかく製作するので、ルーズキットを改造して機能・性能を強化し、日立のCMOS LSIで統一してみました。①RAM 32KB化②ROM 8KB×4ページ化③EEPROMプログラミング④ROM 28KB化⑤HD63C09P⑥3MHz動作が可能になります。


下記は、改造後の基盤です。





改造のポイントは下記内容ですが、銅箔カットはデザイン用カッターナイフとルーペで細かな作業になります。半田付時の再ショート防止のために、カット溝に尖がらした爪楊枝を使って、エポキシ接着剤をわずかに充填しました。


①32KB RAMの搭載(HM62256BLSP-10)

 ・RAM 1pin->GNDのカット、CPU A14->RAM 1pin

 ・RAM 26pin->VCCのカット、CPU A13->RAM 26pin

 ・74138 15pin->RAM 20pinのカット、CPU A15->RAM 20pin

②32KB ROM(HN27C256AG-10)と8KBページ切替で、4つのプログラムROMを搭載可能

 ・ROM A14信号を作成し、ショートジャンパで、GNDとCPU A14切替

 ・ROM 26pin->VCCのカット、ROM 26pinをショートジャンパで、GNDとCPU A13切替

③ページ切替なしで、最大28KBの連続ROM

 ・7400 9pin->GNDのカット、CPU A15->7400 9pin

 ・7400 10pin->GNDのカット、74138 11pin->7400 10pin

 ・74138 7pin->ROM 20pinのカット、7400 8pin->ROM 20pin

 ・74138 4pin->GNDのカット、CPU A12->74138 4pin

④EEPROM(HN58C256AP-10)搭載可能で、自己書き込み可能(後日、プログラム作成予定)

 ・ROM 1pin->VCCのカット、ROM 1pinをショートジャンパで、VCCとROM A14切替

 ・ROM 27pin->VCCのカット、ROM 27pinをショートジャンパで、RAM 27pinとROM A14切替

⑤HD63C09P搭載で3MHz動作

 ・水晶振動子をソケット化

⑥HD63B50P搭載し、READアクセスタイムを稼ぐために74AC138を使用、3MHz動作(実力)

 動作確認後、信号の遅延を測定し、タイミングマージンを測定したいと思います。


基板にピンヘッダーのための穴をピンバイスとドリル刃で開けます。ピンヘッダーは、エポキシ接着剤で基板に固定後、リード線を半田付けします。


変更部分の概略回路とジャンパー設定をまとめると、次のようになります。

(再クロール更新:2022/12/22)