Archive for October 2010

Perl, Embedded C, and a little more on the 8×8 LED matrix

So while I’m waiting for funding and time to get my afformentioned 8×8 led matrix parts, I’ve been spending my time working on a basic driver to test the apparatus via a scrolling text marquis. First of all, it’s funny how a quick and dirty chunk of test code can quickly turn into an interesting and in-depth project! I started out by designing a “library” of hexadecimal values that represent each letter, (for example A == 0x1F,0×28,0×48,0×28,0x1F, which is the columnar value that draws an A on the matrix) and then designing a C program that writes the text to the matrix and scrolls it across the screen using the atmega328P’s timers to multiplex and scroll the message (insert link to code here!). Essentially, this algorithm operates by using one timer output compare interrupt to update the display periodically, and another to increment through the message array periodically. This was simple enough (actually more simple than I had anticipated, which excites me). The problem was creating the array of hex values that contained the message was insanely tedious. For each letter in the message, I had to manually input up to 6 hex values which leaves quite a bit of room for error, and sore wrists. So I figured there had to be an easier way to go about this. What I wanted to do was create a program that took a string of text, encoded it into the hex value array, and then plugged the resulting value into the array that was read from. I didn’t want to do this in the main code as micros only have a limited amount of program space and I didn’t want to bog the program down with something that only had to be run once. So I figured that a script would do the trick. I read somewhere once (wikipedia I think) that Perl was originally designed for working with text files, so I figured that it was a natural choice for my needs. I had never used Perl before and was only barely familiar with the syntax and datatypes, but after about an hour of googling and a quick forum post I had successfully designed a script that read a string in from an input file, used a hash to translate the values into the hex strings, and stuck the whole thing in as a properly formatted C array into the code. Basically, thanks to Perl, I can take a string from an input file, properly update and compile my C source file and load it up all in a few keystrokes! Once again, I’m pretty excited. I feel that this is what computer programming is really all about, taking tedious and repetitive tasks and creating new ways to NOT do them.

The Perl Script:

#!/usr/bin/env perl
################################################################################
# marqconv.pl is a perl hack that I threw together to modify the C source file
# marquis.c This script reads a line in from a text file, translates it through
# a hash into an array of hexadecimal values and then writes these array
# elements to the appropriate array in marquis.c
# basically this is the most awesome thing ever written.
################################################################################
use strict;
use warnings;
use Tie::File;

# Hash relating characters to their hex array values for use in the C program.
my %hashkey = (
	" " => "0x00,0x00,0x00,0x00,				/* space */",
	"A" => "0x1F,0x28,0x48,0x28,0x1F,0x00,0x00,		/*   A   */",
	"B" => "0x7F,0x49,0x49,0x36,0x00,0x00,			/*   B   */",
	"C" => "0x3E,0x41,0x41,0x41,0x22,0x00,0x00,		/*   C   */",
	"D" => "0x7F,0x81,0x81,0x3E,0x00,0x00,			/*   D	 */",
	"E" => "0x7F,0x49,0x49,0x49,0x00,0x00,			/*   E   */",
	"F" => "0x7F,0x48,0x48,0x40,0x00,0x00,			/*   F   */",
	"G" => "0x3E,0x41,0x41,0x45,0x26,0x00,0x00,		/*   G   */",
	"H" => "0x7F,0x08,0x08,0x08,0x7F,0x00,0x00,		/*   H	 */",
	"I" => "0x41,0x41,0x7F,0x41,0x41,0x00,0x00,		/*   I	 */",
	"J" => "0x02,0x01,0x01,0x3E,0x00,0x00,			/*   J   */",
	"K" => "0x7F,0x08,0x14,0x22,0x41,0x00,0x00,	        /*   K	 */",
	"L" => "0x7F,0x01,0x01,0x01,0x00,0x00,			/*   L   */",
	"M" => "0x7F,0x20,0x10,0x20,0x7F,0x00,0x00,		/*   M   */",
	"N" => "0x7F,0x20,0x08,0x02,0x7F,0x00,0x00,		/*   N   */",
	"O" => "0x1C,0x22,0x41,0x41,0x22,0x1C,0x00,0x00,	/*   O   */",
	"P" => "0x7F,0x48,0x48,0x60,0x00,0x00,			/*   P   */",
	"Q" => "0x1C,0x22,0x41,0x49,0x22,0x1D,0x00,0x00,	/*   Q   */",
	"R" => "0x7F,0x48,0x4C,0x33,0x00,0x00,			/*   R   */",
	"S" => "0x32,0x49,0x49,0x26,0x00,0x00,			/*   S   */",
	"T" => "0x40,0x40,0x7F,0x40,0x40,0x00,0x00,		/*   T   */",
	"U" => "0x7E,0x01,0x01,0x01,0x7E,0x00,0x00,		/*   U   */",
	"V" => "0x7C,0x02,0x01,0x02,0x7C,0x00,0x00,		/*   V   */",
	"W" => "0x7F,0x02,0x04,0x02,0x7F,0x00,0x00,		/*   W   */",
	"X" => "0x63,0x14,0x08,0x14,0x63,0x00,0x00,		/*   X   */",
	"Y" => "0x40,0x20,0x1F,0x20,0x40,0x00,0x00,		/*   Y   */",
	"Z" => "0x43,0x45,0x49,0x51,0x61,0x00,0x00,		/*   Z   */",
	"." => "0x02,0x00,0x00,					/*   .   */",
	"!" => "0x7C,0x00,0x00,					/*   !   */",
	"?" => "0x5A,0x50,0x70,0x00,0x00,			/*   ?   */",
	"0" => "0x3E,0x43,0x49,0x61,0x3E,0x00,0x00,		/*   0   */",
	"1" => "0x21,0x7F,0x01,0x00,0x00,			/*   1   */",
	"2" => "0x21,0x43,0x45,0x49,0x31,0x00,0x00,		/*   2   */",
	"3" => "0x22,0x14,0x94,0x55,0x22,0x00,0x00,		/*   3   */",
	"4" => "0x18,0x28,0x48,0x7F,0x08,0x00,0x00,		/*   4   */",
	"5" => "0x79,0x49,0x49,0x4F,0x00,0x00,			/*   5   */",
	"6" => "0X3e,0X49,0x,49,0x26,0x00,0x00,			/*   6   */",
	"7" => "0x40,0x47,0x58,0x60,0x00,0x00,			/*   7   */",
	"8" => "0x36,0x49,0x49,0x36,0x00,0x00,			/*   8   */",
	"9" => "0x30,0x48,0x48,0x3F,0x00,0x00,			/*   9   */",
);

