Created
December 31, 2010 09:10
-
-
Save delamonpansie/760882 to your computer and use it in GitHub Desktop.
tree
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <util/delay.h> | |
#include <avr/io.h> | |
#include <avr/interrupt.h> | |
#include <stdlib.h> | |
#include <math.h> | |
#define CS_BANK0 0 | |
#define CS_BANK1 1 | |
#define WR 2 | |
#define DATA 3 | |
#define CS_BITS _BV(CS_BANK0)|_BV(CS_BANK1) | |
#define MAX_X 32 | |
#define MAX_Y 24 | |
char vram[48 * 2]; | |
char bank_cs[2] = {CS_BANK0, CS_BANK1}; | |
char bank = 1; | |
volatile char frame = 0; | |
#define SYSTEM_DISABLE 0b00000000 | |
#define SYSTEM_ENABLE 0b00000001 | |
#define LED_ON 0b00000011 | |
#define LED_OFF 0b00000010 | |
#define MASTER_MODE 0b00010100 | |
#define RC 0b00011000 | |
#define COMMONS 0b00100000 /* default is NMOS and 8PIN */ | |
#define COMMONS_PMOS 0b00101000 | |
#define COMMONS_16PIN 0b00100100 | |
#define PWM 0b10100000 | |
static void __attribute__((always_inline)) | |
cs(char v) | |
{ | |
if (v) | |
PORTA |= _BV(bank_cs[bank]); | |
else | |
PORTA &= ~_BV(bank_cs[bank]); | |
} | |
static void __attribute__((always_inline)) | |
wr_rise() | |
{ | |
PORTA &= ~_BV(WR); | |
_delay_us(1); | |
PORTA |= _BV(WR); | |
} | |
#define out_bits(n, bits) out_bits_((n), (bits) << (8 - (n))) | |
static void | |
out_bits_(char n, char bits) | |
{ | |
do { | |
if (bits & 0x80) | |
PORTA |= _BV(DATA); | |
else | |
PORTA &= ~_BV(DATA); | |
wr_rise(); | |
bits <<= 1; | |
} while (--n); | |
} | |
static void | |
out_bits_r(char n, char bits) | |
{ | |
do { | |
if (bits & 1) | |
PORTA |= _BV(DATA); | |
else | |
PORTA &= ~_BV(DATA); | |
wr_rise(); | |
bits >>= 1; | |
} while (--n); | |
} | |
static void | |
mode(char op) | |
{ | |
cs(0); | |
out_bits(3, 0b100); | |
out_bits(8, op); | |
out_bits(1, 0); | |
cs(1); | |
} | |
static void | |
write_bank0(char addr, char *value, char count) | |
{ | |
PORTA &= ~_BV(CS_BANK0); | |
out_bits(3, 0b101); | |
out_bits(7, addr); | |
do { | |
value--; | |
value--; | |
out_bits(8, *value--); | |
out_bits(8, *value--); | |
} while (count -= 4); | |
PORTA |= _BV(CS_BANK0); | |
} | |
static void | |
write_bank1(char addr, char *value, char count) | |
{ | |
PORTA &= ~_BV(CS_BANK1); | |
out_bits(3, 0b101); | |
out_bits(7, addr); | |
do { | |
value++; | |
value++; | |
out_bits_r(8, *value++); | |
out_bits_r(8, *value++); | |
} while (count -= 4); | |
PORTA |= _BV(CS_BANK1); | |
} | |
ISR(TIMER0_COMP_vect) | |
{ | |
write_bank0(0, vram + 31, 32); | |
write_bank0(32, vram + 63, 32); | |
write_bank0(64, vram + 95, 32); | |
write_bank1(64, vram, 32); | |
write_bank1(32, vram + 32, 32); | |
write_bank1(0, vram + 64, 32); | |
frame++; | |
} | |
static void | |
wait_frame() | |
{ | |
char old_frame = frame; | |
while (frame == old_frame); | |
} | |
static void | |
clear() | |
{ | |
for(char i = 0; i < 96; i++) | |
vram[i] = 0; | |
} | |
static void | |
pixel(char x, char y, char v) | |
{ | |
char bitval = 1 << (x & 7); | |
char addr = (y<<2) + (x>>3); | |
if (x >= MAX_X || y >= MAX_Y) | |
return; | |
if (v) | |
vram[addr] |= bitval; | |
else | |
vram[addr] &= ~bitval; | |
} | |
static void | |
xor_pixel(char x, char y) | |
{ | |
char bitval = 1 << (x & 7); | |
char addr = (y<<2) + (x>>3); | |
if (x >= MAX_X || y >= MAX_Y) | |
return; | |
vram[addr] ^= bitval; | |
} | |
void | |
line(char x0, char y0, char x1, char y1) | |
{ | |
signed char dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1; | |
signed char dy = abs(y1 - y0), sy = y0 < y1 ? 1 : -1; | |
signed char err = (dx > dy ? dx : -dy) / 2, e2; | |
for (;;) { | |
pixel(x0, y0, 1); | |
if (x0 == x1 && y0 == y1) | |
break; | |
e2 = err; | |
if (e2 >-dx) { | |
err -= dy; | |
x0 += sx; | |
} | |
if (e2 < dy) { | |
err += dx; | |
y0 += sy; | |
} | |
} | |
} | |
#define nelem(x) sizeof(x)/sizeof((x)[0]) | |
struct pixel { | |
char x, y, c; | |
}; | |
struct line { | |
char ax, ay, bx, by; | |
}; | |
void | |
draw(char dx, char dy, struct line *l, char count) | |
{ | |
for (char i = 0; i < count; i++) | |
line(dx + l[i].ax, dy + l[i].ay, dx + l[i].bx, dy + l[i].by); | |
} | |
/* | |
* | |
* x ^ | |
* | | |
* | | |
* -+----> | |
* | y | |
* | |
*/ | |
#define mx 16 | |
#define my 12 | |
#define top 20 | |
struct line tree[] = { | |
{5, my, top, my}, | |
{top, my, top - 2, my - 3}, | |
{top, my, top - 2, my + 3}, | |
{top - 4, my, top - 7, my - 5}, | |
{top - 4, my, top - 7, my + 5}, | |
{top - 9, my, top - 12, my - 7}, | |
{top - 9, my, top - 12, my + 7}, | |
}; | |
struct line year[] = { | |
{5, 0, 5, 3}, {5, 3, 3, 3}, {3, 3, 0, 0}, {0, 0, 0, 3}, | |
{5, 5, 5, 8}, {4, 8, 0, 8}, {0, 8, 0, 5}, {0, 5, 5, 5}, | |
{3, 10, 5, 12}, {5, 12, 0, 12}, | |
{3, 14, 5, 16}, {5, 16, 0, 16}, | |
}; | |
struct pixel flake[5]; | |
void | |
snow() | |
{ | |
for (char i = 0; i < nelem(flake); i++) { | |
flake[i].x = rand() % MAX_X; | |
flake[i].y = rand() % MAX_Y; | |
xor_pixel(flake[i].x, flake[i].y); | |
} | |
for (int z = 0; z < 500; z++) { | |
for (char i = 0; i < nelem(flake); i++) { | |
int rx = rand(); | |
int ry = rand(); | |
char x = flake[i].x; | |
char y = flake[i].y; | |
if (ry < RAND_MAX / 40) | |
y--; | |
else if (ry > RAND_MAX - RAND_MAX / 40) | |
y++; | |
if (rx < RAND_MAX / 10) | |
x--; | |
if (x != flake[i].x || y != flake[i].y) { | |
xor_pixel(x, y); | |
xor_pixel(flake[i].x, flake[i].y); | |
flake[i].x = x; | |
flake[i].y = y; | |
} | |
} | |
} | |
} | |
int main() | |
{ | |
TCCR0 |= _BV(CS02); //|_BV(CS00); | |
OCR0 = 0x9c; | |
TIMSK |= _BV(OCIE0); | |
sei(); | |
clear(); | |
DDRA |= CS_BITS|_BV(WR)|_BV(DATA); | |
PORTA |= CS_BITS; | |
bank = 0; | |
mode(SYSTEM_ENABLE); | |
mode(COMMONS_PMOS|COMMONS_16PIN); | |
mode(LED_ON); | |
mode(PWM|0xf); | |
bank = 1; | |
mode(SYSTEM_ENABLE); | |
mode(COMMONS_PMOS|COMMONS_16PIN); | |
mode(LED_ON); | |
mode(PWM|0xf); | |
again: | |
srand(13); | |
clear(); | |
for (char i = 30; i > -5; i--) { | |
clear(); | |
draw(0, i, tree, nelem(tree)); | |
_delay_ms(30); | |
wait_frame(); | |
} | |
draw(24, 4, year, nelem(year)); | |
_delay_ms(500); | |
snow(); | |
goto again; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment