/****************************************************************************** * BLINKOFANT template controller for the Arduino * https://metalab.at/wiki/Blinkofant * https://metalab.at/wiki/Datei:Ledmatrix_chained.png ******************************************************************************* * ATmega328p datasheet: * Table 18-5. Relationship Between SCK and the Oscillator Frequency * SPI2X SPR1 SPR0 SCK Frequency * 0 0 0 fosc/4 * 0 0 1 fosc/16 * 0 1 0 fosc/64 * 0 1 1 fosc/128 <-- We need to be really sluggish * 1 0 0 fosc/2 * 1 0 1 fosc/8 * 1 1 0 fosc/32 * 1 1 1 fosc/64 ******************************************************************************* * Data and clock lines must be PB3 and PB5 respectively, if we want to use * hardware SPI. ******************************************************************************/ #include #include #define PANEL_DDR DDRB #define PANEL_PORT PORTB #define PANEL_CLEAR 2 // Arduino-pin 10 #define PANEL_MOSI PB3 // Arduino-pin 11 #define PANEL_SCK PB5 // Arduino-pin 13 #define PANELS 1 #define PANEL_DATA_SIZE (10*PANELS) uint8_t panel_data[PANEL_DATA_SIZE]; void init() { PANEL_DDR |= (1 << PANEL_MOSI) | (1 << PANEL_SCK) | (1 << PANEL_CLEAR); PANEL_PORT &=~ ((1 << PANEL_MOSI) | (1 << PANEL_SCK) | (1 << PANEL_CLEAR)); SPCR = (1 << SPE) | // Enable SPI (1 << MSTR) | // We are the master (1 << DORD) | // LSB first (1 << SPR1) | // Clock divider... (1 << SPR0) ; // ...F_CPU / 128 // Not necessary, is disabled by default: // SPSR &=~ (1 << SPI2X); // Disable double speed mode } inline void screen_off() { PANEL_PORT &=~ (1 << PANEL_CLEAR); } inline void screen_on() { PANEL_PORT |= (1 << PANEL_CLEAR); } void set_pixel( uint8_t x, uint8_t y, uint8_t value ) { uint8_t index = (x*10) + (y+1); // y+1 because first bit controls blinking uint8_t byte_nr = index >> 3; // Division by 8 uint8_t bit_nr = index & 0b00000111; // Remainder of division if (value) { panel_data[byte_nr] |= (1 << bit_nr); } else { panel_data[byte_nr] &=~ (1 << bit_nr); } } void shift_pixel_data() { uint8_t i; screen_off(); for ( i = 0 ; i < PANEL_DATA_SIZE ; i++ ) { SPDR = panel_data[i]; while (!(SPSR & (1 << SPIF))) /* wait */; } screen_on(); } int main(void) { uint8_t x, y; uint8_t state = 0; init(); while(1) { state++; for( x = 0 ; x < 8*PANELS ; x++ ) { for( y = 0 ; y < 9 ; y++ ) { //set_pixel(x, y, ((x>>1) + (y>>1) + state) & 1); float dx = x-4; float dy = y-4; float d = sqrt(dx*dx+dy*dy); int ds = 3*d+state; set_pixel( x, y, ((ds % 20) <= 10) ); } } shift_pixel_data(); _delay_ms(5); } }