잔상효과/persistence of vision2
POV라는 잔상효과 소스를 실행해 봤다. 정말 신기하다. 다른 image도 해 보고 싶다.
이번에는 헤드셋 모양의 이미지를 로딩해 보자.
#include <MsTimer2.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#define PARSE(pattern) ((pattern>>14) & 0b111111), ((pattern>>8) & 0b111111), (pattern & 0b11111111)
const uint8_t pov_pattern[] PROGMEM = {
PARSE( 0b00000000000000000000 ),
PARSE( 0b00001111100000000000 ),
PARSE( 0b00111111110000000000 ),
PARSE( 0b00011111111100000000 ),
PARSE( 0b00011111110001100000 ),
PARSE( 0b00000000000000010000 ),
PARSE( 0b00000000000000001000 ),
PARSE( 0b00000000000000000100 ),
PARSE( 0b00000000000000000010 ),
PARSE( 0b00000000000000000000 ),
PARSE( 0b00000000000000000010 ),
PARSE( 0b00000000000000000001 ),
PARSE( 0b00000000000000000010 ),
PARSE( 0b00000000000000000000 ),
PARSE( 0b00000000000000000010 ),
PARSE( 0b00000000000000000010 ),
PARSE( 0b00000000000000000100 ),
PARSE( 0b00000000000000001000 ),
PARSE( 0b00000000000000010000 ),
PARSE( 0b00011011011000100000 ),
PARSE( 0b00111111111011000000 ),
PARSE( 0b00011111110000000000 ),
PARSE( 0b00011111100000000000 ),
PARSE( 0b00000101000000000000 ),
};
void blink() {
static uint16_t index = 0;
PORTC = pgm_read_byte(pov_pattern+(index++));
PORTB = pgm_read_byte(pov_pattern+(index++));
PORTD = pgm_read_byte(pov_pattern+(index++));
if (index >= sizeof(pov_pattern)) { index = 0; }
}
void setup() {
DDRD = 0b11111111; // set digital 0- 7 to output
DDRB = 0b00111111; // set digital 8-13 to output
DDRC = 0b00111111; // set digital 14-19 to output (coincidences with analog 0-5)
MsTimer2::set(2, blink);
MsTimer2::start();
}
void loop() { }
자 이 코드를 로딩해 보자.
화면 클릭~!
오~! 정말로 헤드셋 모양이다. 신기하다. 근데, 매번 이거 어떻게 이렇게 만들지?
친절하게 이미지를 C array pattern으로 만들어 주는 소스가 있다.
import sys
from PIL import Image
# double check that there is at least one argument (the file name)
if len(sys.argv) != 2:
print "Please specify a source filename"
sys.exit(-1)
# determine source file name
sourcefilename = sys.argv[1]
# strip extension
name = sourcefilename.split(".")[0]
# let PIL determine the proper graphics file type
image = Image.open(sourcefilename)
# convert image to black and white
image = image.convert("1")
# get hold of image size
(xsize, ysize) = image.size
# ensure height is 20 pixels (=number of LEDs)
if ysize != 20:
print "Image height must be 20 pixels but is {0} pixels".format(ysize)
# output common start of program
print """#include <MsTimer2.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#define PARSE(pattern) ((pattern>>14) & 0b111111), ((pattern>>8) & 0b111111), (pattern & 0b11111111)
uint8_t const pov_pattern[] PROGMEM = {"""
# generate the bit pattern for the LEDs
for x in range(0, xsize):
line = " PARSE( 0b"
for y in range(0, ysize):
line = line + ('0' if image.getpixel((x, ysize-1-y)) != 0 else '1')
line = line + " ),"
print line
# output common end of program
print """};
void blink() {
static uint16_t index = 0;
PORTC = pgm_read_byte(pov_pattern+(index++));
PORTB = pgm_read_byte(pov_pattern+(index++));
PORTD = pgm_read_byte(pov_pattern+(index++));
if (index >= sizeof(pov_pattern)) { index = 0; }
}
void setup() {
DDRD = 0b11111111; // set digital 0- 7 to output
DDRB = 0b00111111; // set digital 8-13 to output
DDRC = 0b00111111; // set digital 14-19 to output (coincidences with analog 0-5)
MsTimer2::set(2, blink);
MsTimer2::start();
}
void loop() { }
"""
위의 C 소스를 만들어주는 python source이다. Python 3.x에서는 바로 되지 않는다. print()해줘야 한다. () —> 요거 괄호 중요하다. 2.x에서는 바로된다. 그리고 입력하는 이미지는 반드시 높이가 20 pixel이하여야 한다. 그것만 명심해라.