/*
* MaxMatrix
* Version 1.0 Feb 2013
* Copyright 2013 Oscar Kin-Chung Au
*/
/*
* MaxMatrix
* Version 1.0 Feb 2013
* Copyright 2013 Oscar Kin-Chung Au
*/
#ifndef _MaxMatrix_H_
#define _MaxMatrix_H_
#include "Arduino.h"
#define max7219_reg_noop 0x00
#define max7219_reg_digit0 0x01
#define max7219_reg_digit1 0x02
#define max7219_reg_digit2 0x03
#define max7219_reg_digit3 0x04
#define max7219_reg_digit4 0x05
#define max7219_reg_digit5 0x06
#define max7219_reg_digit6 0x07
#define max7219_reg_digit7 0x08
#define max7219_reg_decodeMode 0x09
#define max7219_reg_intensity 0x0a
#define max7219_reg_scanLimit 0x0b
#define max7219_reg_shutdown 0x0c
#define max7219_reg_displayTest 0x0f
class MaxMatrix
{
private:
byte data;
byte load;
byte clock;
byte num;
byte buffer[112];
void reload();
public:
MaxMatrix(byte data, byte load, byte clock, byte num);
void init();
void clear();
void setCommand(byte command, byte value);
void setIntensity(byte intensity);
void setColumn(byte col, byte value);
void setColumnAll(byte col, byte value);
void setDot(byte col, byte row, byte value);
void writeSprite(int x, int y, const byte* sprite);
void shiftLeft(bool rotate = false, bool fill_zero = true);
void shiftRight(bool rotate = false, bool fill_zero = true);
void shiftUp(bool rotate = false);
void shiftDown(bool rotate = false);
};
#endif
#include "Arduino.h"
MaxMatrix::MaxMatrix(byte _data, byte _load, byte _clock, byte _num)
{
data = _data;
load = _load;
clock = _clock;
num = _num;
for (int i=0; i<112; i++)
buffer[i] = 0;
}
void MaxMatrix::init()
{
pinMode(data, OUTPUT);
pinMode(clock, OUTPUT);
pinMode(load, OUTPUT);
digitalWrite(clock, HIGH);
setCommand(max7219_reg_scanLimit, 0x07);
setCommand(max7219_reg_decodeMode, 0x00); // using an led matrix (not digits)
setCommand(max7219_reg_shutdown, 0x01); // not in shutdown mode
setCommand(max7219_reg_displayTest, 0x00); // no display test
// empty registers, turn all LEDs off
clear();
setIntensity(0x0f); // the first 0x0f is the value you can set
}
void MaxMatrix::setIntensity(byte intensity)
{
setCommand(max7219_reg_intensity, intensity);
}
void MaxMatrix::clear()
{
for (int i=0; i<8; i++)
setColumnAll(i,0);
for (int i=0; i<112; i++)
buffer[i] = 0;
}
void MaxMatrix::setCommand(byte command, byte value)
{
digitalWrite(load, LOW);
for (int i=0; i<num; i++)
{
shiftOut(data, clock, MSBFIRST, command);
shiftOut(data, clock, MSBFIRST, value);
}
digitalWrite(load, LOW);
digitalWrite(load, HIGH);
}
void MaxMatrix::setColumn(byte col, byte value)
{
int n = col / 8;
int c = col % 8;
digitalWrite(load, LOW);
for (int i=0; i<num; i++)
{
if (i == n)
{
shiftOut(data, clock, MSBFIRST, c + 1);
shiftOut(data, clock, MSBFIRST, value);
}
else
{
shiftOut(data, clock, MSBFIRST, 0);
shiftOut(data, clock, MSBFIRST, 0);
}
}
digitalWrite(load, LOW);
digitalWrite(load, HIGH);
buffer[col] = value;
}
void MaxMatrix::setColumnAll(byte col, byte value)
{
digitalWrite(load, LOW);
for (int i=0; i<num; i++)
{
shiftOut(data, clock, MSBFIRST, col + 1);
shiftOut(data, clock, MSBFIRST, value);
buffer[col * i] = value;
}
digitalWrite(load, LOW);
digitalWrite(load, HIGH);
}
void MaxMatrix::setDot(byte col, byte row, byte value)
{
bitWrite(buffer[col], row, value);
int n = col / 8;
int c = col % 8;
digitalWrite(load, LOW);
for (int i=0; i<num; i++)
{
if (i == n)
{
shiftOut(data, clock, MSBFIRST, c + 1);
shiftOut(data, clock, MSBFIRST, buffer[col]);
}
else
{
shiftOut(data, clock, MSBFIRST, 0);
shiftOut(data, clock, MSBFIRST, 0);
}
}
digitalWrite(load, LOW);
digitalWrite(load, HIGH);
}
void MaxMatrix::writeSprite(int x, int y, const byte* sprite)
{
int w = sprite[0];
int h = sprite[1];
if (h == 8 && y == 0)
for (int i=0; i<w; i++)
{
int c = x + i;
if (c>=0 && c<112)
setColumn(c, sprite[i+2]);
}
else
for (int i=0; i<w; i++)
for (int j=0; j<h; j++)
{
int c = x + i;
int r = y + j;
if (c>=0 && c<112 && r>=0 && r<8)
setDot(c, r, bitRead(sprite[i+2], j));
}
}
void MaxMatrix::reload()
{
for (int i=0; i<8; i++)
{
int col = i;
digitalWrite(load, LOW);
for (int j=0; j<num; j++)
{
shiftOut(data, clock, MSBFIRST, i + 1);
shiftOut(data, clock, MSBFIRST, buffer[col]);
col += 8;
}
digitalWrite(load, LOW);
digitalWrite(load, HIGH);
}
}
void MaxMatrix::shiftLeft(bool rotate, bool fill_zero)
{
byte old = buffer[0];
int i;
for (i=0; i<112; i++)
buffer[i] = buffer[i+1];
if (rotate) buffer[num*8-1] = old;
else if (fill_zero) buffer[num*8-1] = 0;
reload();
}
void MaxMatrix::shiftRight(bool rotate, bool fill_zero)
{
int last = num*8-1;
byte old = buffer[last];
int i;
for (i=111; i>0; i--)
buffer[i] = buffer[i-1];
if (rotate) buffer[0] = old;
else if (fill_zero) buffer[0] = 0;
reload();
}
void MaxMatrix::shiftUp(bool rotate)
{
for (int i=0; i<num*8; i++)
{
bool b = buffer[i] & 1;
buffer[i] >>= 1;
if (rotate) bitWrite(buffer[i], 7, b);
}
reload();
}
void MaxMatrix::shiftDown(bool rotate)
{
for (int i=0; i<num*8; i++)
{
bool b = buffer[i] & 128;
buffer[i] <<= 1;
if (rotate) bitWrite(buffer[i], 0, b);
}
reload();
}
/*
Version 3.1 Last update: 11-02-2020
This code will control the Left and right of the protogen helmet matrices.
The library for controlling the matrices has to be added to the Arduino IDE before the code can work. The library
that comes with this code has been modified so that you can link up to 14 matrices instead of 10.
If you ever need help or something doesn't work, send me an e-mail to [email protected]
or contact me on twitter @Feronium
Below are the pieces of code listed to show the icons. A '0' means the LED is turned off,
a '1' means the LED will be turned on.
I'd recommend using the website linked below to make custom icons if you want
and then copy the code below here, replacing the icons that are already listed.
https://xantorohara.github.io/led-matrix-editor
you can also easily turn the icons 90 or 180 degrees on this website if the matrix does not show the right orientation.
Also please contact me if you something isn't working properly so it can be fixed in the next update.
Have fun!
*/
/* If you would like to use a hall effect sensor (magnet sensor) to turn off the LED-matrices when the
visor is taken off, you can uncomment the line below by deleting the 2 slashes. */
//#define visorSensor
//Right side of the helmet
char noseRight[] = {8, 8, B00000000, B00000000, B10000000, B11000000, B11000000, B11111100, B01111110, B00000000};
char icon01[] = {8, 8, B00100000,B01111000,B11011110,B11000111,B11111111,B00000000,B00000000,B00000000};
char icon02[] = {8, 8, B00000000,B00000000,B00000000,B10000000,B11100000,B01111000,B00011110,B00000111};
char icon03[] = {8, 8, B00000000,B00000000,B00000000,B00000000,B00000111,B00011110,B01111000,B11100000};
char icon04[] = {8, 8, B00000000,B00000000,B00000000,B11100000,B11111000,B00011110,B00000111,B00000001};
char Glitch01[] = {8, 8, B00001100, B00000000, B11010100, B10001001, B00010100, B01000111, B11010001, B10100101};
char Glitch011[] = {8, 8, B00000000, B00000000, B00000000, B11010101, B10000101, B11101010, B00010111, B00000100};
char Glitch02[] = {8, 8, B01110100, B00000000, B01001011, B10010110, B00010010, B00000000, B00000000, B00000000};
char Glitch022[] = {8, 8, B10100010, B01010100, B10000110, B00010010, B00000101, B00000000, B00000000, B00000000};
char Glitch03[] = {8, 8, B00101001, B10101001, B01001011, B00101100, B01110100, B00000000, B00000000, B00000000};
char Glitch033[] = {8, 8, B01001101, B10011010, B01101001, B10100000, B00001000, B00000000, B00000000, B00000000};
char Glitch04[] = {8, 8, B00000000, B00000000, B10010101, B10011010, B10010111, B11101010, B10111010, B11010000};
char Glitch044[] = {8, 8, B00000000, B00000000, B10001000, B10101010, B00011011, B10010101, B00000001, B00000000};
char Eye02[] = {8, 8, B00000000, B00000000, B00000110, B00001111, B11111111, B11111110, B11111100, B11110000};
char Eye01[] = {8, 8, B00000000, B00000000, B10000000, B11100000, B01111111, B00011111, B00000111, B00000000};
char Angry1[] = {8, 8, B00000000, B11000000, B11110000, B11111000, B11111100, B11111100, B11111000, B00000000};
char Angry2[] = {8, 8, B00000000, B00000001, B00000111, B00011111, B00111111, B01111111, B00111111, B00000000};
char Spooked1[] = {8, 8, B00000001, B00000111, B00000111, B00001111, B00001111, B00000111, B00000111, B00000001};
char Spooked2[] = {8, 8, B10000000, B11100000, B11100000, B11110000, B11110000, B11100000, B11100000, B10000000};
//Left side of the helmet
char noseLeft[] = {8, 8, B00000000, B00000000, B00000001, B00000011, B00000011, B00111111, B01111110, B00000000};
char icon01L[] = {8, 8, B00001000, B00011110, B01111011, B11100011, B11111111, B00000000, B00000000, B00000000};
char icon02L[] = {8, 8, B00000000, B00000000, B00000000, B00000001, B00000111, B00011110, B01111000, B11100000};
char icon03L[] = {8, 8, B00000000, B00000000, B00000000, B00000000, B11100000, B01111000, B00011110, B00000111};
char icon04L[] = {8, 8, B00000000, B00000000, B00000000, B00000111, B00011111, B01111000, B11100000, B10000000};
char Glitch01L[] = {8, 8, B10100101, B11010001, B01000111, B00001010, B10001001, B11010100, B00001100, B00000000};
char Glitch011L[] = {8, 8, B00000000, B00000000, B00000000, B10101011, B10100001, B01010111, B11101000, B00100000};
char Glitch02L[] = {8, 8, B00000000, B00000000, B00000000, B00000000, B00010010, B10010110, B01001011, B01110100};
char Glitch022L[] = {8, 8, B00000000, B00000000, B00000000, B00000101, B00010010, B10000110, B01010100, B10100010};
char Glitch03L[] = {8, 8, B00000000, B00000000, B00000000, B01110100, B00101100, B01001011, B10101001, B00101001};
char Glitch033L[] = {8, 8, B00000000, B00000000, B00000000, B00001000, B10100000, B01101001, B10011010, B01001101};
char Glitch04L[] = {8, 8, B00000000, B00000000, B10101001, B01011001, B11101001, B01010111, B01011101, B00001011};
char Glitch044L[] = {8, 8, B00000000, B00000000, B00010001, B00000110, B01010101, B11011000, B10101001, B10000000};
char Eye02L[] = {8, 8, B00000000, B00000000, B01100000, B11110000, B11111111, B01111111, B00111111, B00001111};
char Eye01L[] = {8, 8, B00000000, B00000000, B00000001, B00000111, B11111110, B11111000, B11100000, B00000000};
char Angry2L[] = {8, 8, B00000000, B00000011, B00001111, B00011111, B00111111, B00111111, B00011111, B00000000};
char Angry1L[] = {8, 8, B00000000, B10000000, B11100000, B11111000, B11111100, B11111110, B11111100, B00000000};
char Spooked1L[] = {8, 8, B00000001, B00000111, B00000111, B00001111, B00001111, B00000111, B00000111, B00000001};
char Spooked2L[] = {8, 8, B10000000, B11100000, B11100000, B11110000, B11110000, B11100000, B11100000, B10000000};
const int interruptPin = 2;
const int interruptPin2 = 3;
volatile long debounceTime = 0;
volatile long currentTime = 0;
int redPin = 5; //These pins are used for the expression indicating rgb LED.
int greenPin = 11;
int bluePin = 9;
//The terms DIN, CLK and CS state where you should connect the the cables from the matrix to the Arduino,
//so DIN is connected to digital pin 6 on the arduino and the CLK on digital pin 7
int DIN = 6; // DIN pin of MAX7219 module
int CLK = 7; // CLK pin of MAX7219 module
int CS = 8; // CS pin of MAX7219 module
int maxInUse = 14; //Change this number to the amount of matrixes you linked together
byte counter = 0;
byte counter2 = 0;
int column1L = 104;
int column2L = 112;
int column3L = 95;
int column4L = 103;
int column1 = 8;
int column2 = 16;
int column3 = -1;
int column4 = 7;
int state = 0;
int state2;
int stateSerial;
MaxMatrix m(DIN, CS, CLK, maxInUse);
void setup() { //starting up sequence
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
Serial.begin(9600);
randomSeed(analogRead(0));
m.init();
m.setIntensity(0); // You can change the brightness of the matrices within a range of 0-15
m.clear();
pinMode(interruptPin, OUTPUT);
digitalWrite(2, HIGH);
attachInterrupt(digitalPinToInterrupt(2), ISR_button, FALLING);
#ifndef visorSensor
state2 = 1;
#endif
#ifdef visorSensor
pinMode(interruptPin2, INPUT);
attachInterrupt(digitalPinToInterrupt(3), hallSensor, CHANGE);
if (digitalRead(3) == 0) {
state2 = 1;
}
#endif
}
void loop() { //This is where the program loop starts.
Serial.println(state2);
if (state2 == 1) { //The Hall sensor Detects wheter the visor is attached, only then will the leds turn on
if (Serial.available() > 0) { //Used for input through bluetooth or serial monitor instead of button.
stateSerial = Serial.read(); //Mainly for testing purposes
}
if (stateSerial == '0') {
state = 0;
}
if (stateSerial == '1') {
state = 1;
}
if (stateSerial == '2') {
state = 2;
}
m.writeSprite(88, 0, icon01L); //Icons for the mouth and nose are being turned on here
m.writeSprite(80, 0, icon02L);
m.writeSprite(72, 0, icon03L);
m.writeSprite(64, 0, icon04L);
m.writeSprite(56, 0, noseLeft);
m.writeSprite(48, 0, noseRight);
m.writeSprite(40, 0, icon04);
m.writeSprite(32, 0, icon03);
m.writeSprite(24, 0, icon02);
m.writeSprite(16, 0, icon01);
if (counter2 > 17) { //The blinking animation begins here
for (int i = 0; i < 5; i++) {
column1L = column1L - 1;
column2L = column2L - 1;
column1 = column1 - 1;
column2 = column2 - 1;
column3L = column3L + 1;
column4L = column4L + 1;
column3 = column3 + 1;
column4 = column4 + 1;
m.setColumn(column1L, 00000000);
m.setColumn(column2L, 00000000);
m.setColumn(column3L, 00000000);
m.setColumn(column4L, 00000000);
m.setColumn(column1, 00000000);
m.setColumn(column2, 00000000);
m.setColumn(column3, 00000000);
m.setColumn(column4, 00000000);
delay(15);
counter2++;
}
column1L = 104;
column2L = 112;
column3L = 95;
column4L = 103;
column1 = 8;
column2 = 16;
column3 = -1;
column4 = 7;
counter2 = 0;
}
counter2++;
Serial.print(("Expression #"));
Serial.println(state);
switch (state) { //First button press: Happy expression
case 0:
m.writeSprite(104, 0, Eye01L);
m.writeSprite(96, 0, Eye02L);
m.writeSprite(8, 0, Eye02);
m.writeSprite(0, 0, Eye01);
setColor(0, 32, 0); //Makes the colour of the rgb LED green
//You can enter any number between 0 and 255 to make any colour combination.
//255,255,255 for example would show a white colour and a lower number would dimm the LED.
//(the 16,8 million colours were not a lie :P)
break;
case 1: //Second button press: Surprised
m.writeSprite(104, 0, Spooked1L);
m.writeSprite(96, 0, Spooked2L);
m.writeSprite(8, 0, Spooked1);
m.writeSprite(0, 0, Spooked2);
setColor(0, 0, 8); //Makes the colour of the LED blue
break;
case 2: //Third button press: Angry expression
m.writeSprite(104, 0, Angry2L);
m.writeSprite(96, 0, Angry1L);
m.writeSprite(8, 0, Angry2);
m.writeSprite(0, 0, Angry1);
setColor(16, 0, 0); //Makes the colour of the LED red
counter++;
if (counter == 16) {
m.writeSprite(64, 0, Glitch044L);
m.writeSprite(72, 0, Glitch033L);
m.writeSprite(80, 0, Glitch022L);
m.writeSprite(88, 0, Glitch011L);
m.writeSprite(16, 0, Glitch011);
m.writeSprite(24, 0, Glitch022);
m.writeSprite(32, 0, Glitch033);
m.writeSprite(40, 0, Glitch044);
delay(75);
counter++;
}
if ((counter >= 17) && (counter < 18)) {
m.writeSprite(88, 0, icon01L);
m.writeSprite(80, 0, icon02L);
m.writeSprite(72, 0, icon03L);
m.writeSprite(64, 0, icon04L);
m.writeSprite(40, 0, icon04);
m.writeSprite(32, 0, icon03);
m.writeSprite(24, 0, icon02);
m.writeSprite(16, 0, icon01);
delay(200);
counter++;
}
if (counter >= 18) {
m.writeSprite(64, 0, Glitch04L);
m.writeSprite(72, 0, Glitch03L);
m.writeSprite(80, 0, Glitch02L);
m.writeSprite(88, 0, Glitch01L);
m.writeSprite(16, 0, Glitch01);
m.writeSprite(24, 0, Glitch02);
m.writeSprite(32, 0, Glitch03);
m.writeSprite(40, 0, Glitch04);
delay(75);
counter = 0;
}
break;
}
}
else {
m.clear();
}
}
void ISR_button() { //Stuff you shouldn't touch :P
currentTime = millis();
if ((currentTime - debounceTime) > 250) {
if (state < 2) {
state++;
}
else {
state = 0;
}
}
debounceTime = currentTime;
}
void hallSensor() { //Stuff you shouldn't touch :P
currentTime = millis();
if ((currentTime - debounceTime) > 25) {
if (digitalRead(3) == 0) {
state2 = 1;
}
else {
state2 = 0;
}
}
debounceTime = currentTime;
}
void setColor(int redValue, int greenValue, int blueValue) {
analogWrite(redPin, redValue);
analogWrite(greenPin, greenValue);
analogWrite(bluePin, blueValue);
}