BCD Conversion #Define(s)

For issues with communication ports, protocols, etc.
Post Reply
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

BCD Conversion #Define(s)

Post by MrSwiss »

Since certain devices require it, to use BCD formatted UBytes, this two #Define(s)
might come in handy, to solve communication problems, with such devices.

#Define setBCD(v) converts from: base 16 to: base 10 (v = Decimal/Hex)
#Define getBCD(v) converts from: base 10 to: base 16 (v = BCD)

BCD_Mac.bas (including some test code):

Code: Select all

' toBCD_Mac.bas -- (c) 2020-07-03, MrSwiss
'
' compile: -s console
'

#Define setBCD(v)   ( CUByte((v) \ 10 Shl 4 + (v) Mod 10) )     ' base 16 to base 10
#Define getBCD(v)   ( CUByte(((v) Shr 4) * 10 + ((v) And 15)) ) ' base 10 to base 16


Dim As Ubyte    buffer(0 To 6)          ' size as required (by device)

Print "DEC"; Tab(9); "BCD-format"; Tab(25); "BIN/HEX"
Print

For i As UInteger = 0 To 99             ' min/max BCD range
    buffer(0) = setBCD(i)               ' set to BCD format (Base 10)
    buffer(1) = getBCD(buffer(0))       ' reset to BIN/HEX  (Base 16)
    Print i; Tab(9); Bin(buffer(0), 8); _
          Tab(25); Bin(buffer(1), 8)    ' show them both
Next

Print : Print : Print "... done ... ";

Sleep
marcov
Posts: 3455
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: BCD Conversion #Define(s)

Post by marcov »

setbcd

aam
mov dl,ah
shl dl,4
or al,dl
xor ah,ah

getbcd

mov ah,al
shr ah,4
and al,15
aad
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: BCD Conversion #Define(s)

Post by MrSwiss »

Nice explanation but ... don't know how many here, are understanding ASM ?!?
(suppose probably less than 10% of all members)
marcov
Posts: 3455
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: BCD Conversion #Define(s)

Post by marcov »

It is pre pentium era fun. I'm not even sure if those instructions are really faster nowadays.

And most members seem to handle horrible preprocessor stuff just fine (look at all the container type discussions). ASM is much simpler.
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: BCD Conversion #Define(s)

Post by MrSwiss »

marcov wrote:It is pre pentium era fun.
Even a 8086 can cope with that.
marcov wrote:I'm not even sure if those instructions are really faster nowadays.
Agree, likely to be slower even ...
marcov
Posts: 3455
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: BCD Conversion #Define(s)

Post by marcov »

MrSwiss wrote:
marcov wrote:It is pre pentium era fun.
Even a 8086 can cope with that.
marcov wrote:I'm not even sure if those instructions are really faster nowadays.
Agree, likely to be slower even ...
That's what I meant with pre-pentium. Starting with pentium-I and more importantly later Pentium-Pro, using standard simple instructions is usually faster than using "weird" legacy instructions that are implemented using microcode.

My big app in the nineties (in Modula-2, if somebody remembers that), mostly did BBS logfile processing and analysis, and to make it fast, I had a whole bunch of date-time routines in assembler, which is why I can still remember this instantly.

Date-time strings are substrings that are small numbers (seconds, minutes, hours days, months and even years without century), so converting them from ascii to integers worked using these kind of tricks. (I think I had a Cyrix P166+ in that time, which was more 486 than pentium-I in this respect).
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: BCD Conversion #Define(s)

Post by jj2007 »

marcov wrote:Starting with pentium-I and more importantly later Pentium-Pro, using standard simple instructions is usually faster than using "weird" legacy instructions that are implemented using microcode.
Usually. Some of them are actually very fast, e.g. rep movsd
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: BCD Conversion #Define(s)

Post by MrSwiss »

Back on topic, please. (aka: ... End Asm ...)

BCD has as caped value, when compared to Hex, because the representation
of A to F (10 to 15 decimal) isn't ever used in a Nibble (value = 0 to 9 dec).
A Nibble is a half-Byte, which means it consists of 4 bits (hi and low = UByte).
In order to avoid the sign-bit issues, it's typically used with unsigned byte.

