by mtbf0 » Fri Apr 20, 2012 10:12 pm
here is some minipov3 code that does some of what you want. takes an ascii string as input and outputs as a pov display. very slowly. this was supposed to be used with uv leds to write on walls painted with phosphorescent paint, so you'd want to speed up the timer interrupt.
the interesting stuff's in the interrupt service routine.
if the code is of no interest you can at least snag the bitmaps for the digits.
- Code: Select all
/*
MENEpov.c - Version 1.0
Copyright 2009 Bobby Cossum. All Rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or banned FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
This firmware is written to run on a minipov3 board from www.adafruit.com.
The red leds supplied with the kit should be replaced with ultra-violet ones
and a prompting led should be installed between the signal and ground pins
of the sensor inputs. Care must be taken to provide adequate voltage for
to drive the uv leds which typically have a voltage drop higher than the
red leds supplied with the board. The values of the current limiting
resistors will have to be selected based on your supply voltage and the
specifications of the leds you use.
My prototype uses leds with a 3.2 volt drop, a 5v supply, and 100 ohm series
resistors. Something like 90 ohms would have been a better choice if i had
had any.
Finally, please do not look directly at ultra-violet leds.
*/
#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 pauseBefore = 95; // pause at the end of each line this long
uint8_t blink = 1; // then turn on indicator for this long
uint8_t pauseAfter = 48; // then wait this long before next line
volatile uint8_t run = 1; // main program loop runs while (run);
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 (pauseBefore) { // pause 2 sec before blinking led
pauseBefore--;
}
else if (blink) { // turn on green led
blink--;
PORTD |= (1 << PD2);
}
else if (pauseAfter) { // pause 1 sec after blinking led
PORTD &= ~(1 << PD2);
pauseAfter--;
}
else if (textPtr < (char*)(text + sizeof(text))) { // if there's more text
c = 0xff; // force acquisition of 1st char of next line
glyfColumn = 5; // ditto
pauseBefore = 95; // 2 seconds based on 48Hz interrupt frequency
blink = 1; // 1/48 second
pauseAfter = 48; // 1 second
}
else { // end of text, signal main program to terminate
run = 0;
}
}
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/1024 prescale, mode 7, 48Hz, enable interrupt
//
TCCR0A = (1 << WGM01) | (1 << WGM00); // select fast pwm w/ top = OCR0A
TCCR0B = (1 << WGM02) | (1 << CS02) | (1 << CS00); // and prescale = 1024
OCR0A = 163; // gives interrupt freq ca 48Hz
TIMSK = (1 << TOIE0); // enable overflow interrupt
sei (); // enable interrupts
MCUCR = (1 << SE); // enable idle sleep mode
while (run) {
sleep_cpu ();
}
TCCR0B = 0x00; // stop timer
DDRB = 0;
DDRD = 0;
PORTB = 0;
PORTD = 0;
MCUCR = (1 << SE) | (1 << SM0);// enable shutdown sleep mode
sleep_cpu (); // zzzzzzzzzzzz
}
"i want to lead a dissipate existence, play scratchy records and enjoy my decline" - iggy pop, i need more