フォト
無料ブログはココログ

CDP1802/COSMAC

2018年4月24日 (火)

lcc1802

 以前書いた記事(CDP1802 (15/10/11))のコメントにCDP1802用のCコンパイラの質問があったので調べてみた。 

 結論は、出力されるバイナリが大きいので、RAMを十分載せておけば使える。

lcc1802

 CDP1802は入手したがまだ動かしていない。 (^^;
SBCを作ったとしても、おそらくtinyBASICでも動かしたら満足するのだろう。というわけで、CDP1802用のCコンパイラは調べていなかった。

 調べてみるとlcc1802が見つかった。
lccはOpen SourceのコンパイラでターゲットCPUはAlpha,SPARC,MIPS,x86に対応している。 lcc1802はlccをCDP1802に対応させたもので、COSMAC ELF Membersip Cardのアドオンシールドにarduinoを持たせた 1802 olduino 用に作られたもののようだ。 
https://sites.google.com/site/lcc1802/downloads
からダウンロードできる。

インストール

 lcc42judy.zipをインストールしてみた。
zipを解凍して現れるlcc42ディレクトリをCドライブ直下(C:\)にコピーしろと書いてある。
開発系は C:\Devzにインストールしているので、ここにインストールした。 コンパイル・ドライバ(lcc)が呼び出すコマンドは同じディレクトリを探すので問題はないだろうと考えたのだが、cppが見付からないと怒られた。(^^;
どうやら、プリプロセッサ(cpp.exe)、コンパイラ(rcc.exe)、アセンブラ(asw.exe)のパスは"C:\lcc42\bin"がハードコードしてあるようだ。 仕方がないので、C:\からinkを張っておいた。

エミュレータ

 まだSBCを作っていないのでCOSMACエミュレータ Emma 02で試してみた。
Emma 02はCDP1802が使われている数々のボードやシステムのエミュレーションができる。 その中でシンプルな VELFで試してみた。

Emma02_velf

Emma02_velf_frontpanel

 COSMAC ELFはシリアル・インタフェースを持っていない。Q(#4)をTXD、EF2(#23)をRXDに使ってソフトウェアで実装してある。

 シンプルな COSMAC ELFで試しておけばSBCを作るときにシリアルインタフェースを載せなくて良い。

サンプル

 lcc1802にはサンプルが用意されている。 これらのサンプルはolduino用なので、これを変更してVELFで動くようにする。

 まずはお約束の hello worldから。 examples/helloworldディレクトリにある。

↓helloworld.c

/*
   print the string "hello World!"
*/
#include <nstdlib.h>
void main()
{
printstr("hello World!\n");
}
#include <nstdlib.c>

ライブラリ

 4行目の #include <nstdlib.h>は良いが、最終行の #include <nstdlib.c>は何?である。

 lcc1802はライブラリはなくて、最低限の関数がinclude/nstdlib.cに書いてある。printf()もあるが、最低限の機能だけで出力幅指定はできない。

 文字列出力関数のprintstr()は1文字出力にout(5,d)を呼んでいるが、VELFでは動作しないのでputc()を使うように変更しておく。

↓nstdlib.c内のprintstr()

void printstr(char *ptr){
//    while(*ptr) out(5,*ptr++);
    while(*ptr) putc(*ptr++);
}

 nstdlib.cにはfloatを扱う関数がある。 sdccは賢いので必要な関数だけリンクしてくれるがlcc1802ではnstdlib.cはいつでもコンパイルされるので使わない関数でもオブジェクトに含まれる。float関係の部分だけは "nofloats"が宣言されているとコンパイルしないようになっている。 コマンドラインオプションで -Dnofloatsとすれば良い。

ランタイムライブラリ

 ランタイムライブラリは、include/lcc1802Prolo??.incとinclude/lcc1802Epiloxx.inc。

 これらはのライブラリは、コンパイル済のライブラリをlinkerがリンクするのではなく、ソースに展開している。ソース中にnsddlib.cをインクルードし、アセンブラソース中でlcc1802Prolo??.incとlcc1802Epiloxx.incをインクルードしている。

入出力ルーチン

 IOルーチンは、include/IO1802.incに書いてある。 printf()は1文字出力にputc()を呼んでいる。  lcc1802が想定しているolduinoの1文字出力はout(5,d)を使っているので、VELFでは出力できない。

 IO1802.incに1文字出力(putc())と1文字入力(getc())を書けば良さそうだ。
ここでハタと困った。CDP1802のアセンブラは書いたことが無い。
とりあえず、Emma02にVELFのモニタソース(Emma02\data\Velf\VELFbios-v3.1.LST)があったので、この中の1文字入出力ルーチンを参考に(ほぼコピペ)、Cから引数を渡す部分と戻り値を返す部分を付け加えて、テンポラリ変数をreからrt1に変えた。

↓IO1802.inc

;**********************************************************************
;Transmit Byte via Q connected to RS232 driver
;call with R3 being the previous PC
;Byte to send in D
;Returns with D unaffected
;re.1 = D
;Destroys rt1.0
;----------------------------------------------------------------------
_putc: glo regArg1
txchar: phi rt1
ldi 9 ;9 bits to transmit (1 start + 8 data)
plo rt1
ghi rt1
shl ;set start bit
rshr ;DF=0

txcloop:
bdf $+5 ;10.5   jump to seq to send a 1 bit
req ;11.5   send a 0 bit
br $+5 ;1      jump +5 to next shift
seq ;11.5   send a 1 bit
br $+2 ;1      jump +2 to next shift (NOP for timing)
rshr ;2      shift next bit to DF flag
phi rt1 ;3      save D in rt1.1
DEC rt1 ;4      dec bit count
glo rt1 ;5      get bit count
bz txcret ;6      if 0 then all 9 bits (start and data) sent
ghi rt1 ;7      restore D
NOP ;8.5    pause 1/2 time
br txcloop ;9.5    loop back to send next bit
txcret: ghi rt1 ;7
ghi rt1 ;8
ghi rt1 ;9
NOP ;10.5
seq ;11.5 stop bit
NOP ;1
NOP ;2.5
NOP ;4
NOP ;5.5
NOP ;7
NOP ;8.5
NOP ;9
NOP ;10.5
Cretn

;**********************************************************************
;rx_char
;Receive Byte via EF2 connected to RS232 rt1ceiver
;Recieves 8 bits
;call with R3 being the previous PC
;Returns with Byte received in D and rt1.1
;Destroys rt1.0
;----------------------------------------------------------------------
_getc:
rxchar: ldi 8 ;start bit +7 bits from loop, last bit on returning
plo rt1
ldi 0
rxcw: ;wait for start bit
bn2 rxcw ;each instr takes 9us, we need 104us = 11.5
;delay 1/2 bit time to center samples
NOP ;     Don't test for correct start bit
NOP ;     it will work, if there's too much
NOP ;     noise on the line, shorten the cable!
rxcloop:
NOP ;10.5
b2 $+6 ;11.5 sample rx input bit
ori 80h ;1
br $+4 ;2
phi rt1 ;1
phi rt1 ;2
shr ;3
phi rt1 ;4
DEC rt1 ;5
glo rt1 ;6
bz rxcret ;7
ghi rt1 ;8
br rxcloop ;9
rxcret: ghi rt1 ;8
ghi rt1 ;9
NOP ;10.5
b2 $+4 ;11.5 sample last rx input bit
ori 80h ;1
plo retVal
Cretn

 

コンパイル

 この変更でIntelHexフォーマットの a.hexが作られるようになる。

C:\Users\user> lcc -Dnofloats helloworld.c
And St. Judy's Compiler FLOATS Across your code...
P2HEX/C V1.42 Beta [Bld 87]
(C) 1992,2013 Alfred Arnold
C:\Users\user\AppData\Local\Temp/lcc124682.p==>>a.hex  (3609 Bytes)

しかし、hellowroldだけで3,609byteとは。 

8Queen

 8Queen問題を解くプログラムをコンパイルしてみる。 再帰を使っているのでちゃんと動くだろうか?

/*
* 8Queen.c
* Yoshi / Apr.2018
*/

#include <nstdlib.h>

#define FALSE 0
#define TRUE (!FALSE)
#define u_char unsigned char
#define u_short unsigned short
#define NL "\r\n"
#define getchar getc
int DEBUG = 0;

char table[8];
void clrtbl(void) { int i; for(i=0;i<8;i++) table[i]=0xFF; }

void printtb(char n) {
    int x, y;
    printf(NL "-- %d --" NL, n);
    for (y=0;y<8;y++) {
        putchar('|');
        for (x=0;x<8;x++) {
            if (table[y]==x)
                 putchar('Q');
            else putchar(' ');
            putchar('|');
        }
        puts(NL);
    }
}

char check(int x, int y) {
    int i;

    if (y==0) return TRUE;
    for (i=y-1; 0<=i; i--) {
        if (2<DEBUG) printf("tb[%d]=%d" NL, i, table[i]);
        if (table[i]==x || table[i]==(x-(y-i)) || table[i]==(x+(y-i)))
            return FALSE;
    }
    return TRUE;
}

char place(int x, int y) {
    static int n = 1;

    if (DEBUG) printf("place(%d,%d):" NL, x, y);

    if (7<y) {  /* 解 */
        printtb(n++);
        return FALSE;
    }
    if (7<x) {  /* 見つからない */
        return FALSE;
    }

    if (check(x,y)) {
        table[y] = x;
        if (n==1) printtb(n);
        place(0, y+1);
        table[y] = (u_char)-1;
    }
    return place(x+1, y);
}

void main(void) {
    printf("8 Queen" NL);
    clrtbl();
    place(0,0);
    exit(0);
}

#include <nstdlib.c>

コンパイルすると、4,542byteだった。

↓実行結果

Emma02_velf_terminal

ちゃんと実行されるようだ。

まとめ

 SBCを作るときはRAMをケチらないで載せておけばlcc1802は使える。今時、32kのRAMを積んでも大した出費ではない。

 残念ながら、オリジナルのCOSMAC ELFではRAMが少ないので使えないだろう。もっともオリジナルのCOSMAC ELFを忠実に作るなら、ハンドアセンブルして、8個のスイッチでプログラムを入力する覚悟が必要だ。

 rcc.exeがASxxxxアセンブラを吐くようにするとSDCCのライブラリが使えるようになる。そして、aslinkを使うともう出力がもう少しコンパクトになると思う。 興味はあるが、そこまでやるか... 



最近の投稿】【2017の投稿】【2016の投稿】【2015の投稿

最近のCOSMAC/CDP1802

2015年10月11日 (日)

CDP1802

 CDP1802を探していた。マルツやChipOneStopで売っているのだが、1個は売ってくれない。CDP1802CDは単価が安いが(800円くらい)最低販売数は14個だ。どうやら 最低販売数は 10,000円を超えるように設定されているようだ。

ばら売りしてくれそうなところに見積もりのメールを出したら、なしのつぶてで、素人相手に1個、2個2の商売はやってられないよな、と諦めかけていたら 返信があった。

 CDP1082BCEの在庫があって@800だと言うので2個発注しておいた。

Cdp1802bce

 

CDP1082は今でも Intersilが作ってるようだが、送られてきたのは RCAのロゴがある。

Cdp1802bcemarking

84年23週製造か?GEに買収される前の年だ。

 CDP1802BCEは高速タイプ(5MHz),推奨VDD 5V(4V-6.5V),PDIPである。CMOSだから電源電圧は5Vでなくても良い。データシートにはCDP1802Aの推奨VDDは4V-10.5Vで、VDD=10Vのとき6.4MHzで動くと書いてある。

 CDP1802を使ったマイコンボード、COSMAC ELFを作ってみたいが、COSMAC ELFを作るには、16進LEDディスプレイが必要だ。

 この前入手したLEDディスプレイは16進表示ではなく10進表示だった。orz

 新品はDigikeyで\5,386、AVNET$33.2939だ。

 マイコンやPLDを使うと簡単だけど...



最近の投稿】【2017の投稿】【2016の投稿】【2015の投稿

最近のCOSMAC/CDP1802

2018年9月
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30            

最近のトラックバック