Some very fragile code that - on visual inspection - produces a binary blob which ought to program the neolithic. It's seriously dodgy code, take with two aspirins and a dose of salt. But it does appear to work with a properly formed intel 8-bit hex file.
Note: it's for Linux. I don't think Windows includes getline() but there are probably versions online if it doesn't. I'll probably just copy the blob to the \dev\ttyUSB0 port directly, but there's a mechanism to send via minicom here:
https://www.dannysung.com/articles/linu ... a-minicom/Don't forget that the comm port speed will need to be 19k2 for the boot load and something rather higher - 115k2 likely - for actual comms.
Neil
Code:
// convert an existing intel 8-bit hex file to a binary blob which can
// be used to load the Neolithic Romless 6502 processor
// three addressable uarts handle the address and data and write strobe,
// a fourth resets the processor after memory is loaded
// - 0x0 data and strobe
// - 0x1 address low byte
// - 0x2 address high byte (page)
// - 0x3 reset
//
// (c) nailed_barnacle 2023
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
void decode_data (uint8_t data)
{
printf ("%02x %01x\t%01x\t%01x\n", data, data >> 4, (data & 0x0e) >> 1, data & 0x01);
}
uint8_t build_txbyte (int8_t val, int8_t target, bool first)
{
// convert a single byte into the first packet value
// bit 0 - always 1
// bit 1-3 - target address
// bit 4-7 - low nibble of val if first is true
// - high nibble of val if first is false
uint8_t res = 1; // bit 0 = 1
res += (target & 7) << 1;
if (first)
{
res += (val & 0x0f) << 4;
}
else
{
res += (val & 0xf0);
}
return res;
}
void output_txpair (int8_t val, int8_t target, FILE * fo)
{
uint8_t first;
uint8_t second;
// output two bytes to fo
first = build_txbyte (val, target, true);
second = build_txbyte (val, target, false);
fprintf (fo, "%c%c", first, second);
decode_data (first);
decode_data (second);
}
void output_page (uint8_t page, FILE * fo)
{
// output a page address to uart 2
// if we only send this when it changes, we increase tranfer speed
// by about fifty percent
output_txpair (page, 2, fo);
}
void output_add_data (uint8_t addr, uint8_t data, FILE * fo)
{
// write a byte at the selected address on the current page
output_txpair (addr, 1, fo);
output_txpair (data, 0, fo); // this writes to the ram
}
int main (int argc, char ** argv)
{
// read an intel hex file and write the data into a binary file
// such that it can be used directly to load the neolithic romless
// processor
FILE * fi;
FILE * fo;
char * line = NULL;
size_t len = 0;
ssize_t nread;
int record_type;
int record_count;
int record_addr;
int record_data;
// sanity check input
if (argc < 3)
{
printf ("Usage: lv8153 <input hex file> <output binary file>\r\n");
return 1;
}
// open input and output files
if (NULL == (fi = fopen (argv[1], "r")))
{
printf ("Can't open input file %s\n", argv[1]);
return 1;
}
if (NULL == (fo = fopen (argv[2], "w")))
{
printf ("Can't open output file %s\n", argv[2]);
fclose (fi);
return 1;
}
// now we can plough through the file one line at a time
// this will only work for a properly formed hex file, not robust!
// - two hex digits for payload count
// - four hex digits for load address (high byte first)
// - two hex digits as record type: 00 for data, 01 for end of file
// - data as two hex digits, repeated count times
// - two hex digits as checksum (we ignore this)
while (-1 != (nread = getline (&line, &len, fi)))
{
sscanf (line, ":%02x%04x%02x", &record_count, &record_addr, &record_type);
if (0 == record_type)
{
// only for types we understand
// send high byte of target
output_page ((record_addr & 0xff00) >> 8, fo);
for (int q = 0; q < record_count; q++)
{
// for each data byte
sscanf (&line[9 + (q * 2)], "%02x", &record_data);
output_add_data (record_addr & 0xff, record_data, fo);
record_addr++;
if (0x00 == record_addr & 0xff)
{
// if the page rolls over in the middle of the line
output_page ((record_addr & 0xff00) >> 8, fo);
}
}
printf ("\n");
}
}
// finally reset the processor
output_txpair (0, 3, fo);
fclose (fi);
fclose (fo);
printf ("Load complete\n");
}