/*
	asrout - Output filter to ASR-33
	convert stdin stream to be ASR-33 compatible
    Is necessary, because most interesting stty(1), termios(3) flags are not
    implemented in the Raspian kernel any more.

	- LF 0x0A is completed with a CR
	- after CR, wait time depends on position of print head

    ASR-33 must be set to 110 7E2 before with
         sudo stty -F /dev/ttyAMA0 110 cs7 cstopb

    Example for usage:
       pdp11.exe pdp11.ini </dev/ttyAMA0 | asrout

*/

#include <stdio.h>
//#include <sys/types.h>
//#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>

// port ASR-33 is conencted to.
char *devicenameASR = "/dev/ttyAMA0" ;

int curCol ; // current output column


int	fout ; // handle of ASR-33 tty port
int curChr ; // current unprocessed input character


// fetch next char into curChr ;
int nextChr() {
	int res ;
	// read blocking
	do {
		curChr = getchar() ;
		if (curChr == EOF)
			usleep(10000) ; // 10 milliseconds

	} while (curChr == EOF) ;
//fprintf(stdout, "get() 0x%x\n", curChr) ;
	return curChr ;
}

// character to ASR-33
// evaluates LF and CR
void	putASRchr(int chr) {
//fprintf(stdout, "put(0x%x ", chr) ;
	if (chr >= ' ') {
		chr = toupper(chr) ;
		curCol++ ;
		write(fout, &chr, 1) ;
	} else if (chr == 7) { // BELL
		write(fout, &chr, 1) ;
	} else if (chr == 0x0d && curCol > 0) { // CR carriage return
		// crraige needs 500ms on pos 72
		int wait_ms = 200 + 500 * curCol / 72 ; // time for carriage return
		// time for moving print head left
		write(fout, &chr, 1) ;
		usleep(1000*wait_ms) ;
		curCol = 0 ;
	} else if (chr == 0x0a) { // LF line feed
		int wait_ms = 100 ; // ms wait to settle
		write(fout, &chr, 1) ;
		usleep(1000 * wait_ms) ;
	} else
		chr = 0 ;
//	if (chr!= 0)
//		fprintf(stdout, " => 0x%x\n", chr) ;
}


int main(int argc, char **argv)
{
	fout = open(devicenameASR, O_WRONLY | O_CLOEXEC) ;
	curCol = 0 ;
	while(1) {
		nextChr() ;
		if (curChr == 0x0A)
			putASRchr(0x0d) ; // LF -> CR LF
		putASRchr(curChr) ;

	}

}


