Skip to content

Instantly share code, notes, and snippets.

@crabdancing
Last active May 20, 2019 03:46
Show Gist options
  • Save crabdancing/d4c400814fc46c22dd2f406639370625 to your computer and use it in GitHub Desktop.
Save crabdancing/d4c400814fc46c22dd2f406639370625 to your computer and use it in GitHub Desktop.
/* Copyleft (C) Alexandria Pettit 2019, GNU GPLv3
* Very basic example code for using the LedControl library to
* display crude multi-panel scanning animation on a MAX7219 monochrome dot matrix.
*
* Requires: https://github.com/wayoda/LedControl/
*/
#include "LedControl.h"
// Delay between frame updates
static const int FRAME_DELAY = 200;
// Number of frames in animation
static const int FRAME_COUNT = 2;
// Number of displays
// in my case, it's a 4x display module
static const int DISPLAY_NUM = 4;
// These are almost always 8x8 displays
static const int DISPLAY_WIDTH = 8;
static const int DISPLAY_HEIGHT = 8;
// The super-display made of each sub-display
// connected together with the magic of SPI
static const int TOTAL_DISPLAY_WIDTH = DISPLAY_WIDTH * DISPLAY_NUM;
static const int TOTAL_DISPLAY_HEIGHT = DISPLAY_HEIGHT;
// This doesn't seem to actually do anything
static const int DISPLAY_INTENSITY = 5;
LedControl ledcontrol = LedControl(
11, // DIN pin
12, // CLK pin
10, // CS pin
DISPLAY_NUM // Number of displays
);
// bool for storing whether or not to set an LED on or off
bool state = true;
// struct for storing division results for calculating coordinates
div_t div_result;
void setup()
{
// Initialize each display
for(int d = 0; d < DISPLAY_NUM; d++) {
ledcontrol.shutdown(d, false);
ledcontrol.setIntensity(d, DISPLAY_INTENSITY);
ledcontrol.clearDisplay(d);
}
}
void loop()
{
// iterate over rows in display
for(int y = 0; y < TOTAL_DISPLAY_HEIGHT; y++) {
// iterate over columns in display
for(int x = 0; x < TOTAL_DISPLAY_WIDTH; x++) {
/* This is not well documented in Arduino-land, but:
* 1) AVR implements division as repeated subtraction, which is very inefficient.
* 2) The '%' operator uses division in the backend, then throws away the division result.
* 3) Therefore to minimize wasted cycles we have div(), that spits out the div_t struct
* containing both remainder & quotient.
*
* In the below code, for instance,
* div_result.quot is equivlant to the output of x / DISPLAY_WIDTH,
* and div_result.rem is equivlant to x % DISPLAY_WIDTH
*
* The function of these variables is to compute the target relative coordinates to send,
* and which screen to send it to.
*
* For example, if we're iterating from left to right, we can just increment the X value,
* but when we get to 7, we have to go back to zero of the next display and increment from there.
*
* So, this generates a pattern with it counting up from 0 to 7,
* then rolling over to the next screen, and counting up to 7 again.
*
* The result is a general method for converting, e.g., a 32x8 coordinate space
* into 4 adjacent 8x8 sub-spaces. This code can be altered very easily to support
* an arbitrarily long chain of displays, or to iterate in reverse, etc.
*/
div_result = div(x, DISPLAY_WIDTH);
ledcontrol.setLed(div_result.quot, y, div_result.rem, state);
delay(8);
}
}
// Invert state so that next time we do the opposite of what we did this time.
state = !state;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment