Last active
May 20, 2019 03:46
-
-
Save crabdancing/d4c400814fc46c22dd2f406639370625 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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