Example:
24 decimal, in ordinary Hex: &b00011000 = 1 (* 16) + 8
in BCD however, it becomes: &b00100100 = 2 (* 10) + 4
marcov
Posts: 3455
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: BCD Conversion #Define(s)

Post by marcov »

Actually, BCD is a digit per byte/word. Digit per nibble is "packed BCD". Afaik forms of EAN 128 barcodes still use it.
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: BCD Conversion #Define(s)

Post by MrSwiss »

Yes, it's packed BCD, which is also used in devices, like RTC's e.t.c.
And this is, what this thread is all about.
Flyzone
Posts: 109
Joined: Nov 17, 2017 17:39

Re: BCD Conversion #Define(s)

Post by Flyzone »

Rather than start a new topic I thought I'd tack on to this old one on BCD conversions ...

I have downloaded a piece of history in the form on a BCD "tape". It has software from the 1960s on it that I am trying to run in a 1401 simulator running on Windows. I have a mental block on trying to convert this into to something I can use on the IBM1401 simulator on my Windows computer.

I am looking for a conversion program that will take this file and convert it for my use as "mag tape" input in ASCII format (I guess) on my SimH simulator.

The first three records on the file contain the information below. The top line of each series of 2 is the ASCII representation of the hex info on the second line for each record. The first digit is the record sequence number on the file.

1 ¥ r
1 9D72
2 A
2 41
3 c ↔ r H D D ↔ ¶ \ ¶ A i ↔ c \ ¶ A
3 631D724844441D145C1441691D635C1441

The conversion programs I've come across use C and I don't know C so I can't make heads or tails of the various procedures and formulas that are already out there. I am looking to find or create something to convert this stuff using FB.

In case you're interested, the file on the tape (referenced below) is supposedly the original IBM supplied "Sort7" program for the IBM 1401 computer first produced in 1959. The computer used BCD encoding. I do not know the process used to copy that file from tape to downloadable format.

----------------------------
The above print was produced with the following code I developed. The source was from the download of the archive tape at http://piercefuller.com/library/connecticut-d.html

Code: Select all

dim as string r,a,p,f
dim as integer i,n
f = "adc00231.bcd"

open f for input as #1

do
    p = ""
    a = ""
    line input #1,r
    For i = 0 to len(r) - 1
        p = p + hex(r[i],2)
        a = a + chr(r[i]) & " "
    next i
    n = n + 1
    print n,a
    print n,p
loop while not eof(1)

close
sleep
end
grindstone
Posts: 862
Joined: May 05, 2015 5:35
Location: Germany

Re: BCD Conversion #Define(s)

Post by grindstone »

Hello Flyzone.

The conversion shouldn't be rocket science, as soon as I know the destination format. From a first glance I suppose the data of the file has to be converted to IBM's punched card format, but that's only a guess. So could you post a link to (at least) one of the C translation programs you came across?
Flyzone
Posts: 109
Joined: Nov 17, 2017 17:39

Re: BCD Conversion #Define(s)

Post by Flyzone »

