OpenCores
URL https://opencores.org/ocsvn/light8080/light8080/trunk

Subversion Repositories light8080

[/] [light8080/] [trunk/] [tools/] [ihex2vlog/] [ihex.c] - Rev 69

Go to most recent revision | Compare with Previous | Blame | View Log

/* Intel HEX read/write functions, Paul Stoffregen, paul@ece.orst.edu */
/* This code is in the public domain.  Please retain my name and */
/* email address in distributed copies, and let me know about any bugs */
 
/* I, Paul Stoffregen, give no warranty, expressed or implied for */
/* this software and/or documentation provided, including, without */
/* limitation, warranty of merchantability and fitness for a */
/* particular purpose. */
 
 
#include <stdio.h>
 
/* some ansi prototypes.. maybe ought to make a .h file */
 
/* this loads an intel hex file into the memory[] array */
int load_file(char *filename);
 
/* this writes a part of memory[] to an intel hex file */
void save_file(char *command);
 
/* this is used by load_file to get each line of intex hex */
int parse_hex_line(char *theline, int bytes[], int *addr, int *num, int *code);
 
/* this does the dirty work of writing an intel hex file */
/* caution, static buffering is used, so it is necessary */
/* to call it with end=1 when finsihed to flush the buffer */
/* and close the file */
void hexout(FILE *fhex, int byte, int memory_location, int end);
 
extern int	memory[65536];		/* the memory is global */
 
/* parses a line of intel hex code, stores the data in bytes[] */
/* and the beginning address in addr, and returns a 1 if the */
/* line was valid, or a 0 if an error occured.  The variable */
/* num gets the number of bytes that were stored into bytes[] */
 
int parse_hex_line(theline, bytes, addr, num, code)
char *theline;
int *addr, *num, *code, bytes[];
{
	int sum, len, cksum;
	char *ptr;
 
	*num = 0;
	if (theline[0] != ':') return 0;
	if (strlen(theline) < 11) return 0;
	ptr = theline+1;
	if (!sscanf(ptr, "%02x", &len)) return 0;
	ptr += 2;
	if ( strlen(theline) < (11 + (len * 2)) ) return 0;
	if (!sscanf(ptr, "%04x", addr)) return 0;
	ptr += 4;
	  /* printf("Line: length=%d Addr=%d\n", len, *addr); */
	if (!sscanf(ptr, "%02x", code)) return 0;
	ptr += 2;
	sum = (len & 255) + ((*addr >> 8) & 255) + (*addr & 255) + (*code & 255);
	while(*num != len) {
		if (!sscanf(ptr, "%02x", &bytes[*num])) return 0;
		ptr += 2;
		sum += bytes[*num] & 255;
		(*num)++;
		if (*num >= 256) return 0;
	}
	if (!sscanf(ptr, "%02x", &cksum)) return 0;
	if ( ((sum & 255) + (cksum & 255)) & 255 ) return 0; /* checksum error */
	return 1;
}
 
/* loads an intel hex file into the global memory[] array */
/* filename is a string of the file to be opened */
// the function returns the number of bytes read from the hex file 
int load_file (char *filename)
{
	char line[1000];
	FILE *fin;
	int addr, n, status, bytes[256];
	int i, total=0, lineno=1;
	int minaddr=65536, maxaddr=0;
	int topaddr=0;
 
	if (strlen(filename) == 0) {
		printf("Can't load a file without the filename.");
		printf("  '?' for help\n");
		return 0;
	}
	fin = fopen(filename, "r");
	if (fin == NULL) {
		printf("Can't open file '%s' for reading.\n", filename);
		return 0;
	}
 
	while (!feof(fin) && !ferror(fin)) {
		line[0] = '\0';
		fgets(line, 1000, fin);
		if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = '\0';
		if (line[strlen(line)-1] == '\r') line[strlen(line)-1] = '\0';
		if (parse_hex_line(line, bytes, &addr, &n, &status)) {
			if (status == 0) {  /* data */
				for(i=0; i<=(n-1); i++) {
					memory[addr] = bytes[i] & 255;
					total++;
					if (addr < minaddr) minaddr = addr;
					if (addr > maxaddr) maxaddr = addr;
					addr++;
				}
				if (addr >= topaddr) {
					topaddr = addr;
				}
			}
			if (status == 1) {  /* end of file */
				fclose(fin);
				printf("Loaded %d bytes between:", total);
				printf(" %04X to %04X\n", minaddr, maxaddr);
				return (topaddr + 1);
			}
			if (status == 2) ;  /* begin of file */
		} else {
			printf("   Error: '%s', line: %d\n", filename, lineno);
		}
		lineno++;
	}
	return (topaddr + 1);
}
 
 
/* the command string format is "S begin end filename" where */
/* "begin" and "end" are the locations to dump to the intel */
/* hex file, specified in hexidecimal. */
 
