next up previous contents
Next: D.4 console.c Up: D C Source Code Previous: D.2 staller.c

D.3 download.c

 

/*****************************************************************
** D O W N L O A D . C
** Address Tracing System, Scott Harrington, Fall 94
** Downloads a Xilinx RBT file (rawbits format) to the FPGA(s) on
** the Bullwinkle board.
**
** Command line options:
** [-p port]     port #(200,220,240,...,3E0) default 300
** [-s segment]  segment D or E (default D)
** filename
*/

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>

#define STAT_Empty0 0x01
#define STAT_Empty1 0x02
#define STAT_Empty2 0x04
#define STAT_Empty3 0x08
#define STAT_nExtract 0x10
#define STAT_nProgram 0x20
#define STAT_nInit 0x40
#define STAT_SACK 0x80

#ifndef INTERACTIVE
#define kbhit() (1)
#define getch() (32)
#endif

enum {OUT_Config=0, OUT_NOP1, OUT_StartWrite, OUT_StartRead,
    OUT_Remote, OUT_Local, OUT_E000, OUT_D000,
    OUT_Sel0, OUT_Sel1, OUT_Sel2, OUT_Sel3,
    OUT_UnSelAll, OUT_SelAll, OUT_NOP14, OUT_Reset};

#define IMAGESIZE 60000
unsigned char far image[IMAGESIZE];
unsigned int ioPort = 0x300;
int page_E = 0;

long download(FILE *rbt);
void writeMem8(unsigned char val);
unsigned int readMem16(void);
int showStatLoop(void);
int fillBoris(long count, unsigned int val);
int emptyBoris(void);

void main(int argc, char *argv[])
    {
    int i, ch;
    long c, cw;
    char *parmstr, *endptr;
    FILE *rbtfile;
    char filename[255];

    for (i=1; i<argc; i++) {
        if (argv[i][0] == '-') {
            switch (argv[i][1]) {
            case 'p':
                parmstr = (argv[i][2]) ? &argv[i][2] : argv[++i];
                ioPort = (unsigned int)strtoul(parmstr, &endptr, 0);
                break;
            case 's':
                parmstr = (argv[i][2]) ? &argv[i][2] : argv[++i];
                page_E = (parmstr[0] == 'E' || parmstr[0] == 'e');
                break;
            default:
                printf("Usage: %s [-p port] [-s D000|E000] filename[.rbt]\n", argv[0]);
                exit(-1);
                }
            }
        else {
            strcpy(filename, argv[i]);
            if ((rbtfile=fopen(filename, "rb")) != NULL)
                break;
            strcat(filename, ".rbt");
            if ((rbtfile=fopen(filename, "rb")) != NULL)
                break;
            printf("Unable to open file %s.\n", filename);
            exit(-1);
            }
        }

    if (ioPort & ~0x3E0) {
        printf("Valid ports are 0x200, 220, 240, ..., 3E0.\n");
        exit(-1);
        }
    if (rbtfile == NULL) {
        printf("Usage: %s [-p port] [-s D000|E000] filename[.rbt]\n", argv[0]);
        exit(-1);
        }

    showStatLoop();

    /* Prepare Bullwinkle for configuration */
    printf("Preparing for FPGA configuration using port %x, mem loc %s.\n",
            ioPort, page_E ? "E000:0000" : "D000:0000");
    outportb(ioPort+OUT_Config, 0);
    outportb(ioPort+OUT_Local, 0);
    outportb(ioPort+(page_E ? OUT_E000:OUT_D000), 0);
    outportb(ioPort+OUT_SelAll, 0);

    printf("Waiting for Init signals to deactivate");
    while ((inportb(ioPort) & STAT_nInit) == 0) {
        if (kbhit()) {
            if (getch() == 27)
                exit(0);
            }
        putchar('.');
        }
    printf("\n");

    showStatLoop();

    printf("Downloading %s to FPGA.\n", filename);
    c = download(rbtfile);
    printf("Total bits written to FPGA = %ld\n", c);

    showStatLoop();
    }

long download(FILE *rbt)
    {
    long cnt = 0L;
    long len;
    long index = 0;
    int i;
    char ch;

    len = fread(image, 1, IMAGESIZE, rbt);

    /* look for 11111111 start bit pattern in rbt file */
    while (cnt<8L) {
        ch = image[index++];
        cnt = (ch=='1') ? cnt+1L : 0L;
        }

    /* send start bits */
    cnt = 0L;
    while (cnt < 8L) {
        writeMem8(0x01);
        cnt += 1L;
        }

    /* send bits in rbt until eof */
    for ( ; index<len; index++) {
        ch = image[index];
//      if (ch == '0' || ch == '1') {
        if (ch & 0x30) {
            writeMem8(ch);
            cnt += 1L;
            if (cnt%1000L == 0L)
                putchar('.');
            }
        }

    /* send an additional few ones to keep CCLK going for a while */
    for (i=0; i<40; i++)
        writeMem8(0x01);

    printf("\n");
    return cnt;
    }

int showStatLoop() {
    unsigned int d, d0=256;
    int c;
#ifdef INTERACTIVE
    printf("\nPress any key to continue (ESC aborts).\n");
#endif
    while (1) {
        d = inportb(ioPort);
        if (d != d0) {
            printf("%s %s %s %s   Empty:%d%d%d%d\n",
                (d & STAT_SACK) ? "SACK":"sack",
                (d & STAT_nInit) ? "init":"INIT",
                (d & STAT_nProgram) ? "pgm":"PGM",
                (d & STAT_nExtract) ? "ext":"EXT",
                (d & STAT_Empty0) ? 1:0,
                (d & STAT_Empty1) ? 1:0,
                (d & STAT_Empty2) ? 1:0,
                (d & STAT_Empty3) ? 1:0);
            d0 = d;
            }
        if (kbhit()) {
            c = getch();
            if (c!='r' && c!='R')
                break;
            printf("Pulsing Global Reset signal.\n");
            outportb(ioPort+OUT_Reset, 0);
            }
        }
    if (c==27)
        exit(0);
    return c;
    }


/* Write a 16-bit word somewhere in the selected shared memory area
** (either D000 or E000 segment)
*/
void writeMem8(unsigned char val)
    {
    static unsigned int offset;
    unsigned char far *memptr;

    memptr = MK_FP(page_E ? 0xE000:0xD000, offset);
    *memptr = val;

    offset++;       /* 16-bit int causes segment wraparound */
    }


unsigned int readMem16()
    {
    static unsigned int offset;
    unsigned int far *memptr;

    /* ensure word-alignment */
    if (offset&1)
        offset = 0;

    memptr = MK_FP(page_E ? 0xE000:0xD000, offset);
    offset += 2;        /* 16-bit int causes segment wraparound */

    return *memptr;
    }


Scott E. Harrington
Sat Apr 29 18:56:25 EDT 1995