2014年9月21日日曜日

BDS C で X1 turbo の DMA を使ってみる

>BDS C の使い方 - 目次

BDS C の使い方 - SHARP X1 で使ってみる で作った IO16.CRL の out16 関数を使っています。

test.c
/*
BDS C で SHARP X1 の DMA を使うテスト

2014年9月20日作成

X1 G-RAM はI/O空間
0x2000 - 0x27FF テキストアトリビュート
0x3000 - 0x37FF テキスト
0x4000 - 0x7FFF B
0x8000 - 0xBFFF R
0xC000 - 0xFFFF G
*/

void main()
{
    /* グラフィックパレット初期化 */
    out16(0x1000,0xAA); /* 1010 1010 */
    out16(0x1100,0xCC); /* 1100 1100 */
    out16(0x1200,0xF0); /* 1111 0000 */
    
    /* GRAMクリア */
    dma_rset();
    dma_vfil(0x4000, 0xC000, 0xAA);
    dma_enbl();
    puts("hit key\n");
    pause();
    dma_vfil(0x4000, 0xC000, 0xFF);
    dma_enbl();
    puts("hit key\n");
    pause();
    dma_vfil(0x4000, 0xC000, 0x55);
    dma_enbl();
    puts("hit key\n");
    pause();
    dma_vfil(0x4000, 0xC000, 0x00);
    dma_enbl();
    puts("hit key\n");
    pause();
    
    /* GRAM Bプレーン適当書き込み*/
    dma_m2v(0x0000, 0x4000, 0x4000);
    dma_enbl();
    dma_rset();
    puts("hit key\n");
    pause();

    dma_vfil(0x4000, 0x4000, 0xAA);
    dma_enbl();
}

dma.c
/*
    DMA.C
    
    2014年9月20日作成
*/

#define DMA_ADDR 0x1F80


/*  DMA RESET */
dma_rset()
{
    char a;
    for(a=6; 0!=a; a--)
    {
        out16(DMA_ADDR, 0xC0);
    }
}

/* ENABLE DMA */
dma_enbl()
{
    out16(DMA_ADDR,0x87);
}

dma_set(cmd, size)
char cmd[];
char size;
{
    char count;
    for(count=0; count!=size; count++)
    {
        out16(DMA_ADDR, cmd[count]);
    }
}

/*  VRAM FILL
    VRAM の addr から size を data で埋める */
dma_vfil(addr, size, data)
short addr,size;
char data;
{
    char cmd[13];
    /*initb(cmd, "0x00,0x00,0x00,0x00,0x00");*/
    
    size--;     /* DMAの都合により -1 */

    out16(addr,data);   /* 最初のアドレスにデータを書く。このデータをソースにDMAで転送する */
                        /* ソースを変数へのポインタで指定しようとしたらうまく行かなかった */
    cmd[ 0]=0x79;       /* 0111 1001    WR0 */
                        /*       +----- 0:B->A 1:A->B */
    cmd[ 1]=addr;       /* PORT A アドレスL */
    cmd[ 2]=addr>>8;    /* PORT A アドレスH */
    cmd[ 3]=size;       /* ブロックレングスL */
    cmd[ 4]=size>>8;    /* ブロックレングスH */

    cmd[ 5]=0x1C;       /* 0001 1100    WR1 PORT A */
                        /*   || +------ 0:メモリー 1:I/O */
                        /*   ++-------- 00:-- 01:++ 10/11:固定 */

    cmd[ 6]=0xCD;       /* 1100 1101    WR4 */
                        /*  ++--------- 00:バイト 01:コンティニュアス 10:バースト */
    cmd[ 7]=addr;       /* PORT B アドレスL */
    cmd[ 8]=addr>>8;    /* PORT B アドレスH */

    cmd[ 9]=0x38;       /* 0011 1000    WR2 PORT B */
                        /*   || +------ 0:メモリー 1:I/O */
                        /*   ++-------- 00:-- 01:++ 10/11:固定 */

    cmd[10]=0x9A;       /* 1001 1010    WR5 */
                        /*    | +------ 0:READY L 1:READY H */
                        /*    +-------- 0:CE 1:CE/WAIT */
    cmd[11]=0xCF;       /*              WR6 LOAD */
    cmd[12]=0xB3;       /*              WR6 FORCE READY */
    
    dma_set(cmd,13);
}

/*  MEMORY -> VRAM */
dma_m2v(src, dst ,size)
short src, dst, size;
{
    char cmd[13];

    size--;
    
    cmd[ 0]=0x7D;       /* 0111 1101    WR0 */
                        /*       +----- 0:B->A 1:A->B */
    cmd[ 1]=src;        /* PORT A アドレスL */
    cmd[ 2]=src>>8;     /* PORT A アドレスH */
    cmd[ 3]=size;       /* ブロックレングスL */
    cmd[ 4]=size>>8;    /* ブロックレングスH */

    cmd[ 5]=0x14;       /* 0001 0100    WR1 PORT A */
                        /*   || +------ 0:メモリー 1:I/O */
                        /*   ++-------- 00:-- 01:++ 10/11:固定 */

    cmd[ 6]=0xCD;       /* 1100 1101    WR4 */
                        /*  ++--------- 00:バイト 01:コンティニュアス 10:バースト */
    cmd[ 7]=dst;        /* PORT B アドレスL */
    cmd[ 8]=dst>>8;     /* PORT B アドレスH */

    cmd[ 9]=0x18;       /* 0001 1000    WR2 PORT B */
                        /*   || +------ 0:メモリー 1:I/O */
                        /*   ++-------- 00:-- 01:++ 10/11:固定 */

    cmd[10]=0x9A;       /* 1001 1010    WR5 READYはH有効 */
                        /*    | +------ 0:READY L 1:READY H */
                        /*    +-------- 0:CE 1:CE/WAIT */

    cmd[11]=0xCF;       /*              WR6 LOAD */
    cmd[12]=0xB3;       /*              WR6 FORCE READY */
    
    dma_set(cmd,13);
}

コンパイル・リンク
>cpm cc dma\dma
BD Software C Compiler v1.60  (part I)
  42K elbowroom
BD Software C Compiler v1.60 (part II)
  39K to spare
>cpm cc dma\test
BD Software C Compiler v1.60  (part I)
  43K elbowroom
BD Software C Compiler v1.60 (part II)
  40K to spare
>cpm clink dma\test c:dma c:io16
BD Software C Linker   v1.60

Last code address: 0C4E
Externals start at 0C4F, occupy 0000 bytes, last byte at 0C4F
Top of memory: FDFF
Stack space: F1B1
Writing output...
  52K link space remaining
>

Z80 DMA のハンドブックを読んでも、いまいちよくわからなかったんですが、決まりきった手順なのでこのように一度 DMA にコマンドを発行してみると、そんなに面倒でもなかったです。

>BDS C の使い方 - 目次