BlinkenArea - GitList
Repositories
Blog
Wiki
bulb
Code
Commits
Branches
Tags
Search
Tree:
4626798
Branches
Tags
master
petaflot
1.0.0
1.1.0
1.1.1
bulb
cccamp2015
firmware
bulb_dim.c
CCCamp2015: alternative firmware by Martin Müllenhaupt
Stefan Schuermans
commited
4626798
at 2015-08-16 08:52:13
bulb_dim.c
Blame
History
Raw
/* bulb - BlinkenArea ultimate logo board version 1.0 date 2015-08-15 Copyright (C) 2015 Martin Müllenhaupt <mm+bulb@netlair.de> Copyleft: GNU public license - http://www.gnu.org/copyleft/gpl.html */ #include <avr/io.h> #include <avr/interrupt.h> #define F_CPU 8000000UL // 8 MHz #include <util/delay.h> #include <stdlib.h> #define NUM_ZEILEN 6 #define NUM_SPALTEN 7 #define NUM_LEDS (NUM_ZEILEN * NUM_SPALTEN) #define MAX_TIME 32 #define LED(index) frame[updateBufferIndex][index/NUM_SPALTEN][index%NUM_SPALTEN] #define LED_INDEX_FROM_MANUAL(index) frame[updateBufferIndex][(index-1)/NUM_SPALTEN][(index-1)%NUM_SPALTEN] /* 0 = off; 255 = max brightness */ uint8_t frame[2][NUM_ZEILEN][NUM_SPALTEN] = {0}; uint8_t displayBufferIndex = 0; uint8_t updateBufferIndex = 1; ISR(TIMER1_COMPA_vect) { static uint8_t zeile = 0; static uint8_t time = 0; ++time; if (time == MAX_TIME) { ++zeile; zeile %= NUM_ZEILEN; PORTB = 0; PORTD = ~(1 << zeile); time = 0; } uint8_t row_data = 0; for(uint8_t spalte = 0; spalte < NUM_SPALTEN; ++spalte) { if (frame[displayBufferIndex][zeile][spalte] > time) { row_data |= (1 << spalte); } } PORTB = row_data; } void swapBuffers() { updateBufferIndex = ( updateBufferIndex + 1 ) % 2; displayBufferIndex = ( displayBufferIndex + 1 ) % 2; } void wurm(uint8_t length, uint8_t reverse) { for (int8_t frontPosition = reverse ? NUM_LEDS : 0; reverse ? frontPosition >= - length - 1 : frontPosition < NUM_LEDS + length; reverse ? --frontPosition : ++frontPosition) { for(uint8_t pos = 0; pos < NUM_LEDS; ++pos) { int8_t dist = abs(pos - frontPosition); uint8_t value = 0; if ( ((reverse && pos >= frontPosition) || (!reverse && pos <= frontPosition)) && dist < length) { value = MAX_TIME / (1 + 4 * dist); } LED(pos) = value; } swapBuffers(); _delay_us(20000); } } #define FIRST_SCANLINE 0 #define LAST_SCANLINE 7 void single_scanline_hori(uint8_t scanposition, uint8_t value) { switch(scanposition) { case 0: for (uint8_t i = 3; i <= 10; ++i) { LED_INDEX_FROM_MANUAL(i) = value; } break; case 1: LED_INDEX_FROM_MANUAL(2) = value; LED_INDEX_FROM_MANUAL(11) = value; LED_INDEX_FROM_MANUAL(32) = value; break; case 2: LED_INDEX_FROM_MANUAL(1) = value; LED_INDEX_FROM_MANUAL(31) = value; LED_INDEX_FROM_MANUAL(33) = value; LED_INDEX_FROM_MANUAL(12) = value; break; case 3: LED_INDEX_FROM_MANUAL(28) = value; LED_INDEX_FROM_MANUAL(29) = value; LED_INDEX_FROM_MANUAL(30) = value; LED_INDEX_FROM_MANUAL(34) = value; LED_INDEX_FROM_MANUAL(13) = value; LED_INDEX_FROM_MANUAL(42) = value; break; case 4: LED_INDEX_FROM_MANUAL(27) = value; LED_INDEX_FROM_MANUAL(41) = value; LED_INDEX_FROM_MANUAL(40) = value; LED_INDEX_FROM_MANUAL(35) = value; LED_INDEX_FROM_MANUAL(14) = value; break; case 5: LED_INDEX_FROM_MANUAL(26) = value; LED_INDEX_FROM_MANUAL(39) = value; LED_INDEX_FROM_MANUAL(36) = value; LED_INDEX_FROM_MANUAL(37) = value; LED_INDEX_FROM_MANUAL(15) = value; break; case 6: LED_INDEX_FROM_MANUAL(25) = value; LED_INDEX_FROM_MANUAL(38) = value; LED_INDEX_FROM_MANUAL(16) = value; break; case 7: for (uint8_t i = 17; i <= 24; ++i) { LED_INDEX_FROM_MANUAL(i) = value; } break; } } void single_scanline_vert(uint8_t scanposition, uint8_t value) { switch(scanposition) { case 0: for (uint8_t i = 10; i <= 17; ++i) { LED_INDEX_FROM_MANUAL(i) = value; } break; case 1: LED_INDEX_FROM_MANUAL(9) = value; LED_INDEX_FROM_MANUAL(34) = value; LED_INDEX_FROM_MANUAL(35) = value; LED_INDEX_FROM_MANUAL(36) = value; LED_INDEX_FROM_MANUAL(18) = value; break; case 2: LED_INDEX_FROM_MANUAL(8) = value; LED_INDEX_FROM_MANUAL(33) = value; LED_INDEX_FROM_MANUAL(42) = value; LED_INDEX_FROM_MANUAL(37) = value; LED_INDEX_FROM_MANUAL(19) = value; break; case 3: LED_INDEX_FROM_MANUAL(7) = value; LED_INDEX_FROM_MANUAL(32) = value; LED_INDEX_FROM_MANUAL(38) = value; LED_INDEX_FROM_MANUAL(20) = value; break; case 4: LED_INDEX_FROM_MANUAL(6) = value; LED_INDEX_FROM_MANUAL(31) = value; LED_INDEX_FROM_MANUAL(39) = value; LED_INDEX_FROM_MANUAL(21) = value; break; case 5: LED_INDEX_FROM_MANUAL(5) = value; LED_INDEX_FROM_MANUAL(30) = value; LED_INDEX_FROM_MANUAL(40) = value; LED_INDEX_FROM_MANUAL(22) = value; break; case 6: LED_INDEX_FROM_MANUAL(4) = value; LED_INDEX_FROM_MANUAL(29) = value; LED_INDEX_FROM_MANUAL(41) = value; LED_INDEX_FROM_MANUAL(23) = value; break; case 7: LED_INDEX_FROM_MANUAL(1) = value; LED_INDEX_FROM_MANUAL(2) = value; LED_INDEX_FROM_MANUAL(3) = value; for (uint8_t i = 24; i <= 28; ++i) { LED_INDEX_FROM_MANUAL(i) = value; } break; } } void scanline(uint8_t length, uint8_t horizontal, uint8_t reverse) { int8_t firstCenter = FIRST_SCANLINE - length + 1; int8_t lastCenter = LAST_SCANLINE + length - 1; for (int8_t centerPosition = reverse ? lastCenter : firstCenter; reverse ? centerPosition >= firstCenter : centerPosition <= lastCenter; reverse ? -- centerPosition : ++centerPosition) { for(int8_t linePos = FIRST_SCANLINE; linePos <= LAST_SCANLINE; ++linePos) { int8_t dist = abs(centerPosition - linePos); if (horizontal) { if (dist < length) { single_scanline_hori(linePos, MAX_TIME / (4*dist + 1)); } else { single_scanline_hori(linePos, 0); } } else { if (dist < length) { single_scanline_vert(linePos, MAX_TIME / (4*dist + 1)); } else { single_scanline_vert(linePos, 0); } } } swapBuffers(); _delay_us(30000); } } void blink() { for(int8_t pos = 0; pos < NUM_LEDS; ++pos) { LED(pos) = 0; } swapBuffers(); _delay_us(100000); for(int8_t pos = 0; pos < NUM_LEDS; ++pos) { LED(pos) = MAX_TIME; } swapBuffers(); _delay_us(100000); } #define ROT_SIZE 5 void dimRotation() { for(uint8_t position = 0; position < ROT_SIZE-1; ++position) { for(uint8_t led = 0; led < NUM_LEDS; ++led) { uint8_t this_led = ((led + position) % NUM_LEDS); LED(this_led) = (led%(ROT_SIZE-1)) * (MAX_TIME/(ROT_SIZE-1)); } swapBuffers(); _delay_us(100000); } } int main(void) { // PA[01] to output, low PORTA = 0; DDRA = 0x03; // PB[0-6] to output, low - PB7 to input, pull-up enabled DDRB = 0x7F; PORTB = 0x80; // PD[0-5] to output, high - PD6 to input, pull-up enabled DDRD = 0x3F; PORTD = 0x7F; // set clock to 8 MHz CLKPR = (1<<CLKPCE); CLKPR = 0; TCCR1B |= (1 << WGM12); // Configure timer 1 for CTC mode TIMSK |= (1 << OCIE1A); // Enable CTC interrupt sei(); // Enable global interrupts OCR1A = 8; // Set CTC compare value to 1Hz at 1MHz AVR clock, with a prescaler of 64 TCCR1B |= ((1 << CS10) | (1 << CS11)); // Start timer at Fcpu/64 for(;;) { for (uint8_t length = 1; length <= 8; length += 2) { wurm(length, 0); wurm(length, 1); } for (int8_t horizontal = 1; horizontal >= 0; --horizontal) { for (uint8_t length = 1; length <= 6; ++length) { for (uint8_t reverse = 0; reverse <= 1; ++reverse) { scanline(length, horizontal, reverse); } } } blink(); blink(); blink(); for (uint8_t i = 1; i <= 8; ++i) { dimRotation(); } } }