# specify file to be edited.
my $codefile = 'marquis.c';

# specify the point in the file to be edited.
my $arraystr = 'volatile const uint8_t marquis[] = {';

# Open up my input files
open(my $in, "<", "string.txt") or die "Cuidado! Piso Mojado: $!";
tie my @code, 'Tie::File', $codefile or die "Cuidado! Piso Mojado: $!";

# Read in the string from the input file and chomp off newline
chomp(my $string = <$in>);

# convert string to upper case to make things easier
$string = uc($string);

# convert string to array of characters
my @line = split('',$string);

# initialize an empty array
my @datalines = ();

# push a leading space into the array
push(@datalines,$hashkey{" "});

# take each character and push it's hex matrix to the array
foreach (@line)
{
	push(@datalines,$hashkey{$_});
}

# add a trailing space with no trailing comma.
push(@datalines,"0x00,0x00,0x00,0x00");

# close all files
close($in);

# calculate the start and length for the splice function.
my $start = (grep {$code[$_] eq $arraystr} 1..$#code)[0]+1;
my $length = (grep {$code[$_] eq '};' and $_>$start} 1..$#code)[0] - $start;

# splice our output into the file to be modified.
splice @code, $start, $length, @datalines;

# close file.
untie @code;

and the C code

/*******************************************************************************
 * File: marquis.c
 * Owner: Cyrus Metcalf (cyrus.metcalf@gmail.com)
 * Date: October 25, 2010
 *
 * Marquis.c is a simple test driver for the atmega328P microcontroller
 * to run a scrolling marquis across an 8x8 LED matrix of my own design.
 *******************************************************************************/

//=====================
//HEADERS
//=====================
#include
#include

//======================
//CONSTANTS
//======================

//#define MAX 77 //length of Marquis, manually calculated.

#define MAX(x) (sizeof(x) / sizeof * (x))

//======================
void ioinit(void);      	//Initializes IO
void timer_0_set_up(void); 	//Initialize Timer 0
void timer_2_set_up(void); 	//Initialize Timer 2
//======================

/* Array autogenerated by marqconv.pl  */
volatile const uint8_t marquis[] = {
0x00,0x00,0x00,0x00,				/* space */
0x7F,0x08,0x08,0x08,0x7F,0x00,0x00,		/*   H	 */
0x7F,0x49,0x49,0x49,0x00,0x00,			/*   E   */
0x7F,0x01,0x01,0x01,0x00,0x00,			/*   L   */
0x7F,0x01,0x01,0x01,0x00,0x00,			/*   L   */
0x1C,0x22,0x41,0x41,0x22,0x1C,0x00,0x00,	/*   O   */
0x00,0x00,0x00,0x00,				/* space */
0x1F,0x28,0x48,0x28,0x1F,0x00,0x00,		/*   A   */
0x7F,0x48,0x4C,0x33,0x00,0x00,			/*   R   */
0x3E,0x41,0x41,0x41,0x22,0x00,0x00,		/*   C   */
0x7F,0x08,0x08,0x08,0x7F,0x00,0x00,		/*   H	 */
0x7F,0x01,0x01,0x01,0x00,0x00,			/*   L   */
0x41,0x41,0x7F,0x41,0x41,0x00,0x00,		/*   I	 */
0x7F,0x20,0x08,0x02,0x7F,0x00,0x00,		/*   N   */
0x7E,0x01,0x01,0x01,0x7E,0x00,0x00,		/*   U   */
0x63,0x14,0x08,0x14,0x63,0x00,0x00,		/*   X   */
0x7C,0x00,0x00,					/*   !   */
0x00,0x00,0x00,0x00
};

volatile uint8_t position = 0;

int main (void)
{
	ioinit();
	timer_0_set_up();
	timer_2_set_up();

	sei();

	while(1)
	{
		//wait for interrupt.
	}

	return(0);
}

void ioinit (void)
{
    //1 = output, 0 = input
    DDRB = 0b11111111; //All outputs
    DDRC = 0b11111111; //All outputs
    DDRD = 0b11111111; //PORTD (RX on PD0)
}

/* Timer 0 output compare interrupt every 18 Hz to scroll Marquis */
void timer_0_set_up(void)
{
	TIMSK0 = _BV(OCF0A); //enable output compare interrupt
	TCCR0A = _BV(WGM01); //enable CTC mode
	TCCR0B = _BV(CS02);  //set prescaler to clk/256
	OCR0A  = 217;	     //increment every 18Hz.
}
/* Timer 2 output compare interrupt every 10Hz to multiplex the display */
void timer_2_set_up(void)
{
	TIMSK2 = _BV(OCF2A); //enable output compare interrupt
	TCCR2A = _BV(WGM01); //enable CTC mode
	TCCR2B = _BV(CS02) | _BV(CS01); //set prescaler to clk/1024
	OCR2A  = 98;	     //increment every 10Hz
}

ISR(TIMER0_COMPA_vect)
{
	/* increment the position to scroll the text */

	if ((position + 7) == MAX(marquis))//prevent array overflow, restart marquis
	{
		position = 0;
	}
	position++;
}
ISR(TIMER2_COMPA_vect)
{

	/* multiplex the LED Matrix and display the value
	 * stored to PortB on the given column*/

	for (uint8_t offset = 0; offset < 8; offset++)
	{
		PORTD = offset;
		PORTB = marquis[position + offset];
	}
}

Scrolling Marquis: more fun with timers

After spending the last week playing around with the timers and interrupts of the AtMega328P Microcontroller (see my previous KITT post!)  I’ve decided it’s time to “move up in Farmville” and build myself a new multi-function prototyping device.  up until now, I’ve been playing with buzzers, 4×7 numeric displays, keypad matrices, and just plain LED’s and I’ve decided my next move is to hack together an 8×8 LED matrix.  LED matrices are double plus awesome because they provide you the flexibility of displaying relatively complex output.  The theory behind them is you create a square (or rectangular) grid of LED’s, tie all of the columns low and all of the rows high, and bam you have X number of uniquely addressable LED’s.  Now, the problem with this layout is if you have an 8×8 matrix, you are going to need 16 IO pins to address all of the LED’s (8 for the columns, 8 for the rows)  this would be the easiest to code together since no multiplexing is involved, however, your design is going to be drawing a ridiculous amount of current and use up a huge number of valuable IO pins on your micro.  So, to work around this problem we use multiplexing.  the theory behind this is that you only turn on one row or column at a time REALLY fast, the human eye cannot discern this at >20Hz! thereby reducing the amount of current drawn but increasing the code complexity.  I considered designing my matrix using double multiplexing between 2 3-8 muxes one for the rows and one for the columns, this would drop the number of IO pins used to address the LEDs to 6, and provide the best performance for power, however the complexity of implementation in code is a little too crazy. why not make things easy on our selves and multiplex the columns and then directly address each row!  it’s the best of both worlds.  So here’s my final prototype for my 8×8 LED Matrix:

matrix pcb

matrix pcb

It’s going to be a little while before I can work with this guy. It’s going to take a month to fab the board and get all of the parts necessary. but I’ve got loads of ideas for working with this device. First of all, I’m designing a scrolling marquis that can be programmed via the serial port, and I’m also working on creating a “snake” game that uses a 2D accelerometer for directional input.

also, this design, and all code for it were designed on an arch linux box using the gEDA design suite, and the gcc-avr compiler, with vim as my text editor and avrdude as my programmer.

more to come when I have a functional prototype (I’m so excited!)

KITT the car micro controller fun.

I was thinking that it’s been a while since I’ve made a post on here. I’ve been really really busy with work/school/kids etc. and I haven’t really had too much “me time” lately to play around with circuits and computers. So, mostly to keep my account on here semi-active, I decided to share my most recent project.

This circuit is commonly known as the Larson Scanner, named for Gary Larson the creator KITT from Knight Rider and the Cylons from BSG. My goal with this project was to learn/play with the various timers and interrupts on my ATMega328P micro controller. I’ve implemented the buzzer on Timer 0 using a simple output compare that toggles the I/O pin at the desired frequency and I added the LED Chaser on timer2 with an output compare interrupt that sweeps through the light sequence. timers and interrupts are awesome in the biblical sense. you wouldn’t believe some of the elaborate programs you can create just using a basic timer setup! well, that’s about all I have time for now.

Apparently WP doesn’t play well with embedded youtube players (or I’m doing something wrong), so here’s a link to the video I was going to post.
AWESOME VIDEO

Source Code Files