I wish I could with some certainty. The references I have are lacking in documentation and there are many similar programs in one of the "libraries" (http://vandyke.mynetgear.com/1401/Pierce/tools/).

I suspect this might be one but I'm not sure. I'm just going by the name which was BCD2TXT. I'm thinking I would wind up with an Windows/ASCII extended data file.

Code: Select all

#include <stdlib.h>
#include <stdio.h>
#include "asciibcd.h"
#include "prsf2.h"

#define MAXREC 10000

char fin[300], fon[300];
unsigned char record[MAXREC];

void main(argc, argv)
	int	argc;
	char	**argv;
{
	int optind;
	char *optarg;
	int blank;
        int cons; /* output to console */
	int ftn;
	register int c;
	FILE *fi, *fo;
	int fileflag;
	unsigned char *p;
	int reclen;

	blank = 0;
        cons = 0;
	ftn = 0;
	for (optind = 1, optarg = argv[optind];
		 optind < argc && *optarg == '-' || *optarg == '/';
		 optind++, optarg = argv[optind]) {
		++optarg;
		while (*optarg) {
			switch(*optarg++) {

			case 'b':
				blank = 1;
				break;

                        case 'c':
                                cons = 1;
                                break;

			case 'f':
				ftn = 1;
				break;

			default:
				fprintf(stderr, "Usage: bcd2txt [-fb] <in> <out> <record length>\n");
				fprintf(stderr, "  -b     Translate 0x50 to 0x00 (blank)\n");
				fprintf(stderr, "  -f     Use Fortran character set\n");
				exit(1);
			}
		}
	}

	reclen = MAXREC;
	parsefiles(argc - (optind-1), &argv[optind-1], "bcd", "txt", &reclen);
	if ((fi = fopen(fin, "rb")) == NULL) {
		perror(fin);
		exit(1);
	}
        if ( cons ) fo = stdout;
	else if ((fo = fopen(fon, "w")) == NULL) {
		perror(fon);
		exit(1);
	}
	p = record;
	fileflag = 1;
	while ( (c = fgetc(fi)) != EOF ) {
		if (c & 0200 || p - record == reclen ) { /* || c == 0132) { */
			while (p != record && p[-1] == ' ') {
				p--;
			}
			if (p != record) {
				fwrite(record, 1, p - record, fo);
				fputc('\n', fo);
			} else if (!fileflag) {
				fputc('\n', fo);
			}
			fileflag = 0;
			p = record;
		}
		if (c == 0217) {
			fputc('\f', fo);
			fileflag = 1;
		} else { /* if (c != 0132) { */
			if (blank && (c & 077) == 020) {
				*p++ = ' ';
			} else if (ftn) {
				*p++ = asciialt[c & 077];
			} else {
				*p++ = asciibcd[c & 077];
			}
		}
	}
	if (p != record) {
		while (p != record && p[-1] == ' ') {
			p--;
		}
		if (p != record) {
			fwrite(record, 1, p - record, fo);
			fputc('\n', fo);
		} else if (!fileflag) {
			fputc('\n', fo);
		}
	}
}
grindstone
Posts: 862
Joined: May 05, 2015 5:35
Location: Germany

Re: BCD Conversion #Define(s)

Post by grindstone »

In the file "tool.htm" of the link you posted you can find an explaination of the data format. So here, quick and dirty, without having a closer look at the C programs (and without guarantee), a first attempt of a conversion program:

Code: Select all

Dim As String g
Dim As Integer gi

Dim As String _bobS     = " 1234567890#@:>(^/STUVWXYZ',%=\+-JKLMNOPQR!$*];_&ABCDEFGHI?.)[<"
Dim As String _bobA     = " 1234567890#@:>tc/STUVWXYZr,%='-JKLMNOPQR!$*);d&ABCDEFGHI?.o(<g"
Dim As String _old      = " 1234567890=':>/STUVWXYZ,(\-JKLMNOPQR!$*];+ABCDEFGHI?.)[<"
Dim As String _newcomer = " 1234567890=':>icalb/STUVWXYZ|,%^\-JKLMNOPQR!$*];lta+ABCDEFGHI?.)[<"
Dim As String _A        = " 1234567890#@/STUVWXYZ|,%-JKLMNOPQR-$*&ABCDEFGHI&.o"
Dim As String _F        = " 1234567890='{^/STUVWXYZ|,(-JKLMNOPQR-$*+ABCDEFGHI&.)}"
Dim As String _Pierce   = " 1234567890#@:>{^/STUVWXYZ|,%~\" & Chr(32) & "-JKLMNOPQR!$*];_&ABCDEFGHI?.)[<}"

Open "adc00224.bcd" For Input As #1
Open "adc00224.con" For Output As #2
Do
	g = Input(1,#1)
	gi = g[0]
	'? Bin(gi, 8); " "; Hex(gi, 2); " ";
	gi And= &b00111111
	'? Bin(gi, 8); " "; Chr(_pierce[gi]) 
	Print #2, Chr(_pierce[gi]);
	'Sleep
Loop Until Eof(1)
Close
? "OK"
Sleep
Maybe you have to replace the "^" character (&h50) with a blank (CHR(0)).
Flyzone
Posts: 109
Joined: Nov 17, 2017 17:39

Re: BCD Conversion #Define(s)

Post by Flyzone »

OK. Thanks for this. I didn't go to the Tools site since it looked like more C stuff with the tar files which I'm not all that familiar with either but 7Zip opened it to my surprise. That was a good explanation of the encoding but it does look like a bit of a mess. Based on other stuff I've seen I don't think it really is as simple as that but we will give it a try. Thanks again for unlodging the logjam.
Post Reply