place the strings you wish to display in the text array. at the end of each line put a null character. your messages will be displayed one line at a time with a pause of approximately 1/2 a second between lines.
this program will only display ascii text. and only characters between 32 and 127.
there used to be GPL text in the comment at the beginning of the code, but the spam filter found the language objectionable.
Code: Select all
/*
*/
#include "avr/io.h" // i/o definitions
#include "avr/interrupt.h" // definitions for interrupts
#include "avr/pgmspace.h" // definitions for data in program memory
#include "avr/sleep.h" // definitions for idling mcu
#define GLYFWIDTH 5
//
// data in program memory
//
// foo - avrobjdump trashes the first symbol after the interrupt vectors,
// so we'll just feed it this.
// text - display text is a single string with lines delimited with nulls
// povGlyf - character bitmaps. each character is 5 bytes, one per column of
// of a 5x8 cell. low order bit is the top.
int foo PROGMEM = 666;
char text[] PROGMEM = "The Moving Finger writes; and, having writ,\0"
"Moves on; nor all your Piety nor Wit\0"
"Shall lure it back to cancel half a Line,\0"
"Nor all your Tears wash out a Word of it.";
uint8_t povGlyf[] PROGMEM = {
/* */ 0x00,0x00,0x00,0x00,0x00, /* ! */ 0x00,0x00,0x5f,0x00,0x00,
/* " */ 0x00,0x07,0x00,0x07,0x00, /* # */ 0x14,0x7f,0x14,0x7f,0x14,
/* $ */ 0x24,0x2a,0x7f,0x2a,0x12, /* % */ 0x23,0x13,0x08,0x64,0x62,
/* & */ 0x36,0x49,0x55,0x22,0x50, /* ' */ 0x00,0x05,0x03,0x00,0x00,
/* ( */ 0x00,0x1c,0x22,0x41,0x00, /* ) */ 0x00,0x41,0x22,0x1c,0x00,
/* * */ 0x08,0x2a,0x1c,0x2a,0x08, /* + */ 0x08,0x08,0x3e,0x08,0x08,
/* , */ 0x00,0x50,0x30,0x00,0x00, /* - */ 0x08,0x08,0x08,0x08,0x08,
/* . */ 0x00,0x60,0x60,0x00,0x00, /* / */ 0x20,0x10,0x08,0x04,0x02,
/* 0 */ 0x3e,0x51,0x49,0x45,0x3e, /* 1 */ 0x00,0x42,0x7f,0x40,0x00,
/* 2 */ 0x42,0x61,0x51,0x49,0x46, /* 3 */ 0x21,0x41,0x45,0x4b,0x31,
/* 4 */ 0x18,0x14,0x12,0x7f,0x10, /* 5 */ 0x27,0x45,0x45,0x45,0x39,
/* 6 */ 0x3c,0x4a,0x49,0x49,0x30, /* 7 */ 0x01,0x71,0x09,0x05,0x03,
/* 8 */ 0x36,0x49,0x49,0x49,0x36, /* 9 */ 0x06,0x49,0x49,0x29,0x1e,
/* : */ 0x00,0x36,0x36,0x00,0x00, /* ; */ 0x00,0x56,0x36,0x00,0x00,
/* < */ 0x00,0x08,0x14,0x22,0x41, /* = */ 0x14,0x14,0x14,0x14,0x14,
/* > */ 0x41,0x22,0x14,0x08,0x00, /* ? */ 0x02,0x01,0x51,0x09,0x06,
/* @ */ 0x32,0x49,0x79,0x41,0x3e, /* A */ 0x7e,0x11,0x11,0x11,0x7e,
/* B */ 0x7f,0x49,0x49,0x49,0x36, /* C */ 0x3e,0x41,0x41,0x41,0x22,
/* D */ 0x7f,0x41,0x41,0x22,0x1c, /* E */ 0x7f,0x49,0x49,0x49,0x41,
/* F */ 0x7f,0x09,0x09,0x01,0x01, /* G */ 0x3e,0x41,0x41,0x51,0x32,
/* H */ 0x7f,0x08,0x08,0x08,0x7f, /* I */ 0x00,0x41,0x7f,0x41,0x00,
/* J */ 0x20,0x40,0x41,0x3f,0x01, /* K */ 0x7f,0x08,0x14,0x22,0x41,
/* L */ 0x7f,0x40,0x40,0x40,0x40, /* M */ 0x7f,0x02,0x04,0x02,0x7f,
/* N */ 0x7f,0x04,0x08,0x10,0x7f, /* O */ 0x3e,0x41,0x41,0x41,0x3e,
/* P */ 0x7f,0x09,0x09,0x09,0x06, /* Q */ 0x3e,0x41,0x51,0x21,0x5e,
/* R */ 0x7f,0x09,0x19,0x29,0x46, /* S */ 0x46,0x49,0x49,0x49,0x31,
/* T */ 0x01,0x01,0x7f,0x01,0x01, /* U */ 0x3f,0x40,0x40,0x40,0x3f,
/* V */ 0x1f,0x20,0x40,0x20,0x1f, /* W */ 0x7f,0x20,0x18,0x20,0x7f,
/* X */ 0x63,0x14,0x08,0x14,0x63, /* Y */ 0x03,0x04,0x78,0x04,0x03,
/* Z */ 0x61,0x51,0x49,0x45,0x43, /* [ */ 0x00,0x00,0x7f,0x41,0x41,
/* \ */ 0x02,0x04,0x08,0x10,0x20, /* ] */ 0x41,0x41,0x7f,0x00,0x00,
/* ^ */ 0x04,0x02,0x01,0x02,0x04, /* _ */ 0x40,0x40,0x40,0x40,0x40,
/* ` */ 0x00,0x01,0x02,0x04,0x00, /* a */ 0x20,0x54,0x54,0x54,0x78,
/* b */ 0x7f,0x48,0x44,0x44,0x38, /* c */ 0x38,0x44,0x44,0x44,0x20,
/* d */ 0x38,0x44,0x44,0x48,0x7f, /* e */ 0x38,0x54,0x54,0x54,0x18,
/* f */ 0x08,0x7e,0x09,0x01,0x02, /* g */ 0x08,0x14,0x54,0x54,0x3c,
/* h */ 0x7f,0x08,0x04,0x04,0x78, /* i */ 0x00,0x44,0x7d,0x40,0x00,
/* j */ 0x20,0x40,0x44,0x3d,0x00, /* k */ 0x00,0x7f,0x10,0x28,0x44,
/* l */ 0x00,0x41,0x7f,0x40,0x00, /* m */ 0x7c,0x04,0x18,0x04,0x78,
/* n */ 0x7c,0x08,0x04,0x04,0x78, /* o */ 0x38,0x44,0x44,0x44,0x38,
/* p */ 0x7c,0x14,0x14,0x14,0x08, /* q */ 0x08,0x14,0x14,0x18,0x7c,
/* r */ 0x7c,0x08,0x04,0x04,0x08, /* s */ 0x48,0x54,0x54,0x54,0x20,
/* t */ 0x04,0x3f,0x44,0x40,0x20, /* u */ 0x3c,0x40,0x40,0x20,0x7c,
/* v */ 0x1c,0x20,0x40,0x20,0x1c, /* w */ 0x3c,0x40,0x30,0x40,0x3c,
/* x */ 0x44,0x28,0x10,0x28,0x44, /* y */ 0x0c,0x50,0x50,0x50,0x3c,
/* z */ 0x44,0x64,0x54,0x4c,0x44, /* { */ 0x00,0x08,0x36,0x41,0x00,
/* | */ 0x00,0x00,0x7f,0x00,0x00, /* } */ 0x00,0x41,0x36,0x08,0x00,
/* ~ */ 0x08,0x08,0x2a,0x1c,0x08, /* */ 0x08,0x1c,0x2a,0x08,0x08
};
//
// data in sram
//
char c = 0; // character being output
uint8_t pauseAfter = 200; // then wait this long before next line
uint8_t buffB; // hold PORTB output 'til next interrupt
char* textPtr = text; // pointer into display text
uint8_t* glyfPtr; // pointer into character bitmap table
uint8_t glyfColumn; // how far we are through the current character
ISR (TIMER0_OVF_vect) {
PORTB = buffB; // ouput one column
if (c) { // not at end of string
if (glyfColumn++ < GLYFWIDTH) {
buffB = pgm_read_byte (glyfPtr++);
}
else { // we've output all 5 columns of character
buffB = 0; // prepare to put space between characters
c = pgm_read_byte (textPtr++); // get next character
if (c) c -= 31; // if it's not null, map to glyph array
glyfPtr = (uint8_t*)((povGlyf - 5) + ((int)c << 2) + (int)c);
glyfColumn = 0; // start counting at first column
}
}
else if (pauseAfter) { // wait a little before next line
pauseAfter--;
}
else {
c = 0xff; // force acquisition of 1st char of next line
glyfColumn = 5; // ditto
pauseAfter = 200;
if (textPtr >= (char*)(text + sizeof(text))) { // if there's no more text
textPtr = text; // return to beginning
}
}
}
int main (void) {
//
// set up i/o ports
//
PORTD = 0x00; // PD2 out
PORTB = 0x00; // all out
DDRD = (1 << PD2); // indicator led
DDRB = 0xff; // pov display
//
// setup timer 0, 1/256 prescale, mode 7, top = 39, 400.64Hz, enable interrupt
//
TCCR0A = (1 << WGM01) | (1 << WGM00); // select fast pwm w/ top = OCR0A
TCCR0B = (1 << WGM02) | (1 << CS02); // and prescale = 256
OCR0A = 39; // gives interrupt freq ca 400Hz
TIMSK = (1 << TOIE0); // enable overflow interrupt
sei (); // enable interrupts
MCUCR = (1 << SE); // enable idle sleep mode
while (1) {
sleep_cpu ();
}
}