Skip to content

Instantly share code, notes, and snippets.

@delamonpansie
Created December 31, 2010 09:10
Show Gist options
  • Save delamonpansie/760882 to your computer and use it in GitHub Desktop.
Save delamonpansie/760882 to your computer and use it in GitHub Desktop.
tree
#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