From robot-board@oberon.com Thu Nov 10 13:00:14 1994
Received: by media.mit.edu (5.57/DA1.0.4.amt)
	id AA01458; Thu, 10 Nov 94 13:00:08 -0500
Received: from  (localhost [127.0.0.1]) by oberon.com (8.6.9/8.6.9) with SMTP id MAA14011; Thu, 10 Nov 1994 12:54:24 -0500
Date: Thu, 10 Nov 1994 12:54:24 -0500
Message-Id: <9411101752.AA09776@Stump.AI.SRI.COM>
Errors-To: gkulosa@oberon.com
Reply-To: konolige@ai.sri.com
Originator: robot-board@oberon.com
Sender: gkulosa@oberon.com
Precedence: bulk
From: Kurt Konolige <konolige@ai.sri.com>
To: Multiple recipients of list <robot-board@oberon.com>
Subject: [?] Interactive-C on EVBU.
X-Listprocessor-Version: 6.0b -- ListProcessor by Anastasios Kotsikonas

If the E9 allows variable-length boot files, then it may have
bootstrap ROM code similar to the 'F1, which I'm using.
Variable-length files are downloaded using a timeout: if there is a
4-character time gap, the chip assumes that the transmission is ended,
and jumps to location 0 to start the loaded program.

DL will not work correctly with this bootload ROM, since it waits
after sending the first $FF wakeup byte.  I had to modify the code a
bit to make it work.  Get the sources from cher.media.mit.edu, and in
the "libs" directory replace the file dl6811.c with the following one,
then recompile.  Note that I've assumed a maximum 1024-byte download
file; you may want to use a shorter limit for the 'E9.

This file works on UNIX systems, but not on the Mac; for some reason
its serial port doesn't send bytes out as fast, and more drastic
hacking is needed.

I also had some trouble with the CONFIG register, but I don't know
enough about the 'E9 to make a recommendation.

CHeers --kk

=====================================================================

/**
 ** dl6811.c
 **
 ** Copyright 1990, 1991 by Randy Sargent.
 **
 ** The author hereby grants to MIT permission to use this software.
 ** The author also grants to MIT permission to distribute this software
 ** to schools for non-commercial educational use only.
 **
 ** The author hereby grants to other individuals or organizations
 ** permission to use this software for non-commercial
 ** educational use only.  This software may not be distributed to others
 ** except by MIT, under the conditions above.
 **
 ** Other than these cases, no part of this software may be used or
 ** distributed without written permission of the author.
 **
 ** Neither the author nor MIT make any representations about the 
 ** suitability of this software for any purpose.  It is provided 
 ** "as is" without express or implied warranty.
 **
 ** Randy Sargent
 ** Research Specialist
 ** MIT Media Lab
 ** 20 Ames St.  E15-301
 ** Cambridge, MA  02139
 ** E-mail:  rsargent@athena.mit.edu
 **
 **/


#include CONFIG

#include <confexec.h>
#include <queue.h>
#include <io.h>
#include <board.h>

#include "dl6811.h"

int dl_queue_size= 1024;

Queue check_queue;

int dl_debug= 0;
int dl_ignore= 0;
int first_char = 0;

void dl_reset_check_char(void)
{
    static initted= 0;
    if (initted) queue_term(&check_queue);
    queue_init(&check_queue, dl_queue_size, sizeof(int));
    initted= 1;
    first_char = 1;
}

/* 0 if successful */
int dl_check_char(IOStream *port, int data)
{
    int received, expected, added= 0;
    int timeout= 500; /* milliseconds */

    if (dl_ignore) return 0;
    
    while (1) {
        if (!added) added= !queue_add_tail(&check_queue, &data);
	received= io_getchar(port, added ? 0 : 10);
	if (received == EOF && added) break;
        if (received == EOF) {
            timeout -= 10;
            if (timeout <= 0) {
                fprintf(stderr, "Timeout on serial response\n");
		return 1;
            }
        }
	if (first_char)		/* got first char, a zero from wakeup */
	  {
	    first_char = 0;
	    break;
	  }
	if (!queue_head(&check_queue)) {
	    fprintf(stderr, "Received too many characters from serial port\n");
	    return 1;
	}
	expected= *(int*)queue_remove_head(&check_queue);
        if (dl_debug) printf("GOT %x\n", expected);
	if (expected != received) {
	    fprintf(stderr, "Expected %d, received %d\n", expected, received);
	    return 1;
	}
    }
    return 0;
}

