UPDATE: MAX7219LED8x8 uses simple scheduler

UPDATE 2022: The MAX7219LED8x8 library, now renamed to MAX7219tiny has now a new home at tinusaur.com/libraries/max7219tiny. Check also this MAX7219 & ATtiny85 tutorial to learn how the library works.

max7219 LED 8x8 Tinusaur ATtiny85

The MAX7219LED8x8 library uses now a simple scheduler to automate the task of outputting the buffer to the LED 8×8 matrix. This is not like a real task scheduler (in a real operating system) but it uses the ATtiny85 microcontroller‘s timer and its interrupt to do certain things at regular intervals.

So this is how I’ve got the idea …

While I was working on some code that uses the MAX7219LED8x8 library I figured out that the task of writing the content of the memory buffer to the MAX7219 could be automated by hooking some code to the ATtiny85 timer.

The modification and additions could be broken down into 2 parts:

First, the scheduling part initializes the ATtiny85 timer, starts it, and handles the hardware interrupt.

Second, the MAX7219LED8x8 library functions for setting/clearing pixels and outputting the buffer that now should work with the scheduler.

There are only 3 functions to handle the scheduling:

void scheduler_init(void);
void scheduler_start(uint8_t max);
void scheduler_userfunc(void);

The scheduler_init function initializes the timer and the scheduler_start starts the timer task to be executed on equal intervals defined by the max parameter.

The scheduler_userfunc function should be implemented in the application so it could be called at regular intervals.

There is no “stop” function at the moment since it was not needed in this particular case.

The code for initializing and starting the ATtiny85 timer is very simple:

void scheduler_init(void) {
    // Setup Timer
    TCCR0A |= (1 << WGM01); // set timer in CTC mode
    TIMSK |= (1 << OCIE0A); // set Bit 4 – OCIE0A:
    // ... Timer/Counter0 Output Compare Match A Interrupt Enable
}

void scheduler_start(uint8_t max) {
    // IMPORTANT: Requires TIMER0_COMPA_vect to be setup.
    sei(); //  Enable global interrupts
    OCR0A = max;    // set value for OCR0A - Output Compare Register A
    // Prescale and start timer: 1/1024-th
    TCCR0B |= (1 << CS02) | (0 << CS01) | (1 << CS00);
}

// Define interrupt vector
ISR(TIMER0_COMPA_vect)
{
    scheduler_userfunc();
    // Note: No need to clear flags in TIFR - done automatically
}

On the MAX7219LED8x8 side there are only 3 functions currently implemented:

void max7219s_init(void);
void max7219s_start(void);
void max7219s_buffer_out(void);

The max7219s_buffer_out function is the one called within the scheduler_userfunc timer handler.

Everything else remains the same – we use MAX7219_buffer_set(x, y) to set pixel and MAX7219_buffer_clr(x, y) to clear pixel.

What could be improved and optimized: output the buffer only when it is changed.

More information is available on the MAX7219LED8x8 library page.

The source code of the MAX7219LED8x8 library, the scheduler, and everything else are available at https://bitbucket.org/tinusaur/max7219led8x8.

Leave a Comment