Source

seven / seven.c

Full commit
/**
 * \file Seven segment driver
 *
 */

#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"


#define LED			0xD6


void send_str(const char *s);
uint8_t recv_str(char *buf, uint8_t size);
void parse_and_execute_command(const char *buf, uint8_t num);

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



// 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 void
led(
	uint8_t val
)
{
	if (val)
		out(LED, 1);
	else
		out(LED, 0);
}


/*  4
 * 5 3
 *  7
 * 0 2
 *  1 
 *
 * 6 is not used since D6 drives the onboard LED.
 */
static uint8_t digits[] = {
	1 << 3 | 1 << 1 | 1 << 0 | 1 << 5 | 1 << 4 | 1 << 2, // 0
	1 << 3 | 1 << 2, // 1
	1 << 4 | 1 << 1 | 1 << 7 | 1 << 0 | 1 << 3, // 2
	1 << 4 | 1 << 2 | 1 << 7 | 1 << 3 | 1 << 1, // 3
	1 << 5 | 1 << 7 | 1 << 2 | 1 << 3, // 4
	1 << 4 | 1 << 5 | 1 << 7 | 1 << 2 | 1 << 1, // 5
	1 << 4 | 1 << 0 | 1 << 7 | 1 << 2 | 1 << 5 | 1 << 1, // 6
	1 << 4 | 1 << 2 | 1 << 3, // 7
	1 << 3 | 1 << 1 | 1 << 0 | 1 << 5 | 1 << 4 | 1 << 2 | 1 << 7, // 8
	1 << 5 | 1 << 7 | 1 << 2 | 1 << 3 | 1 << 4, // 9
	1 << 0, // chase
	1 << 1, // chase
	1 << 2, // chase
	1 << 3, // chase
	1 << 4, // chase
	1 << 5, // chase
};



static void
chase(
	uint8_t count,
	uint8_t delay
)
{
	for (uint8_t i = 0 ; i < count ; i++)
	{
		uint8_t mask = 1;
		for (uint8_t j = 0 ; j < 6 ; j++, mask <<= 1)
		{
			DDRC = mask;
			_delay_ms(delay);
		}
	}
}


/** "Frame buffer" of output LEDs.
 * Since we can't drive all LEDs simultaneously, instead draw them from
 * this frame buffer.
 */
static uint8_t outputs[4];


static void
draw(void)
{
	uint8_t mask = 3;

	for (uint8_t i = 0 ; i < 4 ; i++, mask <<= 2)
	{
		// skip output 6
		//if (i == 6)
			////mask <<= 1;

		DDRB = outputs[0] & mask;
		DDRC = outputs[1] & mask;
		DDRD = outputs[2] & mask;
		DDRF = outputs[3] & mask;
		_delay_us(10);
	}

	DDRB = 0;
	DDRC = 0;
	DDRD = 0;
	DDRF = 0;
}


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

	// Disable the ADC
	ADMUX = 0;

	// 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();

	// LED is an output; will be pulled down once connected
	ddr(LED, 1);
	out(LED, 1);

	while (!usb_configured())
		;

	_delay_ms(1000);

	// 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))
		;

	// 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();

	send_str(PSTR("seven segment\r\n"));
	uint8_t val = 9;
	DDRC = 1 << 7;
	PORTC = 0;


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

		if (val == 10)
		{
			//chase(4, 100);
			val = 0;
		}

		const uint8_t output = digits[val++];
		outputs[0] = outputs[1] = outputs[2] = outputs[3] = output;

		for (uint16_t i = 0 ; i < 20000 ; i++)
			draw();
	}
}