teletype / teletype.c

/**
 * \file 45 baud sync teletype interface
 *
 */

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include <string.h>
#include <util/delay.h>
#include "usb_serial.h"
#include "bits.h"


// Send a string to the USB serial port.  The string must be in
// flash memory, using PSTR
//
void send_str(const char *s)
{
	char c;
	while (1) {
		c = pgm_read_byte(s++);
		if (!c) break;
		usb_serial_putchar(c);
	}
}


static char
hexdigit(
	uint8_t x
)
{
	x &= 0xF;
	if (x < 0xA)
		return x + '0';
	else
		return x + 'A' - 0xA;
}


#define BAUDOT(a,b,c,d,e) ( \
	(1 << 0) | \
	(a << 1) | \
	(b << 2) | \
	(c << 3) | \
	(d << 4) | \
	(e << 5) | \
	(0 << 6) | \
	0 )

static uint8_t baudot[] = 
{
	['a'] = BAUDOT(0,0,1,1,1),
	['b'] = BAUDOT(0,1,1,0,0),
	['c'] = BAUDOT(1,0,0,0,1),
	['d'] = BAUDOT(0,1,1,0,1),
	['e'] = BAUDOT(0,1,1,1,1),
	['f'] = BAUDOT(0,1,0,0,1),
	['g'] = BAUDOT(1,0,1,0,0),
	['h'] = BAUDOT(1,1,0,1,0),
	['i'] = BAUDOT(1,0,0,1,1),
	['j'] = BAUDOT(0,0,1,0,1),
	['k'] = BAUDOT(0,0,0,0,1),
	['l'] = BAUDOT(1,0,1,1,0),
	['m'] = BAUDOT(1,1,0,0,0),
	['n'] = BAUDOT(1,1,0,0,1),
	['o'] = BAUDOT(1,1,1,0,0),
	['p'] = BAUDOT(1,0,0,1,0),
	['q'] = BAUDOT(0,0,0,1,0),
	['r'] = BAUDOT(1,0,1,0,1),
	['s'] = BAUDOT(0,1,0,1,1),
	['t'] = BAUDOT(1,1,1,1,0),
	['u'] = BAUDOT(0,0,0,1,1),
	['v'] = BAUDOT(1,0,0,0,0),
	['w'] = BAUDOT(0,0,1,1,0),
	['x'] = BAUDOT(0,1,0,0,0),
	['y'] = BAUDOT(0,1,0,1,0),
	['z'] = BAUDOT(0,1,1,1,0),
	[' '] = BAUDOT(1,1,0,1,1),
	['\n'] = BAUDOT(1,1,1,0,1),
	['\r'] = BAUDOT(1,0,1,1,1),
};

static void
tty_out(
	uint8_t ch
)
{
	uint8_t c = baudot[ch];
	if (c == 0)
		return;

	for (int i = 0 ; i < 7 ; i++)
	{
		int x = c & 1;
		c >>= 1;

		if (!x)
			out(0xD7, 1);
		else
			out(0xD7, 0);

		_delay_ms(22);
	}

	out(0xD7, 1);
}


int main(void)
{
	// set for 16 MHz clock
#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
	CPU_PRESCALE(0);

	// Disable the ADC
	ADMUX = 0;

	ddr(0xD7, 1);
	out(0xD7, 1);

	// initialize the USB, and then wait for the host
	// to set configuration.  If the Teensy is powered
	// without a PC connected to the USB port, this 
	// will wait forever.
	usb_init();
	while (!usb_configured())
		continue;

	_delay_ms(500);

	// wait for the user to run their terminal emulator program
	// which sets DTR to indicate it is ready to receive.
	while (!(usb_serial_get_control() & USB_SERIAL_DTR))
		continue;

	// discard anything that was received prior.  Sometimes the
	// operating system or other software will send a modem
	// "AT command", which can still be buffered.
	usb_serial_flush_input();

	ddr(0xD6, 1); // LED

	int status = 0;

	while (1)
	{
		int c = usb_serial_getchar();
		if (c == -1)
			continue;

		out(0xD6, 1);
		tty_out(c);
		out(0xD6, 0);
	}
}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.