void save_file(char *command)
{
	int begin, end, addr;
	char *ptr, filename[200];
	FILE *fhex;
 
	ptr = command+1;
	while (isspace(*ptr)) ptr++;
	if (*ptr == '\0') {
		printf("   Must specify address range and filename\n");
		return;
		}
	if (sscanf(ptr, "%x%x%s", &begin, &end, filename) < 3) {
		printf("   Invalid addresses or filename,\n");
		printf("    usage: S begin_addr end_addr filename\n");
		printf("    the addresses must be hexidecimal format\n");
		return;
	}
	begin &= 65535;
	end &= 65535;
	if (begin > end) {
		printf("   Begin address must be less than end address.\n");
		return;
	}
	fhex = fopen(filename, "w");
	if (fhex == NULL) {
		printf("   Can't open '%s' for writing.\n", filename);
		return;
	}
	for (addr=begin; addr <= end; addr++)
		hexout(fhex, memory[addr], addr, 0);
	hexout(fhex, 0, 0, 1);
	printf("Memory %04X to %04X written to '%s'\n", begin, end, filename);
}
 
 
/* produce intel hex file output... call this routine with */
/* each byte to output and it's memory location.  The file */
/* pointer fhex must have been opened for writing.  After */
/* all data is written, call with end=1 (normally set to 0) */
/* so it will flush the data from its static buffer */
 
#define MAXHEXLINE 32	/* the maximum number of bytes to put in one line */
 
void hexout(fhex, byte, memory_location, end)
FILE *fhex;  /* the file to put intel hex into */
int byte, memory_location, end;
{
	static int byte_buffer[MAXHEXLINE];
	static int last_mem, buffer_pos, buffer_addr;
	static int writing_in_progress=0;
	register int i, sum;
 
	if (!writing_in_progress) {
		/* initial condition setup */
		last_mem = memory_location-1;
		buffer_pos = 0;
		buffer_addr = memory_location;
		writing_in_progress = 1;
		}
 
	if ( (memory_location != (last_mem+1)) || (buffer_pos >= MAXHEXLINE) \
	 || ((end) && (buffer_pos > 0)) ) {
		/* it's time to dump the buffer to a line in the file */
		fprintf(fhex, ":%02X%04X00", buffer_pos, buffer_addr);
		sum = buffer_pos + ((buffer_addr>>8)&255) + (buffer_addr&255);
		for (i=0; i < buffer_pos; i++) {
			fprintf(fhex, "%02X", byte_buffer[i]&255);
			sum += byte_buffer[i]&255;
		}
		fprintf(fhex, "%02X\n", (-sum)&255);
		buffer_addr = memory_location;
		buffer_pos = 0;
	}
 
	if (end) {
		fprintf(fhex, ":00000001FF\n");  /* end of file marker */
		fclose(fhex);
		writing_in_progress = 0;
	}
 
	last_mem = memory_location;
	byte_buffer[buffer_pos] = byte & 255;
	buffer_pos++;
}
 
 
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.