int dl_check_rest(IOStream *port)
{
    int received, expected;

    if (dl_ignore) {
	printf("Waiting for serial to finish...\n");
	msleep(5000);  /* wait for downloader to finish */
	io_discard_input(port);
	return 0;
    }
    
    while (queue_head(&check_queue)) {
	received= io_getchar(port, 500);
	if (received == EOF) {
	    fprintf(stderr, "Timeout on serial receive.  %d chars left to receive\n",
		    queue_length(&check_queue));
	    return 1;
	}
	expected= *(int*)queue_remove_head(&check_queue);
	if (expected != received) {
	    fprintf(stderr, "Expected %d, received %d\n", expected, received);
	    return 1;
	}
    }
    return 0;
}

/*****************/
/* HEX FUNCTIONS */
/*****************/

int hex_to_int(char ch)
{
    if ('0' <= ch && ch <= '9') return ch - '0';
    if ('a' <= ch && ch <= 'f') return ch - 'a' + 10;
    if ('A' <= ch && ch <= 'F') return ch - 'A' + 10;
    printf("Illegal hex digit >%c<\n", ch);
    return 0;
}

int hex2_to_int(char *str)
{
    return hex_to_int(str[0]) * 16 + hex_to_int(str[1]);
}

int decode_hex(char *in, unsigned char *out)
{
    int i;
    for (i= 0; in[0] && in[1]; i++, in+=2) {
	out[i]= (unsigned char) hex2_to_int(in);
    }
    if (in[0]) {
	printf("Uneven # of hex digits in decode_hex\n");
    }
    return i;
}

void dl_6811_help(void)
{
    printf
      ("\n");
    printf
      ("This program is attempting to download a 1024 byte bootstrap into your\n"
       "6811 board.  For this to work, you must have your board hooked up to\n"
       "the correct port, and have it in download mode.\n"
       "\n");
    printf
      ("The way to get into download mode varies from board to board.  Here\n"
       "is a list of known boards and how to get them into download mode:\n"
       "\n");
    printf
      ("MIT Rev 1.0 6.270 board (1/90):\n"
       "             Turn toggle switch to left and press RESET\n"
       "\n");
    printf
      ("Randy and Fred \"Mini\" (Rev 1.5) board (10/91):\n"
       "             Turn small slide switch away from processor and press RESET (XIRQ)\n"
       "             (To turn power on, turn toggle switch away from processor)\n"
       "\n");
    printf
      ("MIT Rev 2.0 6.270 board (1/91), MIT Sensor Bot (9/91):\n"
       "             Power-cycle board.  Do NOT press RESET\n"
       "\n");
    printf
      ("(sorry if the board you are using isn't on this list!)\n"
       "\n");
    return;
}

void dl_6811_user_friendly(IOStream *port, unsigned char *c, long len, IOStream *keyboard)
{
    while (1) {
	int err= dl_6811(port, c, len);
	switch (err) {
	  case 0: /* no error */
	    return;
	  case 1: /* communications error */
	    printf("Perhaps the board was not connected properly or not in download mode\n");

	    while (1) {
		int c;
		printf("\n");
		printf("To try again, place board in download mode and press RETURN\n");
		printf("To quit, press Q\n");
		printf("For help, press H\n");
		c= io_getchar(keyboard, -1);
		switch (c) {
		  case '\n':
		  case '\r':
		    goto out_of_loop;
		  case 'q':
		  case 'Q':
		    printf("Bye!\n");
		    exit(1);
		  case 'h':
		  case 'H':
		    dl_6811_help();
		    break;
		  default:
		    break;
		}
	    }
	  out_of_loop:;
	    break;
	  case 2:
	    exit(0);
	}
    }
}

/* 0 if successful */
/* 1 if communications error (maybe prompt user to try again) */
/* 2 if unrecoverable error */

int dl_6811(IOStream *port, unsigned char *c, long len)
{
    long i;
    int j;
    int err;
    char d;

    if (len > 1024) {
	fprintf(stderr, "Attempted to bootstrap download more than 1024 bytes\n");
	return 2;
    }
    printf("Downloading %d byte bootstrap\n", len);
    io_serial_init(1200L, port);
    msleep(5);

    io_putchar(0xff, port);
    dl_reset_check_char();
#if 0
    msleep(1000)
#endif
    for (i= 0; i< len; i++) {
	io_putchar(c[i], port); 
	err= dl_check_char(port, c[i]); 
	if (err) return err; 
    }
#if 0
    for (; i< 256; i++) {
	io_putchar(0, port);
	err= dl_check_char(port, 0);
	if (err) return err;
    }
#endif
    err= dl_check_rest(port);
    if (err) return err;
    printf("Download successful\n");
    msleep(1000);
    return 0;
}
    

    


