- Refactored site specific stuff into a site module - PSI specific stuff is now in the PSI directory. - The old version has been tagged with pre-ansto
243 lines
7.2 KiB
C
243 lines
7.2 KiB
C
/***************************************************************************
|
||
* This file contains the download program the ECB system.
|
||
* It reads a Tek-hex formated file and downloads it to the ECB-system.
|
||
* The lowest address is used as the start address of the program.
|
||
*
|
||
* Project: ECB-C
|
||
* Filename: ecb_load.c
|
||
*
|
||
* Author: L. S. Jensen 18. Feb 1993
|
||
*
|
||
* Heavily reworked by code transfusions from tascom in order to
|
||
* support new ECB file format.
|
||
*
|
||
* Mark Koennecke, May 2003
|
||
*
|
||
* Copyright (C) Risoe National Laboratory, 1993, All rights reserved
|
||
****************************************************************************/
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
#include "ecb-drv.h" /* The ecb driver interface. */
|
||
|
||
#define MAX_BUFFER_SIZE 32767 /* Max. RAM in ECB system */
|
||
#define LINE_SIZE 128
|
||
|
||
#define LAST_LINE -125
|
||
#define CHECKSUM_ERR -100
|
||
#define FORMAT_ERR -101
|
||
#define FILE_ERR -102
|
||
|
||
#define CSTART_CODE 171 /* The number of ECB function cstart */
|
||
|
||
#define FOREVER 1 /* Used in a loop */
|
||
#define ECB_BYTES 65536L
|
||
#define ECB_DOWN_LOAD 178
|
||
#define LOAD_NEXT 1
|
||
/*****************************************************************************
|
||
* Local variables in this file.
|
||
*****************************************************************************/
|
||
static char buffer[MAX_BUFFER_SIZE];
|
||
|
||
static int debug = 0;
|
||
|
||
/*******************************************************************************
|
||
* Convert HEX to bin
|
||
*******************************************************************************/
|
||
static int look_up[] = {10, 11, 12, 13, 14 ,15};
|
||
|
||
static unsigned long
|
||
Hex_to_bin(char c)
|
||
{
|
||
|
||
if(isdigit((int) c))
|
||
return (c - '0');
|
||
else
|
||
return look_up[c - 'A'];
|
||
}
|
||
|
||
|
||
/*******************************************************************************
|
||
* Convert Bin to HEX
|
||
*******************************************************************************/
|
||
|
||
static char
|
||
Bin_to_hex (int i)
|
||
{
|
||
|
||
if(i <= 9)
|
||
return ( (char)(i + (int)('0')) );
|
||
else
|
||
return ( (char)( (i - 10) + (int)('A')) );
|
||
}
|
||
/***************************************************************************
|
||
* This function creates blocks as large as possible of consecutive data
|
||
* bytes from the hex file in order to speed up the data transfer by
|
||
* sending blocks of data to the ECB system rather than single lines.
|
||
****************************************************************************/
|
||
static Z80_reg x_outreg, x_inreg;
|
||
|
||
static long
|
||
Send_blocks(FILE *fp, Gpib_dev dev)
|
||
{
|
||
char line[LINE_SIZE];
|
||
char *point;
|
||
int line_not_output, byte_count, line_no,type, no_bytes,total_bytes;
|
||
int load_count = -1, function;
|
||
unsigned char x_ecb_data[ECB_BYTES]; /* Array to hold data blocks for ECB */
|
||
unsigned long adrs, old_adrs, total0, total1, total2;
|
||
void *line9 = &line[9];
|
||
unsigned short address;
|
||
|
||
for (;;)
|
||
{
|
||
if (line_not_output == 1)
|
||
line_not_output = 0; /* Start with old line */
|
||
else
|
||
{ /* Read a line from file */
|
||
point = fgets (line, LINE_SIZE, fp);
|
||
if (point != NULL)
|
||
{
|
||
byte_count = strlen(line);
|
||
byte_count -= 4; /* Remove checksum and \n in the */
|
||
line[byte_count+1] = '\0'; /* line, i.e. the four last characters */
|
||
line[0] = '0'; /* Replace : in line[0] with 0 */
|
||
}
|
||
else
|
||
{
|
||
if (!ferror(fp))
|
||
byte_count = 0;
|
||
else
|
||
{
|
||
fclose (fp);
|
||
fp = NULL;
|
||
return(FILE_ERR);
|
||
}
|
||
}
|
||
}
|
||
line_no += 1;
|
||
if (byte_count != 0)
|
||
{
|
||
if (line_no == 1)
|
||
strcpy (x_ecb_data, line);
|
||
type = (Hex_to_bin(line[7]) << 4) + Hex_to_bin(line[8]);
|
||
if (type != 0)
|
||
{
|
||
if (line_no > 1) /* Output buffer and mark that */
|
||
line_not_output = 1; /* last input line has not been output */
|
||
}
|
||
else
|
||
{
|
||
no_bytes = (Hex_to_bin(line[1]) << 4) + Hex_to_bin(line[2]);
|
||
adrs = (Hex_to_bin(line[3]) << 12) + (Hex_to_bin(line[4]) << 8) +
|
||
(Hex_to_bin(line[5]) << 4) + Hex_to_bin(line[6]);
|
||
if (line_no == 1)
|
||
{
|
||
total_bytes = no_bytes;
|
||
old_adrs = adrs;
|
||
continue; /* Get next input line */
|
||
}
|
||
else
|
||
{
|
||
if (old_adrs + no_bytes == adrs)
|
||
{ /* Contigious addresses */
|
||
total_bytes += no_bytes;
|
||
old_adrs = adrs;
|
||
strcat (x_ecb_data, line9); /* Add the new bytes to buffer */
|
||
total0 = total_bytes/256; /* and adjust number of bytes */
|
||
x_ecb_data[0] = Bin_to_hex(total0);
|
||
total1 = total_bytes - 256*total0;
|
||
total2 = total1/16;
|
||
x_ecb_data[1] = Bin_to_hex(total2);
|
||
x_ecb_data[2] = Bin_to_hex(total1 - 16*total2);
|
||
if (line_no < 20) /* Max 20 lines together */
|
||
continue; /* Get next input line */
|
||
}
|
||
}
|
||
line_not_output = 0; /* Output buffer, nothing waiting in line[] */
|
||
}
|
||
|
||
address = 1;
|
||
byte_count = strlen (x_ecb_data);
|
||
Ecb_write (dev, x_ecb_data,byte_count,1); /* Write a line to ECB */
|
||
line_no = 0;
|
||
|
||
if (load_count == -1) /* Type Loading followed by dots while */
|
||
{ /* down loading the file */
|
||
printf ("Loading");
|
||
load_count = 0;
|
||
}
|
||
load_count += 1;
|
||
|
||
if (load_count > 15)
|
||
{
|
||
printf (".");
|
||
load_count = 0;
|
||
}
|
||
|
||
|
||
function = ECB_DOWN_LOAD;
|
||
Ecb_func (dev, function,x_inreg); /* Call ECB download function */
|
||
if (x_outreg.b != LOAD_NEXT) /* Wait for reply from ECB */
|
||
break; /* If LOAD_NEXT, get next line, else finished */
|
||
}
|
||
}
|
||
printf("\nLoading completed\n");
|
||
}
|
||
/****************************************************************************
|
||
* Handles error in gpib driver.
|
||
****************************************************************************/
|
||
void
|
||
Exit_code(int status)
|
||
{
|
||
if(debug)
|
||
printf("exit status %d", status);
|
||
exit(status);
|
||
}
|
||
/****************************************************************************
|
||
*
|
||
****************************************************************************/
|
||
int
|
||
main(int argc, char *argv[])
|
||
{
|
||
Gpib_dev dev;
|
||
int dev_no;
|
||
FILE *record_fp;
|
||
long start_adr;
|
||
Z80_reg z80;
|
||
|
||
if (argc < 4|| argc > 5)
|
||
{
|
||
printf("used: %s Gpib-driver-name ECB-device-number ECB-hex-filename\n",
|
||
argv[0]);
|
||
exit(GPIB_ERR);
|
||
}
|
||
if (argc == 5)
|
||
{
|
||
if ((0 == strcasecmp(argv[4],"DEBUG"))||(0 == strcasecmp(argv[4],"VERBOSE")))
|
||
debug = 1;
|
||
}
|
||
|
||
record_fp = fopen(argv[3], "rb"); /* Open in read-only mode in binary mode */
|
||
if (record_fp == NULL)
|
||
{
|
||
printf("used: %s Gpib-driver-name ECB-device-number ECB-hex-filename\n",
|
||
argv[0]);
|
||
exit(FILE_ERR);
|
||
}
|
||
|
||
dev = Ecb_unit(argv[1], argv[2]); /* Open the ECB device */
|
||
|
||
start_adr = Send_blocks(record_fp, dev);
|
||
if (start_adr < 0) /* An error */
|
||
exit(start_adr);
|
||
|
||
z80.d = start_adr; /* Lsb part in Z80 reg. D */
|
||
z80.e = start_adr>>8; /* Msb part in Z80 reg. E */
|
||
|
||
Ecb_func(dev, CSTART_CODE, z80); /* And start the ecb-c program. */
|
||
|
||
return;
|
||
}
|
||
|
||
|