/*
ATtiny85 with 8x8 LED matrix (max7219)
by Anderson Costa
with ❤ for the Wokwi community
*/
#include <avr/io.h>
#include <util/delay.h>
#define CLK_HIGH() PORTB |= (1 << PB2)
#define CLK_LOW() PORTB &= ~(1 << PB2)
#define CS_HIGH() PORTB |= (1 << PB1)
#define CS_LOW() PORTB &= ~(1 << PB1)
#define DATA_HIGH() PORTB |= (1 << PB0)
#define DATA_LOW() PORTB &= ~(1 << PB0)
#define INIT_PORT() DDRB |= (1 << PB0) | (1 << PB1) | (1 << PB2)
const uint8_t pacman1[8] = {
0b00011100,
0b00111110,
0b01110111,
0b01111111,
0b00001111,
0b01111111,
0b00111110,
0b00011100,
};
const uint8_t pacman2[8] = {
0b00011100,
0b00111110,
0b00010111,
0b00001111,
0b00001111,
0b00011111,
0b00111110,
0b00011100,
};
uint8_t display[8];
void spi_send(uint8_t data)
{
uint8_t i;
for (i = 0; i < 8; i++, data <<= 1) {
CLK_LOW();
if (data & 0x80) {
DATA_HIGH();
} else {
DATA_LOW();
}
CLK_HIGH();
}
}
void max7219_writec(uint8_t high_byte, uint8_t low_byte)
{
CS_LOW();
spi_send(high_byte);
spi_send(low_byte);
CS_HIGH();
}
void max7219_clear(void)
{
uint8_t i;
for (i = 0; i < 8; i++) {
max7219_writec(i + 1, 0);
}
}
void max7219_init(void)
{
INIT_PORT();
max7219_writec(0x09, 0); // Set decode mode to none
max7219_writec(0x0A, 1); // Set the intensity to (0-15)
max7219_writec(0x0B, 7); // Set scan limit for all digits
max7219_writec(0x0C, 1); // Shutdown register for display
max7219_writec(0x0F, 0); // Display test off
max7219_clear();
}
void set_pixels(uint8_t pixel[8])
{
uint8_t i;
for (i = 0; i < 8; i++) {
display[i] = pixel[i];
}
}
void update_display(void)
{
uint8_t i;
for (i = 0; i < 8; i++) {
max7219_writec(i + 1, display[i]);
}
}
int main(void)
{
uint8_t i;
max7219_init();
while (1) {
set_pixels(pacman1);
update_display();
_delay_ms(500);
set_pixels(pacman2);
update_display();
_delay_ms(500);
}
return (0);
}