feat: 全量同步 254 个常用的 Arduino 扩展库文件

This commit is contained in:
yczpf2019
2026-01-24 16:05:38 +08:00
parent c665ba662b
commit 397b9a23a3
6878 changed files with 2732224 additions and 1 deletions

View File

@@ -0,0 +1,25 @@
# Library for modular scrolling LED matrix text displays
[Version 1.0 Video](http://www.youtube.com/watch?v=JgzVCSFaz3I)
[Version 2.0 Video](http://www.youtube.com/watch?v=u1iELyROjW8)
[Library Documentation](https://majicdesigns.github.io/MD_Parola/)
Parola is a modular scrolling text display using MAX7219 or MAX7221 LED matrix display controllers using Arduino. The display is made up of any number of identical modules that are plugged together to create a wider/longer display.
* Text left, right or center justification in the display
* Text scrolling, entry and exit effects
* Control display parameters and animation speed
* Support for hardware SPI interface
* Multiple virtual displays (zones) in each string of LED modules
* User defined fonts and/or individual characters substitutions
* Support for double height displays
* Support for mixing text and graphics on the same display
The aim was to create a 'lego-like' LED matrix display, using standard 8x8 LED matrices. The software supports this flexibility through a scalable approach that only requires the definition of the number of modules to adapt existing software to a new configuration.
The Parola software has a dependency on the [MD_MAX72xx Arduino library](https://github.com/MajicDesigns/MD_MAX72xx) which implements hardware functions of the LED matrix. The library needs to be configured for the type of matrices being used - please refer to the hardware section of documentation for the [MD_MAX72xx library](https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html).
Parola discussion on the [Arduino forum](http://forum.arduino.cc/index.php?topic=171056.0) and kits available from [ElectroDragon](http://www.electrodragon.com/product/dot-matrix-chain-display-kit-max7219-v2).
Additional information also at [my blog](http://arduinoplusplus.wordpress.com).

View File

@@ -0,0 +1,54 @@
// Demonstrates revresed text (as if on front of an ambulance)
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 8
#define PAUSE_TIME 1000
#define SCROLL_SPEED 50
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// HARDWARE SPI
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
char *msg[] =
{
"Ambulance",
"Emergency",
};
void setup(void)
{
// initialise the LED display
P.begin();
P.setZoneEffect(0, true, PA_FLIP_LR);
}
void loop(void)
{
static uint8_t cycle = 0;
if (P.displayAnimate())
{
// set up the string
P.displayText(msg[cycle], PA_CENTER, SCROLL_SPEED, PAUSE_TIME, PA_PRINT, PA_NO_EFFECT);
// prepare for next pass
cycle = (cycle + 1) % ARRAY_SIZE(msg);
}
}

View File

@@ -0,0 +1,112 @@
// Program to show full catalog of the MD_Parola animations
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 4
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// Hardware SPI connection
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
// Global data
typedef struct
{
textEffect_t effect; // text effect to display
char * psz; // text string nul terminated
uint16_t speed; // speed multiplier of library default
uint16_t pause; // pause multiplier for library default
} sCatalog;
sCatalog catalog[] =
{
{ PA_PRINT, "PRINT", 1, 1 },
{ PA_PACMAN1,"PMAN1", 5, 1 },
{ PA_PACMAN2,"PMAN2", 5, 1 },
{ PA_ROCKET,"ROKET", 5, 1 },
{ PA_SLICE, "SLICE", 1, 1 },
{ PA_MESH, "MESH", 20, 1 },
{ PA_FADE, "FADE", 20, 1 },
{ PA_WIPE, "WIPE", 5, 1 },
{ PA_WIPE_CURSOR, "WPE_C", 4, 1 },
{ PA_OPENING, "OPEN", 3, 1 },
{ PA_OPENING_CURSOR, "OPN_C", 4, 1 },
{ PA_CLOSING, "CLOSE", 3, 1 },
{ PA_CLOSING_CURSOR, "CLS_C", 4, 1 },
{ PA_RANDOM, "RAND", 3, 1 },
{ PA_BLINDS, "BLIND", 7, 1 },
{ PA_DISSOLVE, "DSLVE", 7, 1 },
{ PA_SCROLL_UP, "SC_U", 5, 1 },
{ PA_SCROLL_DOWN, "SC_D", 5, 1 },
{ PA_SCROLL_LEFT, "SC_L", 5, 1 },
{ PA_SCROLL_RIGHT, "SC_R", 5, 1 },
{ PA_SCROLL_UP_LEFT, "SC_UL", 7, 1 },
{ PA_SCROLL_UP_RIGHT, "SC_UR", 7, 1 },
{ PA_SCROLL_DOWN_LEFT, "SC_DL", 7, 1 },
{ PA_SCROLL_DOWN_RIGHT, "SC_DR", 7, 1 },
{ PA_SCAN_HORIZ, "SCNH", 4, 1 },
{ PA_SCAN_HORIZX, "SCNHX", 4, 1 },
{ PA_SCAN_VERT, "SCNV", 3, 1 },
{ PA_SCAN_VERTX, "SCNVX", 3, 1 },
{ PA_GROW_UP, "GRW_U", 7, 1 },
{ PA_GROW_DOWN, "GRW_D", 7, 1 },
};
void setup(void)
{
P.begin();
for (uint8_t i=0; i<ARRAY_SIZE(catalog); i++)
{
catalog[i].speed *= P.getSpeed();
catalog[i].pause *= 500;
}
}
void loop(void)
{
static textPosition_t just = PA_LEFT;
static uint8_t i = 0;
static uint8_t j = 0;
if (P.displayAnimate()) // animates and returns true when an animation is completed
{
// rotate the justification if needed
if (i == ARRAY_SIZE(catalog))
{
j++;
if (j == 3) j = 0;
switch (j)
{
case 0: just = PA_LEFT; break;
case 1: just = PA_CENTER; break;
case 2: just = PA_RIGHT; break;
}
i = 0; // reset loop index
}
// set up new animation
P.displayText(catalog[i].psz, just, catalog[i].speed, catalog[i].pause, catalog[i].effect, catalog[i].effect);
delay(catalog[i].pause); // wait a while to show the text ...
i++; // ... then set up for next text effect
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -0,0 +1,618 @@
// Bluetooth control of Parola text display
//
// Full featured example controlling a Parola display through a
// BT interface to change the display parameters and text.
//
// An companion Android Application written using the MIT Application
// Inventor (AI2) can be run on an Android device to communicate with
// the Arduino application. AI2 can be found at http://ai2.appinventor.mit.edu/
//
// Provides control of:
// - Displayed message text and justification
// - Speed, pause time and inverted
// - Display intensity
// - Saving parameters to EEPROM
// - Display config reset, Arduino hardware reset
//
// Dependencies
// * AltSoftSerial https://www.pjrc.com/teensy/td_libs_AltSoftSerial.html
// Note: This library is used as an alternative to SoftwareSerial based on the
// defined value USE_ALTSOFTSERIAL below
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include <EEPROM.h>
// BT interface serial interface
#define USE_ALTSOFTSERIAL 0
#if USE_ALTSOFTSERIAL
#include <AltSoftSerial.h>
#else
#include <SoftwareSerial.h>
#endif
// MAX72xx Definitions ----------------
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 8
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// Bluetooth Serial interface ---------
// Bluetooth Serial comms pins and parameters
const uint8_t BT_RECV_PIN = 3; // Arduino receive -> Bluetooth TxD pin
const uint8_t BT_SEND_PIN = 2; // Arduino send -> Bluetooth RxD pin
const char BT_NAME[] = "Parola";
// Define the type of hardware being used.
// Only one of these options is enabled at any time.
// The HM-10 is the JHHuaMao (HMSoft) version, not Bolutek. Line ending for AT commands differ.
#define HW_USE_HC05 0
#define HW_USE_HC06 1
#define HW_USE_HM10_HMSOFT 0
#define HW_USE_HM10_OTHER 0
#if HW_USE_HC05
const uint8_t HC05_SETUP_ENABLE = 7;
#endif
// Miscellaneous
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
#define BUF_SIZE 100 // message buffer size
#define EEPROM_START_ADDR 0 // EEPROM address for setup info
//=====================================================
//======= END OF USER CONFIGURATION PARAMETERS ========
//=====================================================
// Turn on debug statements to the serial output
#define DEBUG 0
#if DEBUG
#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }
#define PRINTS(x) Serial.print(F(x))
#define PRINTX(x) Serial.println(x, HEX)
#else
#define PRINT(s, x)
#define PRINTS(x)
#define PRINTX(x)
#endif
/*
Communications Protocol Definition
Parola is configured as a BT receiver (ie, it only responds to commands and
data requests from the BT requester) using a simple protocol described below.
The Serial interface is implemented using the SoftwareSerial library and slow bit
rates are sufficient for the data load.
Communications between BT requester and responser are implemented in structured packets
with the following request/response pattern
<Start_Char><Command><Data><End_Char>
where
<Start_Char> is a single character used to synch the start of the data packet (PKT_START)
<Command> is an identifier for the action requested (PKT_CMD_*)
<Data> is an optional single character for data supporting <Command>
<End_Char> marks the end of a data packet (PKT_END)
A request is always followed by a response in the format
<Start_Char><Cmd><Error_Code><End_Char>
where
<Start_Char> and <End_Char> are as defined above
<Cmd> is always PKT_CMD_ACK
<Error_Code> is an ASCII digit with the result of the action (PKT_ERR_*)
Packets of data time out if they are not received in their entirety within
BT_COMMS_TIMEOUT milliseconds and the requester should expect a response with the same
timeout BT_COMMS_TIMEOUT period.
The Bluetooth device is initialised in the begin() method. The hardware MUST NOT BE CONNECTED
to a master or the initialisation parameters will be passed through the serial interface.
*/
// Serial protocol parameters
const uint16_t BT_COMMS_TIMEOUT = 1000; // Protocol packet timeout period (start to end packet within this period)
const char PKT_START = '*'; // protocol packet start character
const char PKT_END = '~'; // protocol packet end character
const char PKT_ESC = '#'; // protocol packet escape character
const char PKT_CMD_SPEED = 'S'; // number (ms delay between frames)
const char PKT_CMD_BRIGHT = 'B'; // Toggle 0-15
const char PKT_CMD_RESET = 'R'; // Reset the Arduino hardware
const char PKT_CMD_FACSET = 'F'; // Factory settings
const char PKT_CMD_SAVE = 'W'; // Write current setup to EEPROM
const char PKT_CMD_MESSAGE = 'M'; // Displayed message
const char PKT_CMD_JUSTIFY = 'J'; // Toggle L, C, R
const char PKT_CMD_INVERT = 'V'; // Toggle Invert/Normal
const char PKT_CMD_TPAUSE = 'P'; // number (ms delay between in and out)
const char PKT_CMD_IANIM = 'I'; // In Animation - toggle through Animations table
const char PKT_CMD_OANIM = 'O'; // Out animation - toggle through Animations table
const char PKT_CMD_ACK = 'Z'; // Acknowledge command - data is PKT_ERR_* defines
const char PKT_ERR_OK = '0'; // no error/ok
const char PKT_ERR_TOUT = '1'; // timeout - start detected with no end within timeout period
const char PKT_ERR_CMD = '2'; // command field not valid or unknown
const char PKT_ERR_DATA = '3'; // data field not valid
const char PKT_ERR_SEQ = '4'; // generic protocol sequence error
// Set up BT module initialisation parameters
// This depends on the BT module being used, as they need different AT commands.
// The AT commands are held as a long data string in PROGMEM. AT commands are
// separated by a nul character ('\0'). The last entry ends with a double nul.
// Note: The first entry must always be the BT name as this is passed as a
// parameter and is handled differently in the begin() initialisation code.
const char *szStart = "AT+";
#if HW_USE_HC05
const char *szEnd = "\r\n";
const char PROGMEM ATCmd[] = {"NAME=\0ROLE=0\0CLASS=800500\0RESET\0\0"};
#endif
#if HW_USE_HC06
const char *szEnd = "\r\n";
const char PROGMEM ATCmd[] = {"NAME\0\0"};
#endif
#if HW_USE_HM10_HMSOFT
const char *szEnd = "";
const char PROGMEM ATCmd[] = {"NAME\0TYPE0\0ROLE0\0RESET\0\0"};
#endif
#if HW_USE_HM10_OTHER
const char *szEnd = "\r\n";
const char PROGMEM ATCmd[] = {"NAME\0TYPE0\0ROLE0\0RESET\0\0"};
#endif
// Data tables --------------
const textPosition_t textPosition[] = { PA_LEFT, PA_CENTER, PA_RIGHT };
const textEffect_t textEffect[] =
{
PA_PRINT, PA_SCROLL_UP, PA_SCROLL_LEFT, PA_SCROLL_RIGHT, PA_SCROLL_DOWN,
#if ENA_SCR_DIA
PA_SCROLL_UP_LEFT, PA_SCROLL_UP_RIGHT, PA_SCROLL_DOWN_LEFT, PA_SCROLL_DOWN_RIGHT,
#endif // ENA_SCR_DIA
#if ENA_WIPE
PA_WIPE, PA_WIPE_CURSOR,
#endif // ENA_WIPES
#if ENA_OPNCLS
PA_OPENING, PA_OPENING_CURSOR, PA_CLOSING, PA_CLOSING_CURSOR,
#endif // ENA_OPNCLS
#if ENA_GROW
PA_GROW_UP, PA_GROW_DOWN,
#endif // ENA_GROW
#if ENA_MISC
PA_SLICE, PA_MESH, PA_FADE, PA_DISSOLVE, PA_BLINDS, PA_RANDOM,
#endif //ENA_MISC
#if ENA_SCAN
PA_SCAN_HORIZ, PA_SCAN_VERT,
#endif // ENA_SCAN
};
// Global Variables ------------------
// Parola with HARDWARE SPI
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
#if USE_ALTSOFTSERIAL
AltSoftSerial BTChan = AltSoftSerial();
#else
SoftwareSerial BTChan = SoftwareSerial(BT_RECV_PIN, BT_SEND_PIN);
#endif
#define SIG0 0x55
#define SIG1 0xaa
struct globalData
{
uint8_t signature[2]; // recognise this as a valid setup
uint16_t scrollSpeed; // frame delay value in ms
uint16_t scrollPause; // msg pause in ms
uint8_t effectI; // in effect index into table
uint8_t effectO; // out effect index into table
uint8_t align; // justification index into table
uint8_t intensity; // display intensity
bool bInvert; // display inverted
char msg[BUF_SIZE+1]; // the message being displayed
} G;
// Global message buffers shared by BT and Scrolling functions
char newMessage[BUF_SIZE+1] = { '\0' };
bool newMessageAvailable = false;
bool newConfigAvailable = false;
// Application Code ------------------
void(*hwReset) (void) = 0; //declare reset function @ address 0
void writeGlobal(void)
{
PRINTS("\nSaving Global");
EEPROM.put(EEPROM_START_ADDR, G);
}
void readGlobal(bool bInit = false)
{
PRINTS("\nLoading Global");
EEPROM.get(EEPROM_START_ADDR, G);
if (bInit || G.signature[0] != SIG0 || G.signature[1] != SIG1)
// set the default parameters
{
PRINTS("\nInitialising Global");
G.signature[0] = SIG0;
G.signature[1] = SIG1;
G.scrollSpeed = 25;
G.scrollPause = 2000;
G.effectI = G.effectO = 0;
G.align = 1;
G.intensity = 7;
G.bInvert = false;
strcpy(G.msg, "Setup");
writeGlobal();
}
newConfigAvailable = true;
}
bool BT_getATCmd(char* szBuf, uint8_t lenBuf, bool fReset = true)
// Copy the AT command from PROGMEM into the buffer provided
// The first call should reset the index counter
// Return true if this is the last command
{
static uint16_t cmdIdx;
if (fReset) cmdIdx = 0;
strncpy_P(szBuf, ATCmd + cmdIdx, lenBuf);
cmdIdx += (strlen_P(ATCmd + cmdIdx) + 1);
return(pgm_read_byte(ATCmd + cmdIdx) == '\0');
}
bool BT_getATResponse(char* resp, uint8_t lenBuf)
// Get an AT response from the BT module or time out waiting
{
const uint16_t RESP_TIMEOUT = 500;
uint32_t timeStart = millis();
char c = '\0';
uint8_t len = 0;
*resp = '\0';
while ((millis() - timeStart < RESP_TIMEOUT) && (c != '\n') && (len < lenBuf))
{
if (BTChan.available())
{
c = BTChan.read();
*resp++ = c;
*resp = '\0';
len++;
}
}
return(len != '\0');
}
void BT_sendACK(char resp)
// Send a protocol ACK to the BT master
{
static char msg[] = { PKT_START, PKT_CMD_ACK, PKT_ERR_OK, PKT_END, '\n', '\0' };
msg[2] = resp;
PRINT("\nResp: ", msg);
BTChan.print(msg);
BTChan.flush();
}
void BT_begin(void)
// initialise the BT device for different hardware
{
const uint16_t BAUD = 9600;
char szCmd[20], szResp[16];
uint8_t i = 0;
bool fLast = false;
PRINT("\nStart BT connection at ", BAUD);
BTChan.begin(BAUD);
#if HW_USE_HC05
// Switch the HC05 to setup mode using digital I/O
pinMode(HC05_SETUP_ENABLE, OUTPUT);
digitalWrite(HC05_SETUP_ENABLE, HIGH);
delay(10); // just a small amount of time
digitalWrite(HC05_SETUP_ENABLE, LOW);
#endif
// Process all the AT commands for the selected BT module
// Send each command, read the response (or time out) and then
// do the next one.
// First item is always the name!
do
{
fLast = BT_getATCmd(szCmd, ARRAY_SIZE(szCmd), (i == 0));
// Print the preamble, AT command, end of line by assembling the
// data into a string of allocated memory. This allows the data to
// send out in one hit rather than piecemeal.
char *sz = (char *)malloc((strlen(szStart) + strlen_P(szCmd) + \
strlen(BT_NAME) + strlen(szEnd) + 1) * sizeof(char));
strcpy(sz, szStart);
strcat(sz, szCmd);
if (i == 0) // first item - insert the name
strcat(sz, BT_NAME);
strcat(sz, szEnd);
BTChan.print(sz);
BTChan.flush();
free(sz);
i++;
// Wait for and get the response, except for the
// last one when we don't care as normally a RESET.
if (!fLast)
{
if (!BT_getATResponse(szResp, ARRAY_SIZE(szResp)))
{
PRINT("\nBT err on ", szCmd);
PRINT(":", szResp);
}
}
} while (!fLast);
BTChan.flush();
}
uint8_t BT_executeCommand(uint8_t cmd, char *pd)
{
uint8_t sts = PKT_ERR_OK; // assume all ok ...
PRINT("\nexecuting ", (char)cmd);
PRINT(" with '", pd);
PRINTS("'");
switch (cmd)
{
case PKT_CMD_RESET:
hwReset();
break;
case PKT_CMD_FACSET:
readGlobal(true);
PRINTS("\nCMD Factory Settings");
break;
case PKT_CMD_BRIGHT:
G.intensity = (G.intensity + 1) % (MAX_INTENSITY + 1);
PRINT("\nCMD Brightness ", G.intensity);
break;
case PKT_CMD_IANIM:
G.effectI = (G.effectI + 1) % ARRAY_SIZE(textEffect);
PRINT("\nCMD In Animation ", G.effectI);
break;
case PKT_CMD_OANIM:
G.effectO = (G.effectO + 1) % ARRAY_SIZE(textEffect);
PRINT("\nCMD Out Animation ", G.effectO);
break;
case PKT_CMD_INVERT:
G.bInvert = !P.getInvert();
PRINT("\nCMD Invert ", G.bInvert ? "on" : "off");
break;
case PKT_CMD_JUSTIFY:
G.align = (G.align + 1) % ARRAY_SIZE(textPosition);
PRINT("\nCMD Text Align ", G.align);
break;
case PKT_CMD_SAVE:
writeGlobal();
PRINTS("\nCMD Save");
break;
case PKT_CMD_MESSAGE:
strcpy(newMessage, pd);
newMessageAvailable = true;
PRINT("\nCMD Message '", newMessage); PRINTS("'");
break;
case PKT_CMD_SPEED:
case PKT_CMD_TPAUSE:
{
int16_t v = atoi(pd);
if (v < 0 || v > 10000)
sts = PKT_ERR_DATA;
else
{
if (cmd == PKT_CMD_SPEED)
{
G.scrollSpeed = v;
PRINT("\nCMD Speed ", v);
}
else
{
G.scrollPause = v;
PRINT("\nCMD Pause ", v);
}
}
}
break;
default:
sts = PKT_ERR_CMD;
PRINT("CMD Error - ", cmd);
break;
}
// set global flags
newConfigAvailable = (sts == PKT_ERR_OK && cmd != PKT_CMD_MESSAGE);
return(sts);
}
void BT_getCommand(void)
// Call repeatedly to receive and process characters waiting in the serial queue
// Return true when a good message is fully received
{
static enum { ST_IDLE, ST_CMD, ST_DATA, ST_END } state = ST_IDLE;
static uint32_t timeStart = 0;
static char cBuf[BUF_SIZE+1];
static uint16_t countBuf;
static char cmd = '\0';
static bool prevEsc, inEsc = false;
// check for timeout if we are currently mid-packet
if (state != ST_IDLE)
{
if (millis() - timeStart >= BT_COMMS_TIMEOUT)
{
BT_sendACK(PKT_ERR_TOUT);
timeStart = 0;
state = ST_IDLE;
}
}
// process the next character if there is one
if (BTChan.available())
{
char ch = BTChan.read();
// deal with the escape sequence indicator
prevEsc = inEsc;
inEsc = (ch == PKT_ESC && !prevEsc);
// now run the FSM
switch (state)
{
case ST_IDLE: // waiting start character
if (!prevEsc && ch == PKT_START)
{
PRINT("\nPkt Srt ", ch);
state = ST_CMD;
cmd = cBuf[0] = '\0';
timeStart = millis();
countBuf = 0;
}
break;
case ST_CMD: // reading command
cmd = ch; // save the command until we have a full protocol packet
PRINT("\nPkt Cmd ", cmd);
switch (ch)
{
case PKT_CMD_RESET:
case PKT_CMD_FACSET:
case PKT_CMD_BRIGHT:
case PKT_CMD_IANIM:
case PKT_CMD_OANIM:
case PKT_CMD_INVERT:
case PKT_CMD_JUSTIFY:
case PKT_CMD_SAVE:
case PKT_CMD_MESSAGE:
case PKT_CMD_SPEED:
case PKT_CMD_TPAUSE:
state = ST_DATA;
break;
default:
BT_sendACK(PKT_ERR_CMD);
cmd = '\0';
state = ST_IDLE;
break;
}
break;
case ST_DATA: // reading data
if (countBuf >= BUF_SIZE) // message too large - stop processing it now
{
PRINTS("\nBuffer overflow");
BT_sendACK(PKT_ERR_DATA);
state = ST_IDLE;
}
else if (ch == PKT_END && !prevEsc) // end character not escaped
{
PRINT("\nPkt end @", countBuf);
cBuf[countBuf] = '\0'; // terminate the string
BT_sendACK(BT_executeCommand(cmd, cBuf));
state = ST_IDLE;
}
else if (!inEsc) // not escaping, so save this
{
PRINT("\nPkt cBuf[", countBuf); PRINT("]:", ch);
cBuf[countBuf++] = ch;
}
break;
default: // something screwed up - reset the FSM
state = ST_IDLE;
BT_sendACK(PKT_ERR_SEQ);
break;
}
}
}
void setup()
{
#if DEBUG
Serial.begin(57600);
#endif
PRINTS("\n[Parola_BT_Control Debug]");
readGlobal();
P.begin();
P.displayClear();
BT_begin();
}
void loop()
{
// get the next thing from the BT channel
BT_getCommand();
// if the config has changed, need to change the display parameters
if (newConfigAvailable)
{
PRINTS("\nSetting new config");
P.setSpeed(G.scrollSpeed);
P.setPause(G.scrollPause);
P.setTextEffect(textEffect[G.effectI], textEffect[G.effectO]);
P.setTextAlignment(textPosition[G.align]);
P.setIntensity(G.intensity);
P.setInvert(G.bInvert);
P.setTextBuffer(G.msg);
P.displayReset();
newConfigAvailable = false;
}
// if we have a new message, copy it over
if (newMessageAvailable)
{
PRINTS("\nSetting new message");
strcpy(G.msg, newMessage);
P.displayReset();
newMessageAvailable = false;
}
// keep the animation going in all cases
if (P.displayAnimate())
P.displayReset();
}

View File

@@ -0,0 +1,94 @@
// Program to exercise the MD_Parola library
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 8
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// HARDWARE SPI
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
#define PAUSE_TIME 1000
// Turn on debug statements to the serial output
#define DEBUG 0
#if DEBUG
#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }
#define PRINTS(x) Serial.print(F(x))
#define PRINTX(x) Serial.println(x, HEX)
#else
#define PRINT(s, x)
#define PRINTS(x)
#define PRINTX(x)
#endif
uint8_t degC[] = { 6, 3, 3, 56, 68, 68, 68 }; // Deg C
uint8_t degF[] = { 6, 3, 3, 124, 20, 20, 4 }; // Deg F
uint8_t waveSine[] = { 8, 1, 14, 112, 128, 128, 112, 14, 1 }; // Sine wave
uint8_t waveSqar[] = { 8, 1, 1, 255, 128, 128, 128, 255, 1 }; // Square wave
uint8_t waveTrng[] = { 10, 2, 4, 8, 16, 32, 64, 32, 16, 8, 4 }; // Triangle wave
// Global variables
typedef struct
{
uint8_t spacing; // character spacing
char *msg; // message to display
} msgDef_t;
msgDef_t M[] =
{
{ 1, "User char" },
{ 0, "~~~~" },
{ 1, "24$" },
{ 0, "++++" },
{ 1, "40&" },
{ 0, "^^^^" }
};
#define MAX_STRINGS (sizeof(M)/sizeof(M[0]))
void setup(void)
{
Serial.begin(57600);
PRINTS("\n[Parola User Char Demo]");
P.begin();
P.addChar('$', degC);
P.addChar('&', degF);
P.addChar('~', waveSine);
P.addChar('+', waveSqar);
P.addChar('^', waveTrng);
P.setCharSpacing(M[0].spacing);
P.displayText(M[0].msg, PA_CENTER, P.getSpeed(), PAUSE_TIME, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
}
void loop(void)
{
static uint8_t n = 1;
if (P.displayAnimate())
{
P.setTextBuffer(M[n].msg);
P.setCharSpacing(M[n].spacing);
P.displayReset();
n = (n + 1) % MAX_STRINGS;
}
}

View File

@@ -0,0 +1,155 @@
// Program to demonstrate the MD_Parola library
//
// For every string defined by pc[] iterate through all combinations
// of entry and exit effects.
//
// Animation speed can be controlled using a pot on pin SPEED_IN
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 8
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// set to 1 if we are implementing the user interface pot
#define USE_UI_CONTROL 1
#if USE_UI_CONTROL
#define SPEED_IN A5
uint8_t frameDelay = 25; // default frame delay value
#endif // USE_UI_CONTROL
// Hardware SPI connection
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
#define SPEED_TIME 25
#define PAUSE_TIME 1000
// Turn on debug statements to the serial output
#define DEBUG 0
#if DEBUG
#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }
#define PRINTS(x) Serial.print(F(x))
#define PRINTX(x) Serial.println(x, HEX)
#else
#define PRINT(s, x)
#define PRINTS(x)
#define PRINTX(x)
#endif
// Global variables
uint8_t curText;
char *pc[] =
{
"Parola for",
"Arduino",
};
uint8_t inFX, outFX;
textEffect_t effect[] =
{
PA_PRINT,
PA_SCAN_HORIZ,
PA_SCROLL_LEFT,
PA_WIPE,
PA_SCROLL_UP_LEFT,
PA_SCROLL_UP,
PA_OPENING_CURSOR,
PA_GROW_UP,
PA_MESH,
PA_SCROLL_UP_RIGHT,
PA_BLINDS,
PA_CLOSING,
PA_RANDOM,
PA_GROW_DOWN,
PA_SCAN_VERT,
PA_SCROLL_DOWN_LEFT,
PA_WIPE_CURSOR,
PA_DISSOLVE,
PA_OPENING,
PA_CLOSING_CURSOR,
PA_SCROLL_DOWN_RIGHT,
PA_SCROLL_RIGHT,
PA_SLICE,
PA_SCROLL_DOWN,
};
#if USE_UI_CONTROL
void doUI(void)
{
// set the speed if it has changed
{
int16_t speed = map(analogRead(SPEED_IN), 0, 1023, 0, 250);
if (speed != (int16_t)P.getSpeed())
{
P.setSpeed(speed);
P.setPause(speed);
frameDelay = speed;
PRINT("\nChanged speed to ", P.getSpeed());
}
}
}
#endif // USE_UI_CONTROL
void setup(void)
{
Serial.begin(57600);
PRINTS("[Parola Demo]");
#if USE_UI_CONTROL
pinMode(SPEED_IN, INPUT);
doUI();
#endif // USE_UI_CONTROL
P.begin();
P.setInvert(false);
P.displayText(pc[curText], PA_CENTER, SPEED_TIME, PAUSE_TIME, effect[inFX], effect[outFX]);
}
void loop(void)
{
#if USE_UI_CONTROL
doUI();
#endif // USE_UI_CONTROL
if (P.displayAnimate()) // animates and returns true when an animation is completed
{
// Set the display for the next string.
curText = (++curText) % ARRAY_SIZE(pc);
P.setTextBuffer(pc[curText]);
// When we have gone back to the first string, set a new exit effect
// and when we have done all those set a new entry effect.
if (curText == 0)
{
outFX = (++outFX) % ARRAY_SIZE(effect);
if (outFX == 0)
{
inFX = (++inFX) % ARRAY_SIZE(effect);
if (inFX == 0)
P.setInvert(!P.getInvert());
}
P.setTextEffect(effect[inFX], effect[outFX]);
}
// Tell Parola we have a new animation
P.displayReset();
}
}

View File

@@ -0,0 +1,264 @@
// Data file for user example user defined fonts
#ifndef FONTDATA_H
#define FONTDATA_H
MD_MAX72XX::fontType_t numeric7SegDouble[] PROGMEM = {
0, // 0
0, // 1
0, // 2
0, // 3
0, // 4
0, // 5
0, // 6
0, // 7
0, // 8
0, // 9
0, // 10
0, // 11
0, // 12
0, // 13
0, // 14
0, // 15
0, // 16
0, // 17
0, // 18
0, // 19
0, // 20
0, // 21
0, // 22
0, // 23
0, // 24
0, // 25
0, // 26
0, // 27
0, // 28
0, // 29
0, // 30
0, // 31
2, 0, 0, // 32 - 'Space'
0, // 33 - '!'
0, // 34 - '"'
0, // 35 - '#'
0, // 36 - '$'
0, // 37 - '%'
0, // 38 - '&'
0, // 39 - '''
0, // 40 - '('
0, // 41 - ')'
0, // 42 - '*'
0, // 43 - '+'
0, // 44 - ','
0, // 45 - '-'
2, 48, 48, // 46 - '.'
0, // 47 - '/'
10, 62, 127, 192, 192, 192, 192, 192, 192, 127, 62, // 48 - '0'
10, 0, 0, 0, 0, 0, 0, 0, 0, 127, 62, // 49 - '1'
10, 62, 127, 193, 193, 193, 193, 193, 193, 64, 0, // 50 - '2'
10, 0, 65, 193, 193, 193, 193, 193, 193, 127, 62, // 51 - '3'
10, 0, 0, 1, 1, 1, 1, 1, 1, 127, 62, // 52 - '4'
10, 0, 64, 193, 193, 193, 193, 193, 193, 127, 62, // 53 - '5'
10, 62, 127, 193, 193, 193, 193, 193, 193, 127, 62, // 54 - '6'
10, 0, 0, 0, 0, 0, 0, 0, 0, 127, 62, // 55 - '7'
10, 62, 127, 193, 193, 193, 193, 193, 193, 127, 62, // 56 - '8'
10, 0, 64, 193, 193, 193, 193, 193, 193, 127, 62, // 57 - '9'
2, 6, 6, // 58 - ':'
0, // 59 - ';'
0, // 60 - '<'
0, // 61 - '='
0, // 62 - '>'
0, // 63 - '?'
0, // 64 - '@'
10, 62, 127, 1, 1, 1, 1, 1, 1, 127, 62, // 65 - 'A'
10, 62, 127, 193, 193, 193, 193, 193, 193, 127, 62, // 66 - 'B'
10, 62, 127, 193, 193, 193, 193, 193, 193, 65, 0, // 67 - 'C'
10, 62, 127, 193, 193, 193, 193, 193, 193, 127, 62, // 68 - 'D'
10, 62, 127, 193, 193, 193, 193, 193, 193, 65, 0, // 69 - 'E'
10, 62, 127, 1, 1, 1, 1, 1, 1, 1, 0, // 70 - 'F'
0, // 71 - 'G'
0, // 72 - 'H'
0, // 73 - 'I'
0, // 74 - 'J'
0, // 75 - 'K'
0, // 76 - 'L'
0, // 77 - 'M'
0, // 78 - 'N'
0, // 79 - 'O'
0, // 80 - 'P'
0, // 81 - 'Q'
0, // 82 - 'R'
0, // 83 - 'S'
0, // 84 - 'T'
0, // 85 - 'U'
0, // 86 - 'V'
0, // 87 - 'W'
0, // 88 - 'X'
0, // 89 - 'Y'
0, // 90 - 'Z'
0, // 91 - '['
0, // 92 - '\'
0, // 93 - ']'
0, // 94 - '^'
0, // 95 - '_'
0, // 96 - '`'
10, 62, 127, 1, 1, 1, 1, 1, 1, 127, 62, // 97 - 'a'
10, 62, 127, 193, 193, 193, 193, 193, 193, 127, 62, // 98 - 'b'
10, 62, 127, 193, 193, 193, 193, 193, 193, 65, 0, // 99 - 'c'
10, 62, 127, 193, 193, 193, 193, 193, 193, 127, 62, // 100 - 'd'
10, 62, 127, 193, 193, 193, 193, 193, 193, 65, 0, // 101 - 'e'
10, 62, 127, 1, 1, 1, 1, 1, 1, 1, 0, // 102 - 'f'
0, // 103 - 'g'
0, // 104 - 'h'
0, // 105 - 'i'
0, // 106 - 'j'
0, // 107 - 'k'
0, // 108 - 'l'
0, // 109 - 'm'
0, // 110 - 'n'
0, // 111 - 'o'
0, // 112 - 'p'
0, // 113 - 'q'
0, // 114 - 'r'
0, // 115 - 's'
0, // 116 - 't'
0, // 117 - 'u'
0, // 118 - 'v'
0, // 119 - 'w'
0, // 120 - 'x'
0, // 121 - 'y'
0, // 122 - 'z'
0, // 123 - '{'
2, 255, 255, // 124 - '|'
0, // 125
0, // 126
0, // 127
0, // 128
0, // 129
0, // 130
0, // 131
0, // 132
0, // 133
0, // 134
0, // 135
0, // 136
0, // 137
0, // 138
0, // 139
0, // 140
0, // 141
0, // 142
0, // 143
0, // 144
0, // 145
0, // 146
0, // 147
0, // 148
0, // 149
0, // 150
0, // 151
0, // 152
0, // 153
0, // 154
0, // 155
0, // 156
0, // 157
0, // 158
0, // 159
2, 0, 0, // 160
0, // 161
0, // 162
0, // 163
0, // 164
0, // 165
0, // 166
0, // 167
0, // 168
0, // 169
0, // 170
0, // 171
0, // 172
0, // 173
2, 0, 0, // 174
0, // 175
10, 124, 254, 3, 3, 3, 3, 3, 3, 254, 124, // 176
10, 0, 0, 0, 0, 0, 0, 0, 0, 254, 124, // 177
10, 0, 2, 131, 131, 131, 131, 131, 131, 254, 124, // 178
10, 0, 130, 131, 131, 131, 131, 131, 131, 254, 124, // 179
10, 124, 254, 128, 128, 128, 128, 128, 128, 254, 124, // 180
10, 124, 254, 131, 131, 131, 131, 131, 131, 2, 0, // 181
10, 124, 254, 131, 131, 131, 131, 131, 131, 2, 0, // 182
10, 0, 2, 3, 3, 3, 3, 3, 3, 254, 124, // 183
10, 124, 254, 131, 131, 131, 131, 131, 131, 254, 124, // 184
10, 124, 254, 131, 131, 131, 131, 131, 131, 254, 124, // 185
2, 96, 96, // 186
0, // 187
0, // 188
0, // 189
0, // 190
0, // 191
0, // 192
10, 124, 254, 131, 131, 131, 131, 131, 131, 254, 124, // 193
10, 124, 254, 128, 128, 128, 128, 128, 128, 0, 0, // 194
10, 0, 0, 128, 128, 128, 128, 128, 128, 0, 0, // 195
10, 0, 0, 128, 128, 128, 128, 128, 128, 254, 124, // 196
10, 124, 254, 131, 131, 131, 131, 131, 131, 130, 0, // 197
10, 124, 254, 131, 131, 131, 131, 131, 131, 130, 0, // 198
0, // 199
0, // 200
0, // 201
0, // 202
0, // 203
0, // 204
0, // 205
0, // 206
0, // 207
0, // 208
0, // 209
0, // 210
0, // 211
0, // 212
0, // 213
0, // 214
0, // 215
0, // 216
0, // 217
0, // 218
0, // 219
0, // 220
0, // 221
0, // 222
0, // 223
0, // 224
10, 124, 254, 131, 131, 131, 131, 131, 131, 254, 124, // 225
10, 124, 254, 128, 128, 128, 128, 128, 128, 0, 0, // 226
10, 0, 0, 128, 128, 128, 128, 128, 128, 0, 0, // 227
10, 0, 0, 128, 128, 128, 128, 128, 128, 254, 124, // 228
10, 124, 254, 131, 131, 131, 131, 131, 131, 130, 0, // 229
10, 124, 254, 131, 131, 131, 131, 131, 131, 130, 0, // 230
0, // 231
0, // 232
0, // 233
0, // 234
0, // 235
0, // 236
0, // 237
0, // 238
0, // 239
0, // 240
0, // 241
0, // 242
0, // 243
0, // 244
0, // 245
0, // 246
0, // 247
0, // 248
0, // 249
0, // 250
0, // 251
2, 255, 255, // 252
0, // 253
0, // 254
0, // 255
};
#endif

View File

@@ -0,0 +1,157 @@
// Program to demonstrate the MD_Parola library
//
// Display the time in a double height display with a fixed width font.
// - Time is shown in a user defined seven segment font
// - Optional use of DS1307 module for time
// - DS1307 library (MD_DS1307) found at https://github.com/MajicDesigns/DS1307
//
// Each font file has the lower part of a character as ASCII codes 0-127 and the
// upper part of the character in ASCII code 128-255. Adding 128 to each lower
// character creates the correct index for the upper character.
// The upper and lower portions are managed as 2 zones 'stacked' on top of each other
// so that the module numbers are in the sequence shown below:
//
// * Modules (like FC-16) that can fit over each other with no gap
// n n-1 n-2 ... n/2+1 <- this direction top row
// n/2 ... 3 2 1 0 <- this direction bottom row
//
// * Modules (like Generic and Parola) that cannot fit over each other with no gap
// n/2+1 ... n-2 n-1 n -> this direction top row
// n/2 ... 3 2 1 0 <- this direction bottom row
//
// Sending the original string to the lower zone and the modified (+128) string to the
// upper zone creates the complete message on the display.
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
// Use the DS1307 clock module
#define USE_DS1307 0
// Header file includes
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include "Font_Data.h"
#if USE_GENERIC_HW || USE_PAROLA_HW
#define INVERT_UPPER_ZONE
#endif
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_ZONES 2
#define ZONE_SIZE 7
#define MAX_DEVICES (MAX_ZONES * ZONE_SIZE)
#define ZONE_UPPER 1
#define ZONE_LOWER 0
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
#if USE_DS1307
#include <MD_DS1307.h>
#include <Wire.h>
#endif
// Hardware SPI connection
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
#define SPEED_TIME 75
#define PAUSE_TIME 0
#define MAX_MESG 6
// Turn on debug statements to the serial output
#define DEBUG 0
// Global variables
char szTimeL[MAX_MESG]; // mm:ss\0
char szTimeH[MAX_MESG];
void getTime(char *psz, bool f = true)
// Code for reading clock time
// Simulated clock runs 1 minute every seond
{
#if USE_DS1307
RTC.readTime();
sprintf(psz, "%02d%c%02d", RTC.h, (f ? ':' : ' '), RTC.m);
#else
uint16_t h, m, s;
m = millis()/1000;
h = (m/60) % 24;
m %= 60;
sprintf(psz, "%02d%c%02d", h, (f ? ':' : ' '), m);
#endif
}
void createHString(char *pH, char *pL)
{
for (; *pL != '\0'; pL++)
*pH++ = *pL | 0x80; // offset character
*pH = '\0'; // terminate the string
}
void setup(void)
{
// initialise the LED display
P.begin(MAX_ZONES);
// Set up zones for 2 halves of the display
P.setZone(ZONE_LOWER, 0, ZONE_SIZE - 1);
P.setZone(ZONE_UPPER, ZONE_SIZE, MAX_DEVICES - 1);
P.setFont(numeric7SegDouble);
P.setCharSpacing(P.getCharSpacing() * 2); // double height --> double spacing
#ifdef INVERT_UPPER_ZONE
P.setZoneEffect(ZONE_UPPER, true, PA_FLIP_UD);
P.setZoneEffect(ZONE_UPPER, true, PA_FLIP_LR);
P.displayZoneText(ZONE_LOWER, szTimeL, PA_RIGHT, SPEED_TIME, PAUSE_TIME, PA_PRINT, PA_NO_EFFECT);
P.displayZoneText(ZONE_UPPER, szTimeH, PA_LEFT, SPEED_TIME, PAUSE_TIME, PA_PRINT, PA_NO_EFFECT);
#else
P.displayZoneText(ZONE_LOWER, szTimeL, PA_CENTER, SPEED_TIME, PAUSE_TIME, PA_PRINT, PA_NO_EFFECT);
P.displayZoneText(ZONE_UPPER, szTimeH, PA_CENTER, SPEED_TIME, PAUSE_TIME, PA_PRINT, PA_NO_EFFECT);
#endif
#if USE_DS1307
RTC.control(DS1307_CLOCK_HALT, DS1307_OFF);
RTC.control(DS1307_12H, DS1307_OFF);
#endif
}
void loop(void)
{
static uint32_t lastTime = 0; // millis() memory
static bool flasher = false; // seconds passing flasher
P.displayAnimate();
if (P.getZoneStatus(ZONE_LOWER) && P.getZoneStatus(ZONE_UPPER))
{
// Adjust the time string if we have to. It will be adjusted
// every second at least for the flashing colon separator.
if (millis() - lastTime >= 1000)
{
lastTime = millis();
getTime(szTimeL, flasher);
createHString(szTimeH, szTimeL);
flasher = !flasher;
P.displayReset();
// synchronise the start
P.synchZoneStart();
}
}
}

View File

@@ -0,0 +1,264 @@
// Data file for user example user defined fonts
#ifndef FONTDATA_H
#define FONTDATA_H
MD_MAX72XX::fontType_t BigFont[] PROGMEM = {
0, // 0
0, // 1
0, // 2
0, // 3
0, // 4
0, // 5
0, // 6
0, // 7
0, // 8
0, // 9
0, // 10
0, // 11
0, // 12
0, // 13
0, // 14
0, // 15
0, // 16
0, // 17
0, // 18
0, // 19
0, // 20
0, // 21
0, // 22
0, // 23
0, // 24
0, // 25
0, // 26
0, // 27
0, // 28
0, // 29
0, // 30
0, // 31
4, 0, 0, 0, 0, // 32 - 'Space lower'
2, 51, 51, // 33 - '! lower'
6, 0, 0, 0, 0, 0, 0, // 34 - '" lower'
10, 3, 3, 63, 63, 3, 3, 63, 63, 3, 3, // 35 - '# lower'
10, 24, 56, 48, 48, 127, 127, 48, 57, 31, 15, // 36 - '$ lower'
8, 48, 60, 15, 3, 24, 36, 36, 24, // 37 - '% lower'
10, 15, 31, 57, 48, 48, 59, 31, 14, 63, 51, // 38 - '& lower'
2, 0, 0, // 39 - ' lower'
5, 3, 15, 28, 56, 48, // 40 - '( lower'
5, 48, 56, 28, 15, 3, // 41 - ') lower'
10, 6, 7, 7, 1, 31, 31, 1, 3, 7, 6, // 42 - '* lower'
10, 0, 0, 0, 0, 15, 15, 0, 0, 0, 0, // 43 - '+ lower'
2, 176, 112, // 44 - ', lower'
9, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 45 - '- lower'
2, 48, 48, // 46 - '. lower'
8, 48, 60, 15, 3, 0, 0, 0, 0, // 47 - '/ lower'
10, 15, 31, 57, 48, 48, 48, 48, 56, 31, 15, // 48 - '0 lower'
5, 0, 48, 63, 63, 48, // 49 - '1 lower'
10, 63, 63, 49, 48, 48, 48, 48, 48, 48, 48, // 50 - '2 lower'
10, 12, 28, 56, 48, 48, 48, 48, 56, 31, 15, // 51 - '3 lower'
10, 3, 3, 3, 3, 3, 3, 3, 63, 63, 3, // 52 - '4 lower'
10, 12, 28, 56, 48, 48, 48, 48, 56, 31, 15, // 53 - '5 lower'
10, 15, 31, 56, 48, 48, 48, 48, 56, 31, 15, // 54 - '6 lower'
10, 0, 0, 0, 63, 63, 0, 0, 0, 0, 0, // 55 - '7 lower'
10, 15, 31, 57, 48, 48, 48, 48, 57, 31, 15, // 56 - '8 lower'
10, 0, 0, 0, 0, 0, 0, 0, 0, 63, 63, // 57 - '9 lower'
2, 24, 24, // 58 - ': lower'
2, 88, 56, // 59 - '; lower'
8, 0, 1, 3, 7, 14, 28, 56, 48, // 60 - '< lower'
9, 6, 6, 6, 6, 6, 6, 6, 6, 6, // 61 - '= lower'
8, 48, 56, 28, 14, 7, 3, 1, 0, // 62 - '> lower'
10, 0, 0, 0, 0, 55, 55, 1, 0, 0, 0, // 63 - '? lower'
10, 15, 31, 56, 51, 54, 54, 51, 54, 55, 19, // 64 - '@ lower'
10, 63, 63, 1, 1, 1, 1, 1, 1, 63, 63, // 65 - 'A lower'
10, 63, 63, 48, 48, 48, 48, 48, 57, 31, 15, // 66 - 'B lower'
10, 15, 31, 56, 48, 48, 48, 48, 56, 28, 12, // 67 - 'C lower'
10, 63, 63, 48, 48, 48, 48, 48, 56, 31, 15, // 68 - 'D lower'
9, 63, 63, 48, 48, 48, 48, 48, 48, 48, // 69 - 'E lower'
9, 63, 63, 0, 0, 0, 0, 0, 0, 0, // 70 - 'F lower'
10, 15, 31, 56, 48, 48, 48, 49, 57, 31, 15, // 71 - 'G lower'
10, 63, 63, 0, 0, 0, 0, 0, 0, 63, 63, // 72 - 'H lower'
4, 48, 63, 63, 48, // 73 - 'I lower'
8, 12, 28, 56, 48, 48, 56, 31, 15, // 74 - 'J lower'
9, 63, 63, 1, 3, 7, 14, 28, 56, 48, // 75 - 'K lower'
9, 63, 63, 48, 48, 48, 48, 48, 48, 48, // 76 - 'L lower'
10, 63, 63, 0, 0, 0, 0, 0, 0, 63, 63, // 77 - 'M lower'
10, 63, 63, 0, 0, 0, 0, 1, 3, 63, 63, // 78 - 'N lower'
10, 15, 31, 56, 48, 48, 48, 48, 56, 31, 15, // 79 - 'O lower'
10, 63, 63, 0, 0, 0, 0, 0, 0, 0, 0, // 80 - 'P lower'
10, 15, 31, 56, 48, 48, 54, 62, 28, 63, 55, // 81 - 'Q lower'
10, 63, 63, 0, 1, 3, 7, 14, 28, 56, 48, // 82 - 'R lower'
10, 24, 56, 48, 48, 48, 48, 48, 57, 31, 15, // 83 - 'S lower'
8, 0, 0, 0, 63, 63, 0, 0, 0, // 84 - 'T lower'
10, 15, 31, 56, 48, 48, 48, 48, 56, 31, 15, // 85 - 'U lower'
10, 3, 7, 14, 28, 56, 56, 28, 14, 7, 3, // 86 - 'V lower'
10, 15, 31, 56, 60, 31, 31, 60, 56, 31, 15, // 87 - 'W lower'
10, 60, 62, 7, 3, 1, 1, 3, 7, 62, 60, // 88 - 'X lower'
10, 0, 0, 0, 0, 63, 63, 0, 0, 0, 0, // 89 - 'Y lower'
10, 60, 62, 55, 51, 49, 48, 48, 48, 48, 48, // 90 - 'Z lower'
4, 63, 63, 48, 48, // 91 - '[ lower'
8, 0, 0, 0, 0, 3, 15, 60, 48, // 92 - '\ lower'
4, 48, 48, 63, 63, // 93 - '] lower'
8, 0, 0, 0, 0, 0, 0, 0, 0, // 94 - '^ lower'
10, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 95 - '_ lower'
3, 0, 0, 0, // 96 - '` lower'
10, 12, 30, 51, 51, 51, 51, 51, 51, 63, 31, // 97 - 'a lower'
10, 63, 63, 28, 56, 48, 48, 48, 56, 31, 15, // 98 - 'b lower'
9, 15, 31, 56, 48, 48, 48, 56, 28, 12, // 99 - 'c lower'
10, 15, 31, 56, 48, 48, 48, 56, 28, 63, 63, // 100 - 'd lower'
9, 15, 31, 59, 51, 51, 51, 59, 27, 9, // 101 - 'e lower'
7, 0, 63, 63, 0, 0, 0, 0, // 102 - 'f lower'
9, 49, 115, 231, 198, 198, 198, 230, 127, 63, // 103 - 'g lower'
9, 63, 63, 0, 0, 0, 0, 0, 63, 63, // 104 - 'h lower'
2, 63, 63, // 105 - 'i lower'
8, 48, 112, 224, 192, 192, 224, 127, 63, // 106 - 'j lower'
8, 63, 63, 3, 7, 15, 28, 56, 48, // 107 - 'k lower'
4, 48, 63, 63, 48, // 108 - 'l lower'
10, 63, 63, 0, 0, 63, 63, 0, 0, 63, 63, // 109 - 'm lower'
9, 63, 63, 0, 0, 0, 0, 0, 63, 63, // 110 - 'n lower'
9, 15, 31, 56, 48, 48, 48, 56, 31, 15, // 111 - 'o lower'
9, 255, 255, 7, 14, 12, 12, 14, 7, 3, // 112 - 'p lower'
9, 3, 7, 14, 12, 12, 14, 7, 255, 255, // 113 - 'q lower'
9, 63, 63, 0, 0, 0, 0, 0, 0, 0, // 114 - 'r lower'
9, 24, 57, 51, 51, 51, 51, 51, 30, 12, // 115 - 's lower'
6, 0, 31, 63, 48, 56, 24, // 116 - 't lower'
9, 15, 31, 56, 48, 48, 56, 28, 63, 63, // 117 - 'u lower'
9, 7, 15, 28, 56, 48, 56, 28, 15, 7, // 118 - 'v lower'
10, 15, 31, 56, 56, 31, 31, 56, 56, 31, 15, // 119 - 'w lower'
10, 48, 56, 28, 15, 7, 7, 15, 28, 56, 48, // 120 - 'x lower'
9, 49, 115, 230, 198, 198, 198, 230, 127, 63, // 121 - 'y lower'
10, 48, 56, 60, 62, 55, 51, 49, 48, 48, 48, // 122 - 'z lower'
6, 0, 1, 15, 31, 56, 48, // 123 - '{ lower'
2, 255, 255, // 124 - '| lower'
6, 48, 56, 31, 15, 1, 0, // 125 - '} lower'
0, // 126
0, // 127
0, // 128
0, // 129
0, // 130
0, // 131
0, // 132
0, // 133
0, // 134
0, // 135
0, // 136
0, // 137
0, // 138
0, // 139
0, // 140
0, // 141
0, // 142
0, // 143
0, // 144
0, // 145
0, // 146
0, // 147
0, // 148
0, // 149
0, // 150
0, // 151
0, // 152
0, // 153
0, // 154
0, // 155
0, // 156
0, // 157
0, // 158
0, // 159
4, 0, 0, 0, 0, // 160 - 'Space upper'
2, 255, 255, // 161 - '! upper'
6, 15, 15, 0, 0, 15, 15, // 162 - '" upper'
10, 48, 48, 255, 255, 48, 48, 255, 255, 48, 48, // 163 - '# upper'
10, 56, 124, 238, 198, 255, 255, 198, 198, 142, 12, // 164 - '$ upper'
8, 6, 9, 9, 198, 240, 60, 15, 3, // 165 - '% upper'
10, 0, 128, 204, 254, 243, 243, 158, 12, 0, 0, // 166 - '& upper'
2, 15, 15, // 167 - '' upper'
5, 240, 252, 14, 7, 3, // 168 - '( upper'
5, 3, 7, 14, 252, 240, // 169 - ') upper'
10, 48, 112, 224, 192, 252, 252, 192, 224, 112, 48, // 170 - '* upper'
10, 192, 192, 192, 192, 252, 252, 192, 192, 192, 192, // 171 - '+ upper'
2, 0, 0, // 172 - ', upper'
9, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 173 - '- upper'
2, 0, 0, // 174 - '. upper'
8, 0, 0, 0, 192, 240, 60, 15, 3, // 175 - '/ upper'
10, 252, 254, 135, 195, 99, 51, 27, 15, 254, 252, // 176 - '0 upper'
5, 4, 6, 255, 255, 0, // 177 - '1 upper'
10, 12, 142, 199, 195, 195, 195, 195, 231, 126, 60, // 178 - '2 upper'
10, 12, 14, 7, 3, 3, 195, 195, 199, 254, 60, // 179 - '3 upper'
10, 128, 192, 224, 112, 56, 28, 14, 255, 255, 0, // 180 - '4 upper'
10, 63, 63, 51, 51, 51, 51, 51, 115, 227, 195, // 181 - '5 upper'
10, 252, 254, 231, 99, 99, 99, 99, 231, 198, 132, // 182 - '6 upper'
10, 3, 3, 3, 131, 195, 227, 115, 59, 31, 15, // 183 - '7 upper'
10, 28, 190, 247, 227, 195, 195, 227, 247, 190, 28, // 184 - '8 upper'
10, 60, 126, 231, 195, 195, 195, 195, 231, 255, 254, // 185 - '9 upper'
2, 48, 48, // 186 - ': upper'
2, 48, 48, // 187 - '; upper'
8, 192, 224, 240, 56, 28, 14, 7, 3, // 188 - '< upper'
9, 96, 96, 96, 96, 96, 96, 96, 96, 96, // 189 - '= upper'
8, 3, 7, 14, 28, 56, 240, 224, 192, // 190 - '> upper'
10, 12, 14, 7, 3, 3, 131, 195, 231, 126, 60, // 191 - '? upper'
10, 252, 254, 7, 243, 27, 27, 243, 7, 254, 252, // 192 - '@ upper'
10, 248, 254, 134, 131, 131, 131, 131, 134, 254, 248, // 193 - 'A upper'
10, 255, 255, 195, 195, 195, 195, 195, 231, 254, 60, // 194 - 'B upper'
10, 252, 254, 7, 3, 3, 3, 3, 7, 14, 12, // 195 - 'C upper'
10, 255, 255, 3, 3, 3, 3, 3, 7, 254, 252, // 196 - 'D upper'
9, 255, 255, 195, 195, 195, 195, 195, 3, 3, // 197 - 'E upper'
9, 255, 255, 195, 195, 195, 195, 195, 3, 3, // 198 - 'F upper'
10, 252, 254, 7, 3, 3, 3, 131, 135, 142, 140, // 199 - 'G upper'
10, 255, 255, 192, 192, 192, 192, 192, 192, 255, 255, // 200 - 'H upper'
4, 3, 255, 255, 3, // 201 - 'I upper'
8, 3, 3, 3, 3, 3, 3, 255, 255, // 202 - 'J upper'
9, 255, 255, 224, 240, 56, 28, 14, 7, 3, // 203 - 'K upper'
9, 255, 255, 0, 0, 0, 0, 0, 0, 0, // 204 - 'L upper'
10, 255, 255, 14, 28, 120, 120, 28, 14, 255, 255, // 205 - 'M upper'
10, 255, 255, 28, 56, 112, 224, 192, 128, 255, 255, // 206 - 'N upper'
10, 252, 254, 7, 3, 3, 3, 3, 7, 254, 252, // 207 - 'O upper'
10, 255, 255, 195, 195, 195, 195, 195, 231, 126, 60, // 208 - 'P upper'
10, 252, 254, 7, 3, 3, 3, 3, 7, 254, 252, // 209 - 'Q upper'
10, 255, 255, 195, 195, 195, 195, 195, 231, 126, 60, // 210 - 'R upper'
10, 60, 126, 231, 195, 195, 195, 195, 195, 135, 6, // 211 - 'S upper'
8, 3, 3, 3, 255, 255, 3, 3, 3, // 212 - 'T upper'
10, 255, 255, 0, 0, 0, 0, 0, 0, 255, 255, // 213 - 'U upper'
10, 255, 255, 0, 0, 0, 0, 0, 0, 255, 255, // 214 - 'V upper'
10, 255, 255, 0, 0, 0, 0, 0, 0, 255, 255, // 215 - 'W upper'
10, 15, 31, 56, 240, 224, 224, 240, 56, 31, 15, // 216 - 'X upper'
10, 15, 31, 56, 112, 224, 224, 112, 56, 31, 15, // 217 - 'Y upper'
10, 3, 3, 3, 131, 195, 227, 115, 59, 31, 15, // 218 - 'Z upper'
4, 255, 255, 3, 3, // 219 - '[ upper'
8, 3, 15, 60, 240, 192, 0, 0, 0, // 220 - '\ upper'
4, 3, 3, 255, 255, // 221 - '] upper'
8, 24, 12, 6, 3, 3, 6, 12, 24, // 222 - '^ upper'
10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 223 - '_ upper'
3, 3, 15, 12, // 224 - '` upper'
10, 0, 96, 112, 48, 48, 48, 48, 112, 224, 192, // 225 - 'a upper'
10, 255, 255, 224, 112, 48, 48, 48, 112, 224, 192, // 226 - 'b upper'
9, 192, 224, 112, 48, 48, 48, 112, 224, 192, // 227 - 'c upper'
10, 192, 224, 112, 48, 48, 48, 112, 224, 255, 255, // 228 - 'd upper'
9, 192, 224, 112, 48, 48, 48, 112, 224, 192, // 229 - 'e upper'
7, 192, 252, 254, 199, 199, 14, 12, // 230 - 'f upper'
9, 192, 224, 112, 48, 48, 48, 112, 224, 192, // 231 - 'g upper'
9, 255, 255, 224, 112, 48, 48, 112, 224, 192, // 232 - 'h upper'
2, 246, 246, // 233 - 'i upper'
8, 0, 0, 0, 0, 0, 0, 246, 246, // 234 - 'j upper'
8, 254, 254, 0, 128, 192, 224, 112, 48, // 235 - 'k upper'
4, 3, 255, 255, 0, // 236 - 'l upper'
10, 240, 240, 48, 48, 240, 240, 48, 48, 240, 224, // 237 - 'm upper'
9, 240, 240, 224, 112, 48, 48, 112, 224, 192, // 238 - 'n upper'
9, 192, 224, 112, 48, 48, 48, 112, 224, 192, // 239 - 'o upper'
9, 240, 240, 96, 112, 48, 48, 112, 224, 192, // 240 - 'p upper'
9, 192, 224, 112, 48, 48, 112, 96, 240, 240, // 241 - 'q upper'
9, 240, 240, 224, 112, 48, 48, 112, 224, 192, // 242 - 'r upper'
9, 192, 224, 48, 48, 48, 48, 112, 96, 0, // 243 - 's upper'
6, 96, 252, 252, 96, 96, 0, // 244 - 't upper'
9, 240, 240, 0, 0, 0, 0, 0, 240, 240, // 245 - 'u upper'
9, 240, 240, 0, 0, 0, 0, 0, 240, 240, // 246 - 'v upper'
10, 240, 240, 0, 0, 0, 0, 0, 0, 240, 240, // 247 - 'w upper'
10, 48, 112, 224, 192, 128, 128, 192, 224, 112, 48, // 248 - 'x upper'
9, 240, 240, 0, 0, 0, 0, 0, 240, 240, // 249 - 'y upper'
10, 48, 48, 48, 48, 48, 176, 240, 240, 112, 48, // 250 - 'z upper'
6, 192, 224, 252, 62, 7, 3, // 251 - '{ upper'
2, 255, 255, // 252 - '| upper'
6, 3, 7, 62, 252, 224, 192, // 253 - '} upper'
0, // 254
0, // 255
};
#endif

View File

@@ -0,0 +1,290 @@
// Demonstrates one double height display using Parola using a single font file
// defintion created with the MD_MAX72xx font builder.
//
// Each font file has the lower part of a character as ASCII codes 0-127 and the
// upper part of the character in ASCII code 128-255. Adding 128 to each lower
// character creates the correct index for the upper character.
// The upper and lower portions are managed as 2 zones 'stacked' on top of each other
// so that the module numbers are in the sequence shown below:
//
// * Modules (like FC-16) that can fit over each other with no gap
// n n-1 n-2 ... n/2+1 <- this direction top row
// n/2 ... 3 2 1 0 <- this direction bottom row
//
// * Modules (like Generic and Parola) that cannot fit over each other with no gap
// n/2+1 ... n-2 n-1 n -> this direction top row
// n/2 ... 2 1 0 <- this direction bottom row
//
// Sending the original string to the lower zone and the modified (+128) string to the
// upper zone creates the complete message on the display.
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include "Font_Data.h"
#if USE_GENERIC_HW || USE_PAROLA_HW
#define INVERT_UPPER_ZONE
#else
#undef INVERT_UPPER_ZONE
#endif
// Turn debugging on and off
#define DEBUG 0
#if DEBUG
#define PRINTS(s) { Serial.print(F(s)); }
#define PRINT(s, v) { Serial.print(F(s)); Serial.print(v); }
#define PRINTX(s, v) { Serial.print(F(s)); Serial.print(F("0x")); Serial.print(v, HEX); }
#else
#define PRINTS(s)
#define PRINT(s, v)
#define PRINTX(s, v)
#endif
// User interface pin and switch definitions
#define SPEED_IN A5 // control the speed with an external pot
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers may not work with your hardware and may need changing
#define MAX_ZONES 2
#define ZONE_SIZE 6
#define MAX_DEVICES (MAX_ZONES * ZONE_SIZE)
#define PAUSE_TIME 1000
#define SPEED_DEADBAND 5 // in analog units
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// HARDWARE SPI
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
#define ZONE_LOWER 0
#define ZONE_UPPER 1
// Alignment of the two zones
#ifdef INVERT_UPPER_ZONE
// if inverted, alignment should be opposite and
// CENTER may not work well depending on message
#define ALIGN_LOWER PA_LEFT
#define ALIGN_UPPER PA_RIGHT
#else
// if not inverted, should always be the same
#define ALIGN_LOWER PA_CENTER
#define ALIGN_UPPER ALIGN_LOWER
#endif
char *msgL[] =
{
"Abc",
"123",
"xyz"
};
char* msgH; // allocated memory in setup()
typedef struct catalogItem_t
{
bool fPause;
uint8_t zFX[MAX_ZONES];
};
const PROGMEM catalogItem_t catalog[] =
{
#ifdef INVERT_UPPER_ZONE
{ true, { PA_PRINT, PA_PRINT } },
{ false, { PA_SCROLL_LEFT, PA_SCROLL_RIGHT } },
{ false, { PA_SCROLL_RIGHT, PA_SCROLL_LEFT } },
{ true, { PA_SCROLL_UP, PA_SCROLL_UP } },
{ true, { PA_SCROLL_DOWN, PA_SCROLL_DOWN } },
#if ENA_MISC
// { true, { PA_SLICE, PA_SLICE } }, // looks wrong because of reversal
{ true, { PA_FADE, PA_FADE } },
{ true, { PA_MESH, PA_MESH } },
{ true, { PA_BLINDS, PA_BLINDS } },
{ true, { PA_DISSOLVE, PA_DISSOLVE } },
#endif
#if ENA_WIPE
{ true, { PA_WIPE, PA_WIPE } },
{ true, { PA_WIPE_CURSOR, PA_WIPE_CURSOR } },
#endif
#if ENA_OPNCLS
{ true, { PA_OPENING, PA_OPENING } },
{ true, { PA_OPENING_CURSOR, PA_OPENING_CURSOR } },
{ true, { PA_CLOSING, PA_CLOSING } },
{ true, { PA_CLOSING_CURSOR, PA_CLOSING_CURSOR } },
#endif
#if ENA_SCR_DIA
{ true, { PA_SCROLL_UP_LEFT, PA_SCROLL_UP_LEFT } },
{ true, { PA_SCROLL_UP_RIGHT, PA_SCROLL_UP_RIGHT } },
{ true, { PA_SCROLL_DOWN_LEFT, PA_SCROLL_DOWN_LEFT } },
{ true, { PA_SCROLL_DOWN_RIGHT, PA_SCROLL_DOWN_RIGHT } },
#endif
#if ENA_SCAN
{ true, { PA_SCAN_HORIZ, PA_SCAN_HORIZ } },
{ true, { PA_SCAN_VERT, PA_SCAN_VERT } },
#endif
#if ENA_GROW
{ true, { PA_GROW_UP, PA_GROW_UP } },
{ true, { PA_GROW_DOWN, PA_GROW_DOWN } },
#endif
#else // !INVERT_UPPER_ZONE
{ true, { PA_PRINT, PA_PRINT } },
{ false, { PA_SCROLL_LEFT, PA_SCROLL_LEFT } },
{ false, { PA_SCROLL_RIGHT, PA_SCROLL_RIGHT } },
{ true, { PA_SCROLL_UP, PA_SCROLL_DOWN } },
{ true, { PA_SCROLL_DOWN, PA_SCROLL_UP } },
#if ENA_MISC
{ true, { PA_SLICE, PA_SLICE } },
{ true, { PA_FADE, PA_FADE } },
{ true, { PA_MESH, PA_MESH } },
{ true, { PA_BLINDS, PA_BLINDS } },
{ true, { PA_DISSOLVE, PA_DISSOLVE } },
#endif
#if ENA_WIPE
{ true, { PA_WIPE, PA_WIPE } },
{ true, { PA_WIPE_CURSOR, PA_WIPE_CURSOR } },
#endif
#if ENA_OPNCLS
{ true, { PA_OPENING, PA_OPENING } },
{ true, { PA_OPENING_CURSOR, PA_OPENING_CURSOR } },
{ true, { PA_CLOSING, PA_CLOSING } },
{ true, { PA_CLOSING_CURSOR, PA_CLOSING_CURSOR } },
#endif
#if ENA_SCR_DIA
{ true, { PA_SCROLL_UP_LEFT, PA_SCROLL_DOWN_RIGHT } },
{ true, { PA_SCROLL_UP_RIGHT, PA_SCROLL_DOWN_LEFT } },
{ true, { PA_SCROLL_DOWN_LEFT, PA_SCROLL_UP_RIGHT } },
{ true, { PA_SCROLL_DOWN_RIGHT, PA_SCROLL_UP_LEFT } },
#endif
#if ENA_SCAN
{ true, { PA_SCAN_HORIZ, PA_SCAN_HORIZ } },
{ true, { PA_SCAN_VERT, PA_SCAN_VERT } },
#endif
#if ENA_GROW
{ true, { PA_GROW_UP, PA_GROW_DOWN } },
{ true, { PA_GROW_DOWN, PA_GROW_UP } },
#endif
#endif
};
void doUI(void)
{
// set the speed if it has changed
int16_t speed = map(analogRead(SPEED_IN), 0, 1023, 0, 100);
if ((speed >= ((int16_t)P.getSpeed() + SPEED_DEADBAND)) ||
(speed <= ((int16_t)P.getSpeed() - SPEED_DEADBAND)))
{
P.setSpeed(speed);
PRINT("\nChanged speed to ", P.getSpeed());
}
}
void setup(void)
{
uint8_t max = 0;
#if DEBUG
Serial.begin(57600);
#endif
PRINTS("\n[Double_Height_Test]");
PRINT("\nSize of catalogItem_t ", sizeof(catalogItem_t));
// work out the size of buffer required
for (uint8_t i = 0; i<ARRAY_SIZE(msgL); i++)
{
uint8_t l = strlen(msgL[i]);
if (l > max) max = l;
}
PRINT("\nAllocating memory: ", max + 2);
msgH = (char *)malloc(sizeof(char)*(max + 2));
// initialise the LED display
P.begin(MAX_ZONES);
// Set up zones for 2 halves of the display
P.setZone(ZONE_LOWER, 0, ZONE_SIZE - 1);
P.setZone(ZONE_UPPER, ZONE_SIZE, MAX_DEVICES-1);
P.setFont(BigFont);
P.setCharSpacing(P.getCharSpacing() * 2); // double height --> double spacing
#ifdef INVERT_UPPER_ZONE
P.setZoneEffect(ZONE_UPPER, true, PA_FLIP_UD);
P.setZoneEffect(ZONE_UPPER, true, PA_FLIP_LR);
#endif
}
void createHString(char *pH, char *pL)
{
for (; *pL != '\0'; pL++)
*pH++ = *pL | 0x80; // offset character
*pH = '\0'; // terminate the string
}
void loop(void)
{
static uint8_t idxMsg = 0; // message string index
static uint16_t idxCat = 0; // catalog item index
doUI();
P.displayAnimate();
if (P.getZoneStatus(ZONE_LOWER) && P.getZoneStatus(ZONE_UPPER))
{
catalogItem_t ci;
PRINT("\nC", idxCat);
PRINT(": M", idxMsg);
PRINT(": A ", (uint16_t)&catalog[idxCat]);
PRINT(": ", msgL[idxMsg]);
// copy the next catalog item into RAM
memcpy_P(&ci, &catalog[idxCat], sizeof(catalogItem_t));
// set up the ZONE_UPPER string
createHString(msgH, msgL[idxMsg]);
// renew and start the display
P.displayClear();
P.displayZoneText(ZONE_LOWER, msgL[idxMsg], ALIGN_LOWER,
P.getSpeed(), ci.fPause ? PAUSE_TIME : 0,
ci.zFX[ZONE_LOWER], ci.zFX[ZONE_LOWER]);
P.displayZoneText(ZONE_UPPER, msgH, ALIGN_UPPER,
P.getSpeed(), ci.fPause ? PAUSE_TIME : 0,
ci.zFX[ZONE_UPPER], ci.zFX[ZONE_UPPER]);
// prepare indices for next pass
idxMsg++;
if (idxMsg == ARRAY_SIZE(msgL))
{
idxMsg = 0;
idxCat++;
if (idxCat == ARRAY_SIZE(catalog))
idxCat = 0;
}
// synchronise the start and let the display run
P.synchZoneStart();
}
}

View File

@@ -0,0 +1,527 @@
// Data file for user example user defined fonts
#ifndef FONTDATA_H
#define FONTDATA_H
MD_MAX72XX::fontType_t BigFontLower[] PROGMEM =
{
0, // 0
0, // 1
0, // 2
0, // 3
0, // 4
0, // 5
0, // 6
0, // 7
0, // 8
0, // 9
0, // 10
0, // 11
0, // 12
0, // 13
0, // 14
0, // 15
0, // 16
0, // 17
0, // 18
0, // 19
0, // 20
0, // 21
0, // 22
0, // 23
0, // 24
0, // 25
0, // 26
0, // 27
0, // 28
0, // 29
0, // 30
0, // 31
4,0,0,0,0, // 32 - 'Space'
2,103,103, // 33 - '!'
6,0,0,0,0,0,0, // 34 - '"'
10,6,6,127,127,6,6,127,127,6,6, // 35 - '#'
10,48,112,97,97,255,255,97,115,63,30, // 36 - '$'
10,0,96,120,30,7,1,48,120,120,48, // 37 - '%'
10,30,63,115,97,97,103,63,28,126,102, // 38 - '&'
2,0,0, // 39 - '''
5,7,31,60,112,96, // 40 - '('
5,96,112,60,31,7, // 41 - ')'
10,3,3,1,0,15,15,0,1,3,3, // 42 - '*'
10,1,1,1,1,31,31,1,1,1,1, // 43 - '+'
2,96,224, // 44 - ','
10,1,1,1,1,1,1,1,1,1,1, // 45 - '-'
2,96,96, // 46 - '.'
8,96,120,30,7,1,0,0,0, // 47 - '/'
10,31,63,112,96,96,96,96,112,63,31, // 48 - '0'
10,0,0,96,96,127,127,96,96,0,0, // 49 - '1'
10,96,112,120,124,110,103,99,97,96,96, // 50 - '2'
10,24,56,112,96,96,97,97,113,63,30, // 51 - '3'
10,7,7,6,6,6,6,127,127,6,6, // 52 - '4'
10,24,56,112,96,96,96,96,112,63,31, // 53 - '5'
10,31,63,112,96,96,96,96,113,63,31, // 54 - '6'
10,0,0,0,127,127,1,0,0,0,0, // 55 - '7'
10,30,63,115,97,97,97,97,115,63,30, // 56 - '8'
10,0,0,97,97,113,57,29,15,7,3, // 57 - '9'
2,12,12, // 58 - ':'
2, 97,225, // 59 - ';'
8,1,3,7,14,28,56,112,96, // 60 - '<'
10,12,12,12,12,12,12,12,12,12,12, // 61 - '='
8,96,112,56,28,14,7,3,1, // 62 - '>'
10,0,0,0,0,111,111,1,0,0,0, // 63 - '?'
10,31,63,112,103,111,111,111,108,111,39, // 64 - '@'
10,127,127,6,6,6,6,6,6,127,127, // 65 - 'A'
10,127,127,97,97,97,97,97,115,63,30, // 66 - 'B'
10,31,63,96,96,96,96,96,112,56,24, // 67 - 'C'
10,127,127,96,96,96,96,96,112,63,31, // 68 - 'D'
10,127,127,97,97,97,97,97,97,96,96, // 69 - 'E'
10,127,127,1,1,1,1,1,1,0,0, // 70 - 'F'
10,31,63,112,96,96,96,97,113,63,31, // 71 - 'G'
10,127,127,1,1,1,1,1,1,127,127, // 72 - 'H'
6,96,96,127,127,96,96, // 73 - 'I'
8,24,56,112,96,96,112,63,31, // 74 - 'J'
10,127,127,3,3,7,14,28,56,112,96, // 75 - 'K'
10,127,127,96,96,96,96,96,96,96,96, // 76 - 'L'
10,127,127,0,0,0,0,0,0,127,127, // 77 - 'M'
10,127,127,0,0,1,7,28,48,127,127, // 78 - 'N'
10,31,63,112,96,96,96,96,112,63,31, // 79 - 'O'
10,127,127,1,1,1,1,1,1,0,0, // 80 - 'P'
10,31,63,112,96,96,108,124,56,127,111, // 81 - 'Q'
10,127,127,1,3,7,15,29,57,112,96, // 82 - 'R'
10,48,112,97,97,97,97,97,115,63,30, // 83 - 'S'
10,0,0,0,0,127,127,0,0,0,0, // 84 - 'T'
10,31,63,112,96,96,96,96,112,63,31, // 85 - 'U'
10,7,15,28,56,112,112,56,28,15,7, // 86 - 'V'
10,31,63,112,120,62,62,120,112,63,31, // 87 - 'W'
10,120,124,14,7,3,3,7,14,124,120, // 88 - 'X'
10,0,0,0,0,127,127,0,0,0,0, // 89 - 'Y'
10,120,124,110,103,99,97,96,96,96,96, // 90 - 'Z'
4,127,127,96,96, // 91 - '['
8,0,0,0,1,7,30,120,96, // 92 - '\'
4,96,96,127,127, // 93 - ']'
10,0,0,0,0,0,0,0,0,0,0, // 94 - '^'
10,192,192,192,192,192,192,192,192,192,192, // 95 - '_'
3,0,0,0, // 96 - '`'
10,24,60,102,102,102,102,102,102,127,63, // 97 - 'a'
10,127,127,96,96,96,96,96,112,63,31, // 98 - 'b'
10,31,63,112,96,96,96,96,112,57,25, // 99 - 'c'
10,31,63,112,96,96,96,96,96,127,127, // 100 - 'd'
10,31,63,118,102,102,102,102,118,55,19, // 101 - 'e'
7,1,127,127,1,1,0,0, // 102 - 'f'
10,35,103,238,204,204,204,204,236,127,63, // 103 - 'g'
10,127,127,0,0,0,0,0,0,127,127, // 104 - 'h'
2,127,127, // 105 - 'i'
8,24,56,112,96,96,112,63,31, // 106 - 'j'
8,127,127,14,15,31,57,112,96, // 107 - 'k'
6,96,96,127,127,96,96, // 108 - 'l'
10,127,127,0,0,127,127,0,0,127,127, // 109 - 'm'
10,127,127,1,1,0,0,0,0,127,127, // 110 - 'n'
10,31,63,112,96,96,96,96,112,63,31, // 111 - 'o'
10,255,255,24,24,24,24,24,28,15,7, // 112 - 'p'
10,7,15,28,24,24,24,24,24,255,255, // 113 - 'q'
10,127,127,3,1,0,0,0,0,1,1, // 114 - 'r'
10,49,115,102,102,102,102,102,126,60,24, // 115 - 's'
8,0,0,31,63,112,112,56,24, // 116 - 't'
10,31,63,112,96,96,96,96,112,63,31, // 117 - 'u'
10,7,15,28,56,112,112,56,28,15,7, // 118 - 'v'
10,31,63,112,112,62,62,112,112,63,31, // 119 - 'w'
10,96,112,57,31,15,15,31,57,112,96, // 120 - 'x'
10,3,7,206,204,204,204,204,236,127,63, // 121 - 'y'
10,96,112,120,124,110,103,99,97,96,96, // 122 - 'z'
6,1,3,31,62,112,96, // 123 - '{'
2,255,255, // 124 - '|'
6,96,112,62,31,3,1, // 125 - '}'
0, // 126
0, // 127
0, // 128
0, // 129
0, // 130
0, // 131
0, // 132
0, // 133
0, // 134
0, // 135
0, // 136
0, // 137
0, // 138
0, // 139
0, // 140
0, // 141
0, // 142
0, // 143
0, // 144
0, // 145
0, // 146
0, // 147
0, // 148
0, // 149
0, // 150
0, // 151
0, // 152
0, // 153
0, // 154
0, // 155
0, // 156
0, // 157
0, // 158
0, // 159
0, // 160
0, // 161
0, // 162
0, // 163
0, // 164
0, // 165
0, // 166
0, // 167
0, // 168
0, // 169
0, // 170
0, // 171
0, // 172
0, // 173
0, // 174
0, // 175
0, // 176
0, // 177
0, // 178
0, // 179
0, // 180
0, // 181
0, // 182
0, // 183
0, // 184
0, // 185
0, // 186
0, // 187
0, // 188
0, // 189
0, // 190
0, // 191
0, // 192
0, // 193
0, // 194
0, // 195
0, // 196
0, // 197
0, // 198
0, // 199
0, // 200
0, // 201
0, // 202
0, // 203
0, // 204
0, // 205
0, // 206
0, // 207
0, // 208
0, // 209
0, // 210
0, // 211
0, // 212
0, // 213
0, // 214
0, // 215
0, // 216
0, // 217
0, // 218
0, // 219
0, // 220
0, // 221
0, // 222
0, // 223
0, // 224
0, // 225
0, // 226
0, // 227
0, // 228
0, // 229
0, // 230
0, // 231
0, // 232
0, // 233
0, // 234
0, // 235
0, // 236
0, // 237
0, // 238
0, // 239
0, // 240
0, // 241
0, // 242
0, // 243
0, // 244
0, // 245
0, // 246
0, // 247
0, // 248
0, // 249
0, // 250
0, // 251
0, // 252
0, // 253
0, // 254
0, // 255
};
MD_MAX72XX::fontType_t BigFontUpper[] PROGMEM =
{
0, // 0
0, // 1
0, // 2
0, // 3
0, // 4
0, // 5
0, // 6
0, // 7
0, // 8
0, // 9
0, // 10
0, // 11
0, // 12
0, // 13
0, // 14
0, // 15
0, // 16
0, // 17
0, // 18
0, // 19
0, // 20
0, // 21
0, // 22
0, // 23
0, // 24
0, // 25
0, // 26
0, // 27
0, // 28
0, // 29
0, // 30
0, // 31
4,0,0,0,0, // 32 - 'Space'
2,254,254, // 33 - '!'
6,14,14,0,0,14,14, // 34 - '"'
10,96,96,254,254,96,96,254,254,96,96, // 35 - '#'
10,120,252,206,134,255,255,134,134,14,12, // 36 - '$'
10,12,30,30,12,128,224,120,30,6,0, // 37 - '%'
10,0,0,152,252,230,230,60,24,0,0, // 38 - '&'
2,14,14, // 39 - '''
5,224,248,60,14,6, // 40 - '('
5,6,14,60,248,224, // 41 - ')'
10,24,184,240,224,254,254,224,240,184,24, // 42 - '*'
10,128,128,128,128,248,248,128,128,128,128, // 43 - '+'
2,0,0, // 44 - ','
10,128,128,128,128,128,128,128,128,128,128, // 45 - '-'
2,0,0, // 46 - '.'
8,0,0,0,128,224,120,30,6, // 47 - '/'
10,248,252,14,6,6,6,6,14,252,248, // 48 - '0'
10,0,0,24,28,254,254,0,0,0,0, // 49 - '1'
10,24,28,14,6,6,6,134,206,252,120, // 50 - '2'
10,24,28,14,6,6,134,134,142,252,120, // 51 - '3'
10,128,192,224,112,56,28,254,254,0,0, // 52 - '4'
10,126,126,102,102,102,102,102,230,198,134, // 53 - '5'
10,248,252,198,198,198,198,198,198,140,8, // 54 - '6'
10,6,6,6,6,134,198,230,118,62,30, // 55 - '7'
10,56,124,206,134,134,134,134,206,124,56, // 56 - '8'
10,120,252,206,134,134,134,134,206,252,248, // 57 - '9'
2,48,48, // 58 - ':'
2,128,128, // 59 - ';'
8,128,192,224,112,56,28,14,6, // 60 - '<'
10,48,48,48,48,48,48,48,48,48,48, // 61 - '='
8,6,14,28,56,112,224,192,128, // 62 - '>'
10,24,28,14,6,6,134,134,206,252,120, // 63 - '?'
10,248,252,14,230,246,246,230,14,252,248, // 64 - '@'
10,248,252,14,6,6,6,6,14,252,248, // 65 - 'A'
10,254,254,134,134,134,134,134,206,252,120, // 66 - 'B'
10,248,252,6,6,6,6,6,14,28,24, // 67 - 'C'
10,254,254,6,6,6,6,6,14,252,248, // 68 - 'D'
10,254,254,134,134,134,134,134,134,6,6, // 69 - 'E'
10,254,254,134,134,134,134,134,134,6,6, // 70 - 'F'
10,248,252,14,6,6,6,134,142,156,152, // 71 - 'G'
10,254,254,128,128,128,128,128,128,254,254, // 72 - 'H'
6,6,6,254,254,6,6, // 73 - 'I'
8,6,6,6,6,6,6,254,254, // 74 - 'J'
10,254,254,192,192,224,112,56,28,14,6, // 75 - 'K'
10,254,254,0,0,0,0,0,0,0,0, // 76 - 'L'
10,254,254,28,56,240,240,56,28,254,254, // 77 - 'M'
10,254,254,28,112,192,0,0,0,254,254, // 78 - 'N'
10,248,252,14,6,6,6,6,14,252,248, // 79 - 'O'
10,254,254,134,134,134,134,134,206,252,120, // 80 - 'P'
10,248,252,14,6,6,6,6,14,252,248, // 81 - 'Q'
10,254,254,134,134,134,134,134,206,252,120, // 82 - 'R'
10,120,252,206,134,134,134,134,134,14,12, // 83 - 'S'
10,6,6,6,6,254,254,6,6,6,6, // 84 - 'T'
10,254,254,0,0,0,0,0,0,254,254, // 85 - 'U'
10,254,254,0,0,0,0,0,0,254,254, // 86 - 'V'
10,254,254,0,0,0,0,0,0,254,254, // 87 - 'W'
10,30,62,48,224,192,192,224,112,62,30, // 88 - 'X'
10,30,62,112,224,192,192,224,112,62,30, // 89 - 'Y'
10,6,6,6,6,134,198,230,118,62,30, // 90 - 'Z'
4,254,254,6,6, // 91 - '['
8,6,30,120,224,128,0,0,0, // 92 - '\'
4,6,6,254,254, // 93 - ']'
10,96,112,56,28,14,14,28,56,112,96, // 94 - '^'
10,0,0,0,0,0,0,0,0,0,0, // 95 - '_'
3,6,30,24, // 96 - '`'
10,0,192,224,96,96,96,96,224,192,128, // 97 - 'a'
10,254,254,96,96,96,96,96,224,192,128, // 98 - 'b'
10,128,192,224,96,96,96,96,224,192,128, // 99 - 'c'
10,128,192,224,96,96,96,96,96,254,254, // 100 - 'd'
10,128,192,224,96,96,96,96,224,192,128, // 101 - 'e'
7,128,248,252,142,142,28,24, // 102 - 'f'
10,128,192,224,96,96,96,96,96,224,224, // 103 - 'g'
10,254,254,96,96,96,96,96,224,192,128, // 104 - 'h'
2,236,236, // 105 - 'i'
8,0,0,0,0,0,0,230,230, // 106 - 'j'
8,254,254,0,0,128,192,224,96, // 107 - 'k'
6,6,6,254,254,0,0, // 108 - 'l'
10,224,224,96,96,224,224,96,96,224,192, // 109 - 'm'
10,224,224,128,192,224,96,96,224,192,128, // 110 - 'n'
10,128,192,224,96,96,96,96,224,192,128, // 111 - 'o'
10,224,224,96,96,96,96,96,224,192,128, // 112 - 'p'
10,128,192,224,96,96,96,96,96,224,224, // 113 - 'q'
10,224,224,128,192,224,96,96,224,192,128, // 114 - 'r'
10,128,192,96,96,96,96,96,96,192,192, // 115 - 's'
8,96,96,254,254,96,96,96,96, // 116 - 't'
10,224,224,0,0,0,0,0,0,224,224, // 117 - 'u'
10,224,224,0,0,0,0,0,0,224,224, // 118 - 'v'
10,224,224,0,0,0,0,0,0,224,224, // 119 - 'w'
10,96,224,192,128,0,0,128,192,224,96, // 120 - 'x'
10,224,224,0,0,0,0,0,0,224,224, // 121 - 'y'
10,96,96,96,96,96,96,224,224,224,96, // 122 - 'z'
6,128,192,248,124,14,6, // 123 - '{'
2,255,255, // 124 - '|'
6,6,14,124,248,192,128, // 125 - '}'
0, // 126
0, // 127
0, // 128
0, // 129
0, // 130
0, // 131
0, // 132
0, // 133
0, // 134
0, // 135
0, // 136
0, // 137
0, // 138
0, // 139
0, // 140
0, // 141
0, // 142
0, // 143
0, // 144
0, // 145
0, // 146
0, // 147
0, // 148
0, // 149
0, // 150
0, // 151
0, // 152
0, // 153
0, // 154
0, // 155
0, // 156
0, // 157
0, // 158
0, // 159
0, // 160
0, // 161
0, // 162
0, // 163
0, // 164
0, // 165
0, // 166
0, // 167
0, // 168
0, // 169
0, // 170
0, // 171
0, // 172
0, // 173
0, // 174
0, // 175
0, // 176
0, // 177
0, // 178
0, // 179
0, // 180
0, // 181
0, // 182
0, // 183
0, // 184
0, // 185
0, // 186
0, // 187
0, // 188
0, // 189
0, // 190
0, // 191
0, // 192
0, // 193
0, // 194
0, // 195
0, // 196
0, // 197
0, // 198
0, // 199
0, // 200
0, // 201
0, // 202
0, // 203
0, // 204
0, // 205
0, // 206
0, // 207
0, // 208
0, // 209
0, // 210
0, // 211
0, // 212
0, // 213
0, // 214
0, // 215
0, // 216
0, // 217
0, // 218
0, // 219
0, // 220
0, // 221
0, // 222
0, // 223
0, // 224
0, // 225
0, // 226
0, // 227
0, // 228
0, // 229
0, // 230
0, // 231
0, // 232
0, // 233
0, // 234
0, // 235
0, // 236
0, // 237
0, // 238
0, // 239
0, // 240
0, // 241
0, // 242
0, // 243
0, // 244
0, // 245
0, // 246
0, // 247
0, // 248
0, // 249
0, // 250
0, // 251
0, // 252
0, // 253
0, // 254
0, // 255
};
#endif

View File

@@ -0,0 +1,160 @@
// Demonstrates one way to create a double height display using Parola.
//
// Largely based on code shared by arduino.cc forum user Arek00, 26 Sep 2015.
// Video of running display can be seen at https://www.youtube.com/watch?v=7nPCIMVUo5g
//
// The upper and lower portions are managed as 2 zones 'stacked' on top of each other
// so that the module numbers are in the sequence shown below:
//
// * Modules (like FC-16) that can fit over each other with no gap
// n n-1 n-2 ... n/2+1 <- this direction top row
// n/2 ... 3 2 1 0 <- this direction bottom row
//
// * Modules (like Generic and Parola) that cannot fit over each other with no gap
// n/2+1 ... n-2 n-1 n -> this direction top row
// n/2 ... 3 2 1 0 <- this direction bottom row
//
// Each font displays letters for either top or bottom half of the message. Sending the
// same string to both zones creates the complete message
// on the display.
//
// NOTE: MD_MAX72xx library must be installed and confugured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include "Font_Data.h"
#if USE_GENERIC_HW || USE_PAROLA_HW
#define INVERT_UPPER_ZONE
#endif
#define DEBUG 0
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_ZONES 2
#define ZONE_SIZE 4
#define MAX_DEVICES (MAX_ZONES * ZONE_SIZE)
#define SCROLL_SPEED 30
#define ZONE_UPPER 1
#define ZONE_LOWER 0
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// HARDWARE SPI
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
char *msg[] =
{
"Create double height displays using 2 custom fonts and 2 zones",
"Zone 0 for lower half",
"Zone 1 for upper half",
"BIG",
"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
"abcdefghijklmnopqrstuvwxyz",
"0123456789",
"`!@#$%^&*()_+-={};:'\"<>?,./|\\{}",
"Download Parola at github.com/MajicDesigns",
"Watch the video on YouTube"
};
void setup(void)
{
// initialise the LED display
P.begin(MAX_ZONES);
// Set up zones for 2 halves of the display
// Each zone gets a different font, making up the top
// and bottom half of each letter
P.setZone(ZONE_LOWER, 0, ZONE_SIZE - 1);
P.setFont(ZONE_LOWER, BigFontLower);
P.setZone(ZONE_UPPER, ZONE_SIZE, MAX_DEVICES-1);
P.setFont(ZONE_UPPER, BigFontUpper);
P.setCharSpacing(P.getCharSpacing() * 2); // double height --> double spacing
#ifdef INVERT_UPPER_ZONE
P.setZoneEffect(ZONE_UPPER, true, PA_FLIP_UD);
P.setZoneEffect(ZONE_UPPER, true, PA_FLIP_LR);
#endif
#if DEBUG
Serial.begin(57600);
Serial.println("[Double Height demo start]");
#endif
}
void loop(void)
{
static uint8_t cycle = 0;
// Run the animation and then check if BOTH zones have
// completed. The animations are not the same length due
// to upper/lower effects being displayed differently.
P.displayAnimate();
if (P.getZoneStatus(ZONE_LOWER) && P.getZoneStatus(ZONE_UPPER))
{
#if DEBUG
Serial.println(cycle);
#endif
switch (cycle)
{
default:
P.setFont(ZONE_LOWER, BigFontLower);
P.setFont(ZONE_UPPER, BigFontUpper);
#ifdef INVERT_UPPER_ZONE
P.displayZoneText(ZONE_LOWER, msg[cycle], PA_LEFT, SCROLL_SPEED, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
P.displayZoneText(ZONE_UPPER, msg[cycle], PA_LEFT, SCROLL_SPEED, 0, PA_SCROLL_RIGHT, PA_SCROLL_RIGHT);
#else
P.displayZoneText(ZONE_LOWER, msg[cycle], PA_RIGHT, SCROLL_SPEED, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
P.displayZoneText(ZONE_UPPER, msg[cycle], PA_LEFT, SCROLL_SPEED, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
#endif
break;
case 1:
P.setFont(ZONE_LOWER, NULL);
P.setFont(ZONE_UPPER, BigFontUpper);
P.displayZoneText(ZONE_LOWER, msg[1], PA_CENTER, SCROLL_SPEED, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
P.displayZoneText(ZONE_UPPER, msg[3], PA_CENTER, SCROLL_SPEED, 0, PA_PRINT, PA_NO_EFFECT);
break;
case 2:
P.setFont(ZONE_LOWER, BigFontLower);
P.setFont(ZONE_UPPER, NULL);
P.displayZoneText(ZONE_LOWER, msg[3], PA_CENTER, SCROLL_SPEED, 0, PA_PRINT, PA_NO_EFFECT);
#ifdef INVERT_UPPER_ZONE
P.displayZoneText(ZONE_UPPER, msg[2], PA_CENTER, SCROLL_SPEED, 0, PA_SCROLL_RIGHT, PA_SCROLL_RIGHT);
#else
P.displayZoneText(ZONE_UPPER, msg[2], PA_CENTER, SCROLL_SPEED, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
#endif
break;
case 3:
P.setFont(ZONE_LOWER, BigFontLower);
P.setFont(ZONE_UPPER, BigFontUpper);
P.displayZoneText(ZONE_LOWER, msg[3], PA_CENTER, SCROLL_SPEED, 2000, PA_PRINT, PA_NO_EFFECT); // PA_SCROLL_LEFT, PA_SCROLL_LEFT);
P.displayZoneText(ZONE_UPPER, msg[3], PA_CENTER, SCROLL_SPEED, 2000, PA_PRINT, PA_NO_EFFECT); //PA_SCROLL_RIGHT, PA_SCROLL_RIGHT);
break;
}
// prepare for next pass
cycle = (cycle + 1) % ARRAY_SIZE(msg);
// synchronise the start
P.displayClear();
P.synchZoneStart();
}
}

View File

@@ -0,0 +1,529 @@
// Data file for user example user defined fonts
// руские большие и маленькие
#ifndef FONTDATA_H
#define FONTDATA_H
const uint8_t BigFontLower[] PROGMEM =
{
0, // 0
0, // 1
0, // 2
0, // 3
0, // 4
0, // 5
0, // 6
0, // 7
0, // 8
0, // 9
0, // 10
0, // 11
0, // 12
0, // 13
0, // 14
0, // 15
0, // 16
0, // 17
0, // 18
0, // 19
0, // 20
0, // 21
0, // 22
0, // 23
0, // 24
0, // 25
0, // 26
0, // 27
0, // 28
0, // 29
0, // 30
0, // 31
4,0,0,0,0, // 32 - 'Space'
2,103,103, // 33 - '!'
6,0,0,0,0,0,0, // 34 - '"'
10,6,6,127,127,6,6,127,127,6,6, // 35 - '#'
10,48,112,97,97,255,255,97,115,63,30, // 36 - '$'
10,0,96,120,30,7,1,48,120,120,48, // 37 - '%'
10,30,63,115,97,97,103,63,28,126,102, // 38 - '&'
2,0,0, // 39 - '''
5,7,31,60,112,96, // 40 - '('
5,96,112,60,31,7, // 41 - ')'
10,3,3,1,0,15,15,0,1,3,3, // 42 - '*'
10,1,1,1,1,31,31,1,1,1,1, // 43 - '+'
2,96,224, // 44 - ','
10,1,1,1,1,1,1,1,1,1,1, // 45 - '-'
2,96,96, // 46 - '.'
8,96,120,30,7,1,0,0,0, // 47 - '/'
10,31,63,112,96,96,96,96,112,63,31, // 48 - '0'
6,96,96,127,127,96,96, // 49 - '1' //
10,96,112,120,124,110,103,99,97,96,96, // 50 - '2'
10,24,56,112,96,96,97,97,113,63,30, // 51 - '3'
10,7,7,6,6,6,6,127,127,6,6, // 52 - '4'
10,24,56,112,96,96,96,96,112,63,31, // 53 - '5'
10,31,63,112,96,96,96,96,113,63,31, // 54 - '6'
10,0,0,0,127,127,1,0,0,0,0, // 55 - '7'
10,30,63,115,97,97,97,97,115,63,30, // 56 - '8'
10,0,0,97,97,113,57,29,15,7,3, // 57 - '9'
2,12,12, // 58 - ':'
2, 97,225, // 59 - ';'
8,1,3,7,14,28,56,112,96, // 60 - '<'
10,12,12,12,12,12,12,12,12,12,12, // 61 - '='
8,96,112,56,28,14,7,3,1, // 62 - '>'
10,0,0,0,0,111,111,1,0,0,0, // 63 - '?'
10,31,63,112,103,111,111,111,108,111,39, // 64 - '@'
10,127,127,6,6,6,6,6,6,127,127, // 65 - 'A'
10,127,127,97,97,97,97,97,115,63,30, // 66 - 'B'
10,31,63,96,96,96,96,96,112,56,24, // 67 - 'C'
10,127,127,96,96,96,96,96,112,63,31, // 68 - 'D'
10,127,127,97,97,97,97,97,97,96,96, // 69 - 'E'
10,127,127,1,1,1,1,1,1,0,0, // 70 - 'F'
10,31,63,112,96,96,96,97,113,63,31, // 71 - 'G'
10,127,127,1,1,1,1,1,1,127,127, // 72 - 'H'
6,96,96,127,127,96,96, // 73 - 'I'
8,24,56,112,96,96,112,63,31, // 74 - 'J'
10,127,127,3,3,7,14,28,56,112,96, // 75 - 'K'
10,127,127,96,96,96,96,96,96,96,96, // 76 - 'L'
10,127,127,0,0,0,0,0,0,127,127, // 77 - 'M'
10,127,127,0,0,1,7,28,48,127,127, // 78 - 'N'
10,31,63,112,96,96,96,96,112,63,31, // 79 - 'O'
10,127,127,1,1,1,1,1,1,0,0, // 80 - 'P'
10,31,63,112,96,96,108,124,56,127,111, // 81 - 'Q'
10,127,127,1,3,7,15,29,57,112,96, // 82 - 'R'
10,48,112,97,97,97,97,97,115,63,30, // 83 - 'S'
10,0,0,0,0,127,127,0,0,0,0, // 84 - 'T'
10,31,63,112,96,96,96,96,112,63,31, // 85 - 'U'
10,7,15,28,56,112,112,56,28,15,7, // 86 - 'V'
10,31,63,112,120,62,62,120,112,63,31, // 87 - 'W'
10,120,124,14,7,3,3,7,14,124,120, // 88 - 'X'
10,0,0,0,0,127,127,0,0,0,0, // 89 - 'Y'
10,120,124,110,103,99,97,96,96,96,96, // 90 - 'Z'
4,127,127,96,96, // 91 - '['
8,0,0,0,1,7,30,120,96, // 92 - '\'
4,96,96,127,127, // 93 - ']'
10,0,0,0,0,0,0,0,0,0,0, // 94 - '^'
10,192,192,192,192,192,192,192,192,192,192, // 95 - '_'
3,0,0,0, // 96 - '`'
10,24,60,102,102,102,102,102,102,127,63, // 97 - 'a'
10,127,127,96,96,96,96,96,112,63,31, // 98 - 'b'
10,31,63,112,96,96,96,96,112,57,25, // 99 - 'c'
10,31,63,112,96,96,96,96,96,127,127, // 100 - 'd'
10,31,63,118,102,102,102,102,118,55,19, // 101 - 'e'
7,1,127,127,1,1,0,0, // 102 - 'f'
10,35,103,238,204,204,204,204,236,127,63, // 103 - 'g'
10,127,127,0,0,0,0,0,0,127,127, // 104 - 'h'
2,127,127, // 105 - 'i'
8,24,56,112,96,96,112,63,31, // 106 - 'j'
8,127,127,14,15,31,57,112,96, // 107 - 'k'
6,96,96,127,127,96,96, // 108 - 'l'
10,127,127,0,0,127,127,0,0,127,127, // 109 - 'm'
10,127,127,1,1,0,0,0,0,127,127, // 110 - 'n'
10,31,63,112,96,96,96,96,112,63,31, // 111 - 'o'
10,255,255,24,24,24,24,24,28,15,7, // 112 - 'p'
10,7,15,28,24,24,24,24,24,255,255, // 113 - 'q'
10,127,127,3,1,0,0,0,0,1,1, // 114 - 'r'
10,49,115,102,102,102,102,102,126,60,24, // 115 - 's'
8,0,0,31,63,112,112,56,24, // 116 - 't'
10,31,63,112,96,96,96,96,112,63,31, // 117 - 'u'
10,7,15,28,56,112,112,56,28,15,7, // 118 - 'v'
10,31,63,112,112,62,62,112,112,63,31, // 119 - 'w'
10,96,112,57,31,15,15,31,57,112,96, // 120 - 'x'
10,3,7,206,204,204,204,204,236,127,63, // 121 - 'y'
10,96,112,120,124,110,103,99,97,96,96, // 122 - 'z'
6,1,3,31,62,112,96, // 123 - '{'
2,255,255, // 124 - '|'
6,96,112,62,31,3,1, // 125 - '}'
0, // 126
0, // 127
8, 255, 255, 12, 12, 12, 14, 7, 3, // 128 - 'р' //Low
8, 63, 127, 224, 192, 192, 224, 112, 48, // 129 - 'с' //Low
8, 0, 0, 0, 255, 255, 0, 0, 0, // 130 - 'т' //Low
8, 35, 103, 198, 198, 198, 198, 127, 63, // 131 - 'у' //Low
10, 15, 31, 56, 48, 255, 255, 48, 56, 31, 15, // 132 - 'ф' //Low
8, 240, 248, 13, 7, 7, 13, 248, 240, // 133 - 'х' //Low
8, 127, 127, 96, 96, 96, 255, 255, 192, // 134 - 'ц' //Low
8, 3, 7, 14, 12, 12, 12, 255, 255, // 135 - 'ч' //Low
10, 255, 255, 192, 192, 255, 255, 192, 192, 255, 255, // 136 - 'ш' //Low
10, 127, 127, 96, 96, 127, 127, 96, 224, 255, 255, // 137 - 'щ' //Low
8, 0, 255, 255, 195, 195, 231, 126, 60, // 138 - 'ъ' //Low
10, 255, 255, 195, 195, 231, 126, 60, 0, 255, 255, // 139 - 'ы' //Low
8, 255, 255, 195, 195, 195, 231, 126, 60, // 140 - 'ь' //Low
8, 48, 112, 224, 192, 198, 230, 127, 63, // 141 - 'э' //Low
10, 255, 255, 6, 63, 127, 224, 192, 224, 127, 63, // 142 - 'ю' //Low
8, 131, 199, 110, 60, 28, 12, 255, 255, // 143 - 'я' //Low
8, 255, 255, 6, 6, 6, 6, 255, 255, // 144 - 'А' //Low
8, 255, 255, 192, 192, 192, 225, 127, 63, // 145 - 'Б' //Low
8, 255, 255, 192, 192, 192, 225, 127, 63, // 146 - 'В' //Low
6, 255, 255, 0, 0, 0, 0, // 147 - 'Г' //Low
10, 224, 255, 127, 96, 96, 96, 96, 127, 255, 224, // 148 - 'Д' //Low
6, 255, 255, 193, 193, 193, 192, // 149 - 'Е' //Low
10, 252, 254, 3, 1, 255, 255, 1, 3, 254, 252, // 150 - 'Ж' //Low
8, 56, 120, 224, 192, 192, 225, 127, 63, // 151 - 'З' //Low
8, 255, 255, 56, 28, 14, 7, 255, 255, // 152 - 'И' //Low
8, 255, 255, 56, 28, 14, 7, 255, 255, // 153 - 'Й' //Low
8, 255, 255, 1, 3, 6, 12, 248, 240, // 154 - 'К' //Low
8, 192, 255, 127, 0, 0, 0, 255, 255, // 155 - 'Л' //Low
10, 255, 255, 0, 3, 63, 63, 3, 0, 255, 255, // 156 - 'М' //Low
8, 255, 255, 1, 1, 1, 1, 255, 255, // 157 - 'Н' //Low
8, 63, 127, 224, 192, 192, 224, 127, 63, // 158 - 'О' //Low
8, 255, 255, 0, 0, 0, 0, 255, 255, // 159 - 'П' //Low
8, 255, 255, 6, 6, 6, 7, 3, 1, // 160 - 'Р' //Low
8, 63, 127, 224, 192, 192, 224, 120, 56, // 161 - 'С' //Low
8, 0, 0, 0, 255, 255, 0, 0, 0, // 162 - 'Т' //Low
8, 48, 112, 224, 193, 195, 230, 127, 63, // 163 - 'У' //Low
10, 15, 31, 56, 48, 255, 255, 48, 56, 31, 15, // 164 - 'Ф' //Low
8, 248, 252, 14, 3, 3, 6, 252, 248, // 165 - 'Х' //Low
8, 127, 127, 96, 96, 96, 127, 255, 224, // 166 - 'Ц' //Low
8, 1, 3, 7, 6, 6, 6, 255, 255, // 167 - 'Ч' //Low
10, 255, 255, 224, 224, 255, 255, 224, 224, 255, 255, // 168 - 'Ш' //Low
10, 127, 127, 112, 112, 127, 127, 112, 240, 255, 255, // 169 - 'Щ' //Low
8, 0, 255, 255, 192, 192, 225, 127, 63, // 170 - 'Ъ' //Low
10, 255, 255, 192, 192, 225, 127, 63, 0, 255, 255, // 171 - 'Ы' //Low
8, 255, 255, 192, 192, 192, 224, 127, 63, // 172 - 'Ь' //Low
8, 48, 112, 224, 193, 193, 225, 127, 63, // 173 - 'Э' //Low
10, 255, 255, 1, 63, 127, 224, 192, 224, 127, 63, // 174 - 'Ю' //Low
8, 192, 225, 115, 59, 31, 15, 255, 255, // 175 - 'Я' //Low
8, 56, 124, 238, 198, 198, 255, 255, 192, // 176 - 'а' //Low
8, 255, 255, 195, 195, 195, 231, 126, 60, // 177 - 'б' //Low
7, 255, 255, 198, 199, 237, 124, 56, // 178 - 'в' //Low
6, 255, 255, 0, 0, 0, 0, // 179 - 'г' //Low
8, 224, 255, 127, 96, 96, 127, 255, 224, // 180 - 'д' //Low
8, 63, 127, 230, 198, 198, 230, 103, 35, // 181 - 'е' //Low
10, 240, 248, 13, 6, 255, 255, 6, 13, 248, 240, // 182 - 'ж' //Low
8, 48, 112, 224, 194, 198, 239, 125, 56, // 183 - 'з' //Low
8, 255, 255, 96, 48, 24, 12, 255, 255, // 184 - 'и' //Low
8, 255, 255, 96, 48, 24, 12, 255, 255, // 185 - 'й' //Low
8, 255, 255, 6, 7, 13, 24, 240, 224, // 186 - 'к' //Low
8, 192, 240, 28, 7, 1, 0, 255, 255, // 187 - 'л' //Low
10, 255, 255, 3, 14, 120, 120, 14, 3, 255, 255, // 188 - 'м' //Low
8, 255, 255, 6, 6, 6, 6, 255, 255, // 189 - 'н' //Low
8, 63, 127, 224, 192, 192, 224, 127, 63, // 190 - 'о' //Low
8, 255, 255, 0, 0, 0, 0, 255, 255, // 191 - 'п' //Low
0, // 192
0, // 193
0, // 194
0, // 195
0, // 196
0, // 197
0, // 198
0, // 199
0, // 200
0, // 201
0, // 202
0, // 203
0, // 204
0, // 205
0, // 206
0, // 207
0, // 208
0, // 209
0, // 210
0, // 211
0, // 212
0, // 213
0, // 214
0, // 215
0, // 216
0, // 217
0, // 218
0, // 219
0, // 220
0, // 221
0, // 222
0, // 223
0, // 224
0, // 225
0, // 226
0, // 227
0, // 228
0, // 229
0, // 230
0, // 231
0, // 232
0, // 233
0, // 234
0, // 235
0, // 236
0, // 237
0, // 238
0, // 239
0, // 240
0, // 241
0, // 242
0, // 243
0, // 244
0, // 245
0, // 246
0, // 247
0, // 248
0, // 249
0, // 250
0, // 251
0, // 252
0, // 253
0, // 254
0, // 255
};
const uint8_t BigFontUpper[] PROGMEM =
{
0, // 0
0, // 1
0, // 2
0, // 3
0, // 4
0, // 5
0, // 6
0, // 7
0, // 8
0, // 9
0, // 10
0, // 11
0, // 12
0, // 13
0, // 14
0, // 15
0, // 16
0, // 17
0, // 18
0, // 19
0, // 20
0, // 21
0, // 22
0, // 23
0, // 24
0, // 25
0, // 26
0, // 27
0, // 28
0, // 29
0, // 30
0, // 31
4,0,0,0,0, // 32 - 'Space'
2,254,254, // 33 - '!'
6,14,14,0,0,14,14, // 34 - '"'
10,96,96,254,254,96,96,254,254,96,96, // 35 - '#'
10,120,252,206,134,255,255,134,134,14,12, // 36 - '$'
10,12,30,30,12,128,224,120,30,6,0, // 37 - '%'
10,0,0,152,252,230,230,60,24,0,0, // 38 - '&'
2,14,14, // 39 - '''
5,224,248,60,14,6, // 40 - '('
5,6,14,60,248,224, // 41 - ')'
10,24,184,240,224,254,254,224,240,184,24, // 42 - '*'
10,128,128,128,128,248,248,128,128,128,128, // 43 - '+'
2,0,0, // 44 - ','
10,128,128,128,128,128,128,128,128,128,128, // 45 - '-'
2,0,0, // 46 - '.'
8,0,0,0,128,224,120,30,6, // 47 - '/'
10,248,252,14,6,6,6,6,14,252,248, // 48 - '0'
6,24,28,254,254,0,0, // 49 - '1'
10,24,28,14,6,6,6,134,206,252,120, // 50 - '2'
10,24,28,14,6,6,134,134,142,252,120, // 51 - '3'
10,128,192,224,112,56,28,254,254,0,0, // 52 - '4'
10,126,126,102,102,102,102,102,230,198,134, // 53 - '5'
10,248,252,198,198,198,198,198,198,140,8, // 54 - '6'
10,6,6,6,6,134,198,230,118,62,30, // 55 - '7'
10,56,124,206,134,134,134,134,206,124,56, // 56 - '8'
10,120,252,206,134,134,134,134,206,252,248, // 57 - '9'
2,48,48, // 58 - ':'
2,128,128, // 59 - ';'
8,128,192,224,112,56,28,14,6, // 60 - '<'
10,48,48,48,48,48,48,48,48,48,48, // 61 - '='
8,6,14,28,56,112,224,192,128, // 62 - '>'
10,24,28,14,6,6,134,134,206,252,120, // 63 - '?'
10,248,252,14,230,246,246,230,14,252,248, // 64 - '@'
10,248,252,14,6,6,6,6,14,252,248, // 65 - 'A'
10,254,254,134,134,134,134,134,206,252,120, // 66 - 'B'
10,248,252,6,6,6,6,6,14,28,24, // 67 - 'C'
10,254,254,6,6,6,6,6,14,252,248, // 68 - 'D'
10,254,254,134,134,134,134,134,134,6,6, // 69 - 'E'
10,254,254,134,134,134,134,134,134,6,6, // 70 - 'F'
10,248,252,14,6,6,6,134,142,156,152, // 71 - 'G'
10,254,254,128,128,128,128,128,128,254,254, // 72 - 'H'
6,6,6,254,254,6,6, // 73 - 'I'
8,6,6,6,6,6,6,254,254, // 74 - 'J'
10,254,254,192,192,224,112,56,28,14,6, // 75 - 'K'
10,254,254,0,0,0,0,0,0,0,0, // 76 - 'L'
10,254,254,28,56,240,240,56,28,254,254, // 77 - 'M'
10,254,254,28,112,192,0,0,0,254,254, // 78 - 'N'
10,248,252,14,6,6,6,6,14,252,248, // 79 - 'O'
10,254,254,134,134,134,134,134,206,252,120, // 80 - 'P'
10,248,252,14,6,6,6,6,14,252,248, // 81 - 'Q'
10,254,254,134,134,134,134,134,206,252,120, // 82 - 'R'
10,120,252,206,134,134,134,134,134,14,12, // 83 - 'S'
10,6,6,6,6,254,254,6,6,6,6, // 84 - 'T'
10,254,254,0,0,0,0,0,0,254,254, // 85 - 'U'
10,254,254,0,0,0,0,0,0,254,254, // 86 - 'V'
10,254,254,0,0,0,0,0,0,254,254, // 87 - 'W'
10,30,62,48,224,192,192,224,112,62,30, // 88 - 'X'
10,30,62,112,224,192,192,224,112,62,30, // 89 - 'Y'
10,6,6,6,6,134,198,230,118,62,30, // 90 - 'Z'
4,254,254,6,6, // 91 - '['
8,6,30,120,224,128,0,0,0, // 92 - '\'
4,6,6,254,254, // 93 - ']'
10,96,112,56,28,14,14,28,56,112,96, // 94 - '^'
10,0,0,0,0,0,0,0,0,0,0, // 95 - '_'
3,6,30,24, // 96 - '`'
10,0,192,224,96,96,96,96,224,192,128, // 97 - 'a'
10,254,254,96,96,96,96,96,224,192,128, // 98 - 'b'
10,128,192,224,96,96,96,96,224,192,128, // 99 - 'c'
10,128,192,224,96,96,96,96,96,254,254, // 100 - 'd'
10,128,192,224,96,96,96,96,224,192,128, // 101 - 'e'
7,128,248,252,142,142,28,24, // 102 - 'f'
10,128,192,224,96,96,96,96,96,224,224, // 103 - 'g'
10,254,254,96,96,96,96,96,224,192,128, // 104 - 'h'
2,236,236, // 105 - 'i'
8,0,0,0,0,0,0,230,230, // 106 - 'j'
8,254,254,0,0,128,192,224,96, // 107 - 'k'
6,6,6,254,254,0,0, // 108 - 'l'
10,224,224,96,96,224,224,96,96,224,192, // 109 - 'm'
10,224,224,128,192,224,96,96,224,192,128, // 110 - 'n'
10,128,192,224,96,96,96,96,224,192,128, // 111 - 'o'
10,224,224,96,96,96,96,96,224,192,128, // 112 - 'p'
10,128,192,224,96,96,96,96,96,224,224, // 113 - 'q'
10,224,224,128,192,224,96,96,224,192,128, // 114 - 'r'
10,128,192,96,96,96,96,96,96,192,192, // 115 - 's'
8,96,96,254,254,96,96,96,96, // 116 - 't'
10,224,224,0,0,0,0,0,0,224,224, // 117 - 'u'
10,224,224,0,0,0,0,0,0,224,224, // 118 - 'v'
10,224,224,0,0,0,0,0,0,224,224, // 119 - 'w'
10,96,224,192,128,0,0,128,192,224,96, // 120 - 'x'
10,224,224,0,0,0,0,0,0,224,224, // 121 - 'y'
10,96,96,96,96,96,96,224,224,224,96, // 122 - 'z'
6,128,192,248,124,14,6, // 123 - '{'
2,255,255, // 124 - '|'
6,6,14,124,248,192,128, // 125 - '}'
0, // 126
0, // 127
8, 240, 240, 48, 48, 48, 112, 224, 192, // 128 - 'р' //Up
8, 192, 224, 112, 48, 48, 112, 224, 192, // 129 - 'с' //Up
8, 112, 48, 48, 240, 240, 48, 48, 112, // 130 - 'т' //Up
8, 240, 240, 0, 0, 0, 0, 240, 240, // 131 - 'у' //Up
10, 128, 192, 224, 96, 240, 240, 96, 224, 192, 128, // 132 - 'ф' //Up
8, 112, 240, 128, 0, 0, 128, 240, 112, // 133 - 'х' //Up
8, 240, 240, 0, 0, 0, 240, 240, 0, // 134 - 'ц' //Up
8, 240, 240, 0, 0, 0, 0, 240, 240, // 135 - 'ч' //Up
10, 240, 240, 0, 0, 224, 224, 0, 0, 240, 240, // 136 - 'ш' //Up
10, 240, 240, 0, 0, 128, 128, 0, 0, 240, 240, // 137 - 'щ' //Up
8, 48, 240, 240, 0, 0, 0, 0, 0, // 138 - 'ъ' //Up
10, 240, 240, 0, 0, 0, 0, 0, 0, 240, 240, // 139 - 'ы' //Up
8, 240, 240, 0, 0, 0, 0, 0, 0, // 140 - 'ь' //Up
8, 192, 224, 112, 48, 48, 112, 224, 192, // 141 - 'э' //Up
10, 240, 240, 0, 192, 224, 112, 48, 112, 224, 192, // 142 - 'ю' //Up
8, 192, 224, 112, 48, 48, 48, 240, 240, // 143 - 'я' //Up
8, 248, 252, 14, 7, 7, 14, 252, 248, // 144 - 'А' //Up
8, 255, 255, 195, 195, 195, 195, 131, 0, // 145 - 'Б' //Up
8, 255, 255, 195, 195, 195, 231, 190, 28, // 146 - 'В' //Up
6, 255, 255, 3, 3, 7, 7, // 147 - 'Г' //Up
10, 0, 248, 252, 14, 7, 7, 7, 255, 255, 0, // 148 - 'Д' //Up
6, 255, 255, 131, 131, 131, 3, // 149 - 'Е' //Up
10, 31, 63, 96, 192, 255, 255, 192, 96, 63, 63, // 150 - 'Ж' //Up
8, 12, 14, 7, 195, 195, 231, 190, 28, // 151 - 'З' //Up
8, 255, 255, 0, 0, 0, 0, 255, 255, // 152 - 'И' //Up
8, 254, 254, 0, 3, 3, 0, 254, 254, // 153 - 'Й' //Up
8, 255, 255, 128, 192, 96, 48, 31, 15, // 154 - 'К' //Up
8, 0, 248, 252, 14, 7, 7, 255, 255, // 155 - 'Л' //Up
10, 255, 255, 240, 192, 0, 0, 192, 240, 255, 255, // 156 - 'М' //Up
8, 255, 255, 128, 128, 128, 128, 255, 255, // 157 - 'Н' //Up
8, 252, 254, 7, 3, 3, 7, 254, 252, // 158 - 'О' //Up
8, 255, 255, 7, 7, 7, 7, 255, 255, // 159 - 'П' //Up
8, 255, 255, 3, 3, 3, 7, 254, 252, // 160 - 'Р' //Up
8, 252, 254, 7, 3, 3, 7, 30, 28, // 161 - 'С' //Up
8, 7, 7, 3, 255, 255, 3, 7, 7, // 162 - 'Т' //Up
8, 63, 127, 192, 128, 0, 0, 255, 255, // 163 - 'У' //Up
10, 240, 248, 28, 12, 255, 255, 12, 28, 248, 240, // 164 - 'Ф' //Up
8, 31, 63, 112, 192, 192, 112, 63, 31, // 165 - 'Х' //Up
8, 255, 255, 0, 0, 0, 255, 255, 0, // 166 - 'Ц' //Up
8, 255, 255, 0, 0, 0, 0, 255, 255, // 167 - 'Ч' //Up
10, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, // 168 - 'Ш' //Up
10, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, // 169 - 'Щ' //Up
8, 7, 255, 255, 192, 192, 192, 128, 0, // 170 - 'Ъ' //Up
10, 255, 255, 192, 192, 192, 128, 0, 0, 255, 255, // 171 - 'Ы' //Up
8, 255, 255, 96, 96, 96, 224, 192, 128, // 172 - 'Ь' //Up
8, 12, 14, 7, 131, 131, 135, 254, 252, // 173 - 'Э' //Up
10, 255, 255, 128, 252, 254, 7, 3, 7, 254, 252, // 174 - 'Ю' //Up
8, 252, 254, 135, 3, 3, 3, 255, 255, // 175 - 'Я' //Up
8, 192, 224, 112, 48, 112, 240, 224, 0, // 176 - 'а' //Up
8, 240, 240, 48, 48, 48, 48, 48, 0, // 177 - 'б' //Up
7, 240, 240, 48, 112, 224, 192, 0, // 178 - 'в' //Up
6, 240, 240, 48, 48, 112, 112, // 179 - 'г' //Up
8, 0, 128, 192, 224, 112, 240, 240, 0, // 180 - 'д' //Up
8, 192, 224, 112, 48, 48, 112, 224, 192, // 181 - 'е' //Up
10, 112, 240, 0, 0, 240, 240, 0, 0, 240, 112, // 182 - 'ж' //Up
8, 192, 224, 112, 48, 48, 112, 224, 192, // 183 - 'з' //Up
8, 240, 240, 0, 0, 0, 0, 240, 240, // 184 - 'и' //Up
8, 224, 224, 0, 48, 48, 0, 224, 224, // 185 - 'й' //Up
8, 240, 240, 0, 0, 128, 192, 112, 48, // 186 - 'к' //Up
8, 0, 0, 0, 0, 192, 112, 240, 240, // 187 - 'л' //Up
10, 240, 240, 128, 0, 0, 0, 0, 128, 240, 240, // 188 - 'м' //Up
8, 240, 240, 0, 0, 0, 0, 240, 240, // 189 - 'н' //Up
8, 192, 224, 112, 48, 48, 112, 224, 192, // 190 - 'о' //Up
8, 240, 240, 48, 48, 48, 48, 240, 240, // 191 - 'п' //Up
0, // 192
0, // 193
0, // 194
0, // 195
0, // 196
0, // 197
0, // 198
0, // 199
0, // 200
0, // 201
0, // 202
0, // 203
0, // 204
0, // 205
0, // 206
0, // 207
0, // 208
0, // 209
0, // 210
0, // 211
0, // 212
0, // 213
0, // 214
0, // 215
0, // 216
0, // 217
0, // 218
0, // 219
0, // 220
0, // 221
0, // 222
0, // 223
0, // 224
0, // 225
0, // 226
0, // 227
0, // 228
0, // 229
0, // 230
0, // 231
0, // 232
0, // 233
0, // 234
0, // 235
0, // 236
0, // 237
0, // 238
0, // 239
0, // 240
0, // 241
0, // 242
0, // 243
0, // 244
0, // 245
0, // 246
0, // 247
0, // 248
0, // 249
0, // 250
0, // 251
0, // 252
0, // 253
0, // 254
0, // 255
};
#endif

View File

@@ -0,0 +1,162 @@
// Demonstrates one way to create a double height display using Parola.
//
// Largely based on code shared by arduino.cc forum user Arek00, 26 Sep 2015.
// Video of running display can be seen at https://www.youtube.com/watch?v=7nPCIMVUo5g
// Modified with Russian font by arduino.cc forum user borzov161, 25 May 2017.
//
// The upper and lower portions are managed as 2 zones 'stacked' on top of each other
// so that the module numbers are in the sequence shown below:
//
// * Modules (like FC-16) that can fit over each other with no gap
// n n-1 n-2 ... n/2+1 <- this direction top row
// n/2 ... 3 2 1 0 <- this direction bottom row
//
// * Modules (like Generic and Parola) that cannot fit over each other with no gap
// n/2+1 ... n-2 n-1 n -> this direction top row
// n/2 ... 3 2 1 0 <- this direction bottom row
//
// Each font displays letters for either top or bottom half of the message. Sending the
// same string to both zones creates the complete message
// on the display.
//
// NOTE: MD_MAX72xx library must be installed and confugured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include "Font_Data_RUS.h" //English + Russian
#if USE_GENERIC_HW || USE_PAROLA_HW
#define INVERT_UPPER_ZONE
#endif
#define DEBUG 0
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_ZONES 2
#define ZONE_SIZE 4
#define MAX_DEVICES (MAX_ZONES * ZONE_SIZE)
#define SCROLL_SPEED 30
#define ZONE_UPPER 1
#define ZONE_LOWER 0
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// HARDWARE SPI
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
char *msg[] =
{
"Create double height displays using 2 custom fonts and 2 zones",
"Zone 0 for lower half",
"Zone 1 for upper half",
"BIG",
"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
"abcdefghijklmnopqrstuvwxyz",
"0123456789",
"`!@#$%^&*()_+-={};:'\"<>?,./|\\{}",
"АБВГДЕЖЗКЛМНОПРСТФУХЦЧШЩЪЫЬЭЮЯ",
"абвгдежзлмнопрстуфхцчшщъыьэюя"
};
void setup(void)
{
// initialise the LED display
P.begin(MAX_ZONES);
// Set up zones for 2 halves of the display
// Each zone gets a different font, making up the top
// and bottom half of each letter
P.setZone(ZONE_LOWER, 0, ZONE_SIZE - 1);
P.setFont(ZONE_LOWER, BigFontLower);
P.setZone(ZONE_UPPER, ZONE_SIZE, MAX_DEVICES-1);
P.setFont(ZONE_UPPER, BigFontUpper);
P.setCharSpacing(P.getCharSpacing() * 2); // double height --> double spacing
#ifdef INVERT_UPPER_ZONE
P.setZoneEffect(ZONE_UPPER, true, PA_FLIP_UD);
P.setZoneEffect(ZONE_UPPER, true, PA_FLIP_LR);
#endif
#if DEBUG
Serial.begin(57600);
Serial.println("[Double Height demo start]");
#endif
}
void loop(void)
{
static uint8_t cycle = 0;
// Run the animation and then check if BOTH zones have
// completed. The animations are not the same length due
// to upper/lower effects being displayed differently.
P.displayAnimate();
if (P.getZoneStatus(ZONE_LOWER) && P.getZoneStatus(ZONE_UPPER))
{
#if DEBUG
Serial.println(cycle);
#endif
switch (cycle)
{
default:
P.setFont(ZONE_LOWER, BigFontLower);
P.setFont(ZONE_UPPER, BigFontUpper);
#ifdef INVERT_UPPER_ZONE
P.displayZoneText(ZONE_LOWER, msg[cycle], PA_LEFT, SCROLL_SPEED, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
P.displayZoneText(ZONE_UPPER, msg[cycle], PA_LEFT, SCROLL_SPEED, 0, PA_SCROLL_RIGHT, PA_SCROLL_RIGHT);
#else
P.displayZoneText(ZONE_LOWER, msg[cycle], PA_RIGHT, SCROLL_SPEED, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
P.displayZoneText(ZONE_UPPER, msg[cycle], PA_LEFT, SCROLL_SPEED, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
#endif
break;
case 1:
P.setFont(ZONE_LOWER, NULL);
P.setFont(ZONE_UPPER, BigFontUpper);
P.displayZoneText(ZONE_LOWER, msg[1], PA_CENTER, SCROLL_SPEED, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
P.displayZoneText(ZONE_UPPER, msg[3], PA_CENTER, SCROLL_SPEED, 0, PA_PRINT, PA_NO_EFFECT);
break;
case 2:
P.setFont(ZONE_LOWER, BigFontLower);
P.setFont(ZONE_UPPER, NULL);
P.displayZoneText(ZONE_LOWER, msg[3], PA_CENTER, SCROLL_SPEED, 0, PA_PRINT, PA_NO_EFFECT);
#ifdef INVERT_UPPER_ZONE
P.displayZoneText(ZONE_UPPER, msg[2], PA_CENTER, SCROLL_SPEED, 0, PA_SCROLL_RIGHT, PA_SCROLL_RIGHT);
#else
P.displayZoneText(ZONE_UPPER, msg[2], PA_CENTER, SCROLL_SPEED, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
#endif
break;
case 3:
P.setFont(ZONE_LOWER, BigFontLower);
P.setFont(ZONE_UPPER, BigFontUpper);
P.displayZoneText(ZONE_LOWER, msg[3], PA_CENTER, SCROLL_SPEED, 2000, PA_PRINT, PA_NO_EFFECT); // PA_SCROLL_LEFT, PA_SCROLL_LEFT);
P.displayZoneText(ZONE_UPPER, msg[3], PA_CENTER, SCROLL_SPEED, 2000, PA_PRINT, PA_NO_EFFECT); //PA_SCROLL_RIGHT, PA_SCROLL_RIGHT);
break;
}
// prepare for next pass
cycle = (cycle + 1) % ARRAY_SIZE(msg);
// synchronise the start
P.displayClear();
P.synchZoneStart();
}
}

View File

@@ -0,0 +1,264 @@
// Data file for user example user defined fonts
#ifndef FONTDATA_H
#define FONTDATA_H
MD_MAX72XX::fontType_t BigFont[] PROGMEM = {
0, // 0
0, // 1
0, // 2
0, // 3
0, // 4
0, // 5
0, // 6
0, // 7
0, // 8
0, // 9
0, // 10
0, // 11
0, // 12
0, // 13
0, // 14
0, // 15
0, // 16
0, // 17
0, // 18
0, // 19
0, // 20
0, // 21
0, // 22
0, // 23
0, // 24
0, // 25
0, // 26
0, // 27
0, // 28
0, // 29
0, // 30
0, // 31
4, 0, 0, 0, 0, // 32 - 'Space lower'
2, 51, 51, // 33 - '! lower'
6, 0, 0, 0, 0, 0, 0, // 34 - '" lower'
10, 3, 3, 63, 63, 3, 3, 63, 63, 3, 3, // 35 - '# lower'
10, 24, 56, 48, 48, 127, 127, 48, 57, 31, 15, // 36 - '$ lower'
8, 48, 60, 15, 3, 24, 36, 36, 24, // 37 - '% lower'
10, 15, 31, 57, 48, 48, 59, 31, 14, 63, 51, // 38 - '& lower'
2, 0, 0, // 39 - ' lower'
5, 3, 15, 28, 56, 48, // 40 - '( lower'
5, 48, 56, 28, 15, 3, // 41 - ') lower'
10, 6, 7, 7, 1, 31, 31, 1, 3, 7, 6, // 42 - '* lower'
10, 0, 0, 0, 0, 15, 15, 0, 0, 0, 0, // 43 - '+ lower'
2, 176, 112, // 44 - ', lower'
9, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 45 - '- lower'
2, 48, 48, // 46 - '. lower'
8, 48, 60, 15, 3, 0, 0, 0, 0, // 47 - '/ lower'
10, 15, 31, 57, 48, 48, 48, 48, 56, 31, 15, // 48 - '0 lower'
5, 0, 48, 63, 63, 48, // 49 - '1 lower'
10, 63, 63, 49, 48, 48, 48, 48, 48, 48, 48, // 50 - '2 lower'
10, 12, 28, 56, 48, 48, 48, 48, 56, 31, 15, // 51 - '3 lower'
10, 3, 3, 3, 3, 3, 3, 3, 63, 63, 3, // 52 - '4 lower'
10, 12, 28, 56, 48, 48, 48, 48, 56, 31, 15, // 53 - '5 lower'
10, 15, 31, 56, 48, 48, 48, 48, 56, 31, 15, // 54 - '6 lower'
10, 0, 0, 0, 63, 63, 0, 0, 0, 0, 0, // 55 - '7 lower'
10, 15, 31, 57, 48, 48, 48, 48, 57, 31, 15, // 56 - '8 lower'
10, 0, 0, 0, 0, 0, 0, 0, 0, 63, 63, // 57 - '9 lower'
2, 24, 24, // 58 - ': lower'
2, 88, 56, // 59 - '; lower'
8, 0, 1, 3, 7, 14, 28, 56, 48, // 60 - '< lower'
9, 6, 6, 6, 6, 6, 6, 6, 6, 6, // 61 - '= lower'
8, 48, 56, 28, 14, 7, 3, 1, 0, // 62 - '> lower'
10, 0, 0, 0, 0, 55, 55, 1, 0, 0, 0, // 63 - '? lower'
10, 15, 31, 56, 51, 54, 54, 51, 54, 55, 19, // 64 - '@ lower'
10, 63, 63, 1, 1, 1, 1, 1, 1, 63, 63, // 65 - 'A lower'
10, 63, 63, 48, 48, 48, 48, 48, 57, 31, 15, // 66 - 'B lower'
10, 15, 31, 56, 48, 48, 48, 48, 56, 28, 12, // 67 - 'C lower'
10, 63, 63, 48, 48, 48, 48, 48, 56, 31, 15, // 68 - 'D lower'
9, 63, 63, 48, 48, 48, 48, 48, 48, 48, // 69 - 'E lower'
9, 63, 63, 0, 0, 0, 0, 0, 0, 0, // 70 - 'F lower'
10, 15, 31, 56, 48, 48, 48, 49, 57, 31, 15, // 71 - 'G lower'
10, 63, 63, 0, 0, 0, 0, 0, 0, 63, 63, // 72 - 'H lower'
4, 48, 63, 63, 48, // 73 - 'I lower'
8, 12, 28, 56, 48, 48, 56, 31, 15, // 74 - 'J lower'
9, 63, 63, 1, 3, 7, 14, 28, 56, 48, // 75 - 'K lower'
9, 63, 63, 48, 48, 48, 48, 48, 48, 48, // 76 - 'L lower'
10, 63, 63, 0, 0, 0, 0, 0, 0, 63, 63, // 77 - 'M lower'
10, 63, 63, 0, 0, 0, 0, 1, 3, 63, 63, // 78 - 'N lower'
10, 15, 31, 56, 48, 48, 48, 48, 56, 31, 15, // 79 - 'O lower'
10, 63, 63, 0, 0, 0, 0, 0, 0, 0, 0, // 80 - 'P lower'
10, 15, 31, 56, 48, 48, 54, 62, 28, 63, 55, // 81 - 'Q lower'
10, 63, 63, 0, 1, 3, 7, 14, 28, 56, 48, // 82 - 'R lower'
10, 24, 56, 48, 48, 48, 48, 48, 57, 31, 15, // 83 - 'S lower'
8, 0, 0, 0, 63, 63, 0, 0, 0, // 84 - 'T lower'
10, 15, 31, 56, 48, 48, 48, 48, 56, 31, 15, // 85 - 'U lower'
10, 3, 7, 14, 28, 56, 56, 28, 14, 7, 3, // 86 - 'V lower'
10, 15, 31, 56, 60, 31, 31, 60, 56, 31, 15, // 87 - 'W lower'
10, 60, 62, 7, 3, 1, 1, 3, 7, 62, 60, // 88 - 'X lower'
10, 0, 0, 0, 0, 63, 63, 0, 0, 0, 0, // 89 - 'Y lower'
10, 60, 62, 55, 51, 49, 48, 48, 48, 48, 48, // 90 - 'Z lower'
4, 63, 63, 48, 48, // 91 - '[ lower'
8, 0, 0, 0, 0, 3, 15, 60, 48, // 92 - '\ lower'
4, 48, 48, 63, 63, // 93 - '] lower'
8, 0, 0, 0, 0, 0, 0, 0, 0, // 94 - '^ lower'
10, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 95 - '_ lower'
3, 0, 0, 0, // 96 - '` lower'
10, 12, 30, 51, 51, 51, 51, 51, 51, 63, 31, // 97 - 'a lower'
10, 63, 63, 28, 56, 48, 48, 48, 56, 31, 15, // 98 - 'b lower'
9, 15, 31, 56, 48, 48, 48, 56, 28, 12, // 99 - 'c lower'
10, 15, 31, 56, 48, 48, 48, 56, 28, 63, 63, // 100 - 'd lower'
9, 15, 31, 59, 51, 51, 51, 59, 27, 9, // 101 - 'e lower'
7, 0, 63, 63, 0, 0, 0, 0, // 102 - 'f lower'
9, 49, 115, 231, 198, 198, 198, 230, 127, 63, // 103 - 'g lower'
9, 63, 63, 0, 0, 0, 0, 0, 63, 63, // 104 - 'h lower'
2, 63, 63, // 105 - 'i lower'
8, 48, 112, 224, 192, 192, 224, 127, 63, // 106 - 'j lower'
8, 63, 63, 3, 7, 15, 28, 56, 48, // 107 - 'k lower'
4, 48, 63, 63, 48, // 108 - 'l lower'
10, 63, 63, 0, 0, 63, 63, 0, 0, 63, 63, // 109 - 'm lower'
9, 63, 63, 0, 0, 0, 0, 0, 63, 63, // 110 - 'n lower'
9, 15, 31, 56, 48, 48, 48, 56, 31, 15, // 111 - 'o lower'
9, 255, 255, 7, 14, 12, 12, 14, 7, 3, // 112 - 'p lower'
9, 3, 7, 14, 12, 12, 14, 7, 255, 255, // 113 - 'q lower'
9, 63, 63, 0, 0, 0, 0, 0, 0, 0, // 114 - 'r lower'
9, 24, 57, 51, 51, 51, 51, 51, 30, 12, // 115 - 's lower'
6, 0, 31, 63, 48, 56, 24, // 116 - 't lower'
9, 15, 31, 56, 48, 48, 56, 28, 63, 63, // 117 - 'u lower'
9, 7, 15, 28, 56, 48, 56, 28, 15, 7, // 118 - 'v lower'
10, 15, 31, 56, 56, 31, 31, 56, 56, 31, 15, // 119 - 'w lower'
10, 48, 56, 28, 15, 7, 7, 15, 28, 56, 48, // 120 - 'x lower'
9, 49, 115, 230, 198, 198, 198, 230, 127, 63, // 121 - 'y lower'
10, 48, 56, 60, 62, 55, 51, 49, 48, 48, 48, // 122 - 'z lower'
6, 0, 1, 15, 31, 56, 48, // 123 - '{ lower'
2, 255, 255, // 124 - '| lower'
6, 48, 56, 31, 15, 1, 0, // 125 - '} lower'
0, // 126
0, // 127
0, // 128
0, // 129
0, // 130
0, // 131
0, // 132
0, // 133
0, // 134
0, // 135
0, // 136
0, // 137
0, // 138
0, // 139
0, // 140
0, // 141
0, // 142
0, // 143
0, // 144
0, // 145
0, // 146
0, // 147
0, // 148
0, // 149
0, // 150
0, // 151
0, // 152
0, // 153
0, // 154
0, // 155
0, // 156
0, // 157
0, // 158
0, // 159
4, 0, 0, 0, 0, // 160 - 'Space upper'
2, 255, 255, // 161 - '! upper'
6, 15, 15, 0, 0, 15, 15, // 162 - '" upper'
10, 48, 48, 255, 255, 48, 48, 255, 255, 48, 48, // 163 - '# upper'
10, 56, 124, 238, 198, 255, 255, 198, 198, 142, 12, // 164 - '$ upper'
8, 6, 9, 9, 198, 240, 60, 15, 3, // 165 - '% upper'
10, 0, 128, 204, 254, 243, 243, 158, 12, 0, 0, // 166 - '& upper'
2, 15, 15, // 167 - '' upper'
5, 240, 252, 14, 7, 3, // 168 - '( upper'
5, 3, 7, 14, 252, 240, // 169 - ') upper'
10, 48, 112, 224, 192, 252, 252, 192, 224, 112, 48, // 170 - '* upper'
10, 192, 192, 192, 192, 252, 252, 192, 192, 192, 192, // 171 - '+ upper'
2, 0, 0, // 172 - ', upper'
9, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 173 - '- upper'
2, 0, 0, // 174 - '. upper'
8, 0, 0, 0, 192, 240, 60, 15, 3, // 175 - '/ upper'
10, 252, 254, 135, 195, 99, 51, 27, 15, 254, 252, // 176 - '0 upper'
5, 4, 6, 255, 255, 0, // 177 - '1 upper'
10, 12, 142, 199, 195, 195, 195, 195, 231, 126, 60, // 178 - '2 upper'
10, 12, 14, 7, 3, 3, 195, 195, 199, 254, 60, // 179 - '3 upper'
10, 128, 192, 224, 112, 56, 28, 14, 255, 255, 0, // 180 - '4 upper'
10, 63, 63, 51, 51, 51, 51, 51, 115, 227, 195, // 181 - '5 upper'
10, 252, 254, 231, 99, 99, 99, 99, 231, 198, 132, // 182 - '6 upper'
10, 3, 3, 3, 131, 195, 227, 115, 59, 31, 15, // 183 - '7 upper'
10, 28, 190, 247, 227, 195, 195, 227, 247, 190, 28, // 184 - '8 upper'
10, 60, 126, 231, 195, 195, 195, 195, 231, 255, 254, // 185 - '9 upper'
2, 48, 48, // 186 - ': upper'
2, 48, 48, // 187 - '; upper'
8, 192, 224, 240, 56, 28, 14, 7, 3, // 188 - '< upper'
9, 96, 96, 96, 96, 96, 96, 96, 96, 96, // 189 - '= upper'
8, 3, 7, 14, 28, 56, 240, 224, 192, // 190 - '> upper'
10, 12, 14, 7, 3, 3, 131, 195, 231, 126, 60, // 191 - '? upper'
10, 252, 254, 7, 243, 27, 27, 243, 7, 254, 252, // 192 - '@ upper'
10, 248, 254, 134, 131, 131, 131, 131, 134, 254, 248, // 193 - 'A upper'
10, 255, 255, 195, 195, 195, 195, 195, 231, 254, 60, // 194 - 'B upper'
10, 252, 254, 7, 3, 3, 3, 3, 7, 14, 12, // 195 - 'C upper'
10, 255, 255, 3, 3, 3, 3, 3, 7, 254, 252, // 196 - 'D upper'
9, 255, 255, 195, 195, 195, 195, 195, 3, 3, // 197 - 'E upper'
9, 255, 255, 195, 195, 195, 195, 195, 3, 3, // 198 - 'F upper'
10, 252, 254, 7, 3, 3, 3, 131, 135, 142, 140, // 199 - 'G upper'
10, 255, 255, 192, 192, 192, 192, 192, 192, 255, 255, // 200 - 'H upper'
4, 3, 255, 255, 3, // 201 - 'I upper'
8, 3, 3, 3, 3, 3, 3, 255, 255, // 202 - 'J upper'
9, 255, 255, 224, 240, 56, 28, 14, 7, 3, // 203 - 'K upper'
9, 255, 255, 0, 0, 0, 0, 0, 0, 0, // 204 - 'L upper'
10, 255, 255, 14, 28, 120, 120, 28, 14, 255, 255, // 205 - 'M upper'
10, 255, 255, 28, 56, 112, 224, 192, 128, 255, 255, // 206 - 'N upper'
10, 252, 254, 7, 3, 3, 3, 3, 7, 254, 252, // 207 - 'O upper'
10, 255, 255, 195, 195, 195, 195, 195, 231, 126, 60, // 208 - 'P upper'
10, 252, 254, 7, 3, 3, 3, 3, 7, 254, 252, // 209 - 'Q upper'
10, 255, 255, 195, 195, 195, 195, 195, 231, 126, 60, // 210 - 'R upper'
10, 60, 126, 231, 195, 195, 195, 195, 195, 135, 6, // 211 - 'S upper'
8, 3, 3, 3, 255, 255, 3, 3, 3, // 212 - 'T upper'
10, 255, 255, 0, 0, 0, 0, 0, 0, 255, 255, // 213 - 'U upper'
10, 255, 255, 0, 0, 0, 0, 0, 0, 255, 255, // 214 - 'V upper'
10, 255, 255, 0, 0, 0, 0, 0, 0, 255, 255, // 215 - 'W upper'
10, 15, 31, 56, 240, 224, 224, 240, 56, 31, 15, // 216 - 'X upper'
10, 15, 31, 56, 112, 224, 224, 112, 56, 31, 15, // 217 - 'Y upper'
10, 3, 3, 3, 131, 195, 227, 115, 59, 31, 15, // 218 - 'Z upper'
4, 255, 255, 3, 3, // 219 - '[ upper'
8, 3, 15, 60, 240, 192, 0, 0, 0, // 220 - '\ upper'
4, 3, 3, 255, 255, // 221 - '] upper'
8, 24, 12, 6, 3, 3, 6, 12, 24, // 222 - '^ upper'
10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 223 - '_ upper'
3, 3, 15, 12, // 224 - '` upper'
10, 0, 96, 112, 48, 48, 48, 48, 112, 224, 192, // 225 - 'a upper'
10, 255, 255, 224, 112, 48, 48, 48, 112, 224, 192, // 226 - 'b upper'
9, 192, 224, 112, 48, 48, 48, 112, 224, 192, // 227 - 'c upper'
10, 192, 224, 112, 48, 48, 48, 112, 224, 255, 255, // 228 - 'd upper'
9, 192, 224, 112, 48, 48, 48, 112, 224, 192, // 229 - 'e upper'
7, 192, 252, 254, 199, 199, 14, 12, // 230 - 'f upper'
9, 192, 224, 112, 48, 48, 48, 112, 224, 192, // 231 - 'g upper'
9, 255, 255, 224, 112, 48, 48, 112, 224, 192, // 232 - 'h upper'
2, 246, 246, // 233 - 'i upper'
8, 0, 0, 0, 0, 0, 0, 246, 246, // 234 - 'j upper'
8, 254, 254, 0, 128, 192, 224, 112, 48, // 235 - 'k upper'
4, 3, 255, 255, 0, // 236 - 'l upper'
10, 240, 240, 48, 48, 240, 240, 48, 48, 240, 224, // 237 - 'm upper'
9, 240, 240, 224, 112, 48, 48, 112, 224, 192, // 238 - 'n upper'
9, 192, 224, 112, 48, 48, 48, 112, 224, 192, // 239 - 'o upper'
9, 240, 240, 96, 112, 48, 48, 112, 224, 192, // 240 - 'p upper'
9, 192, 224, 112, 48, 48, 112, 96, 240, 240, // 241 - 'q upper'
9, 240, 240, 224, 112, 48, 48, 112, 224, 192, // 242 - 'r upper'
9, 192, 224, 48, 48, 48, 48, 112, 96, 0, // 243 - 's upper'
6, 96, 252, 252, 96, 96, 0, // 244 - 't upper'
9, 240, 240, 0, 0, 0, 0, 0, 240, 240, // 245 - 'u upper'
9, 240, 240, 0, 0, 0, 0, 0, 240, 240, // 246 - 'v upper'
10, 240, 240, 0, 0, 0, 0, 0, 0, 240, 240, // 247 - 'w upper'
10, 48, 112, 224, 192, 128, 128, 192, 224, 112, 48, // 248 - 'x upper'
9, 240, 240, 0, 0, 0, 0, 0, 240, 240, // 249 - 'y upper'
10, 48, 48, 48, 48, 48, 176, 240, 240, 112, 48, // 250 - 'z upper'
6, 192, 224, 252, 62, 7, 3, // 251 - '{ upper'
2, 255, 255, // 252 - '| upper'
6, 3, 7, 62, 252, 224, 192, // 253 - '} upper'
0, // 254
0, // 255
};
#endif

View File

@@ -0,0 +1,175 @@
// Demonstrates one double height display using Parola using a single font file
// defintion created with the MD_MAX72xx font builder.
//
// Each font file has the lower part of a character as ASCII codes 0-127 and the
// upper part of the character in ASCII code 128-255. Adding 128 to each lower
// character creates the correct index for the upper character.
// The upper and lower portions are managed as 2 zones 'stacked' on top of each other
// so that the module numbers are in the sequence shown below:
//
// * Modules (like FC-16) that can fit over each other with no gap
// n n-1 n-2 ... n/2+1 <- this direction top row
// n/2 ... 3 2 1 0 <- this direction bottom row
//
// * Modules (like Generic and Parola) that cannot fit over each other with no gap
// n/2+1 ... n-2 n-1 n -> this direction top row
// n/2 ... 3 2 1 0 <- this direction bottom row
//
// Sending the original string to the lower zone and the modified (+128) string to the
// upper zone creates the complete message on the display.
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include "Font_Data.h"
#if USE_GENERIC_HW || USE_PAROLA_HW
#define INVERT_UPPER_ZONE 1
#endif
// Turn debugging on and off
#define DEBUG 0
#if DEBUG
#define PRINTS(s) { Serial.print(F(s)); }
#define PRINT(s, v) { Serial.print(F(s)); Serial.print(v); }
#else
#define PRINTS(s)
#define PRINT(s, v)
#endif
// Define the main direction for scrolling double height.
// if 1, scroll left; if 0, scroll right
#define SCROLL_LEFT 1
#if INVERT_UPPER_ZONE
#if SCROLL_LEFT // invert and scroll left
#define SCROLL_UPPER PA_SCROLL_RIGHT
#define SCROLL_LOWER PA_SCROLL_LEFT
#else // invert and scroll right
#define SCROLL_UPPER PA_SCROLL_LEFT
#define SCROLL_LOWER PA_SCROLL_RIGHT
#endif
#else // not invert
#if SCROLL_LEFT // not invert and scroll left
#define SCROLL_UPPER PA_SCROLL_LEFT
#define SCROLL_LOWER PA_SCROLL_LEFT
#else // not invert and scroll right
#define SCROLL_UPPER PA_SCROLL_RIGHT
#define SCROLL_LOWER PA_SCROLL_RIGHT
#endif
#endif
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers may not work with your hardware and may need changing
#define MAX_ZONES 2
#define ZONE_SIZE 4
#define MAX_DEVICES (MAX_ZONES * ZONE_SIZE)
#define ZONE_UPPER 1
#define ZONE_LOWER 0
#define PAUSE_TIME 0
#define SCROLL_SPEED 50
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// HARDWARE SPI
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
char *msgL[] =
{
"Double height with custom font & 2 zones",
"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
"abcdefghijklmnopqrstuvwxyz",
"0123456789",
"`!@#$%^&*()_+-={};:'<>\"?,./|\\{}",
};
char *msgH; // allocated memory in setup()
void setup(void)
{
uint8_t max = 0;
#if DEBUG
Serial.begin(57600);
PRINTS("\n[Double_Height_v2]");
#endif
// work out the size of buffer required
for (uint8_t i = 0; i<ARRAY_SIZE(msgL); i++)
if (strlen(msgL[i]) > max) max = strlen(msgL[i]);
msgH = (char *)malloc(sizeof(char)*(max + 2));
// initialise the LED display
P.begin(MAX_ZONES);
// Set up zones for 2 halves of the display
P.setZone(ZONE_LOWER, 0, ZONE_SIZE - 1);
P.setZone(ZONE_UPPER, ZONE_SIZE, MAX_DEVICES-1);
P.setFont(BigFont);
P.setCharSpacing(P.getCharSpacing() * 2); // double height --> double spacing
#if INVERT_UPPER_ZONE
P.setZoneEffect(ZONE_UPPER, true, PA_FLIP_UD);
P.setZoneEffect(ZONE_UPPER, true, PA_FLIP_LR);
#endif
PRINT("\nFLIP_UD=", P.getZoneEffect(ZONE_UPPER, PA_FLIP_UD));
PRINT("\nFLIP_LR=", P.getZoneEffect(ZONE_UPPER, PA_FLIP_LR));
PRINT("\nSCROLL_LEFT=", SCROLL_LEFT);
}
void createHString(char *pH, char *pL)
{
for (; *pL != '\0'; pL++)
*pH++ = *pL | 0x80; // offset character
*pH = '\0'; // terminate the string
}
void loop(void)
{
static uint8_t cycle = 0;
P.displayAnimate();
if (P.getZoneStatus(ZONE_LOWER) && P.getZoneStatus(ZONE_UPPER))
{
PRINT("\n", cycle);
PRINT(": ", msgL[cycle]);
// set up the string
createHString(msgH, msgL[cycle]);
P.displayClear();
#if INVERT_UPPER_ZONE
P.displayZoneText(ZONE_UPPER, msgH, PA_CENTER, SCROLL_SPEED, PAUSE_TIME, SCROLL_UPPER, SCROLL_UPPER);
P.displayZoneText(ZONE_LOWER, msgL[cycle], PA_CENTER, SCROLL_SPEED, PAUSE_TIME, SCROLL_LOWER, SCROLL_LOWER);
#else
P.displayZoneText(ZONE_LOWER, msgL[cycle], PA_LEFT, SCROLL_SPEED, PAUSE_TIME, SCROLL_LOWER, SCROLL_LOWER);
P.displayZoneText(ZONE_UPPER, msgH, PA_LEFT, SCROLL_SPEED, PAUSE_TIME, SCROLL_UPPER, SCROLL_UPPER);
#endif
// prepare for next pass
cycle = (cycle + 1) % ARRAY_SIZE(msgL);
// synchronise the start and run the display
P.synchZoneStart();
}
}

View File

@@ -0,0 +1,90 @@
// Program to exercise the MD_Parola library
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include "Parola_Fonts_data.h"
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 8
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// HARDWARE SPI
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
#define PAUSE_TIME 3000
// Turn on debug statements to the serial output
#define DEBUG 0
#if DEBUG
#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }
#define PRINTS(x) Serial.print(F(x))
#define PRINTX(x) Serial.println(x, HEX)
#else
#define PRINT(s, x)
#define PRINTS(x)
#define PRINTX(x)
#endif
// Global variables
typedef struct
{
char name[10];
MD_MAX72XX::fontType_t *pFont;
textEffect_t effect;
char * pMsg;
} message_t;
message_t M[] =
{
{ "Roman", nullptr, PA_SCROLL_LEFT, "Arduino" },
{ "Japanese", fontKatakana, PA_SCROLL_LEFT, "\x0b1\x0b0\x0c2\x0b2\x0c9" },
{ "Arabic", fontArabic, PA_SCROLL_RIGHT, "\x0a9\x0a7\x0ab\x0a9\x090\x0a5\x088" }, // ا ر د و ي ن و
{ "Greek", fontGreek, PA_SCROLL_LEFT, "\x080\x0a8\x09b\x0b2\x0a0\x0a4\x0a6" }
};
#define MAX_MESG (sizeof(M)/sizeof(M[0]))
uint8_t curM = 0; // current message definition to use
void setup(void)
{
Serial.begin(57600);
PRINTS("\n[Parola Demo]");
P.begin();
P.setFont(M[curM].pFont);
P.displayText(M[curM].pMsg, PA_CENTER, P.getSpeed(), PAUSE_TIME, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
}
void loop(void)
{
if (P.displayAnimate())
{
curM = (curM + 1) % MAX_MESG;
P.setFont(M[curM].pFont);
P.setTextBuffer(M[curM].pMsg);
P.setTextEffect(M[curM].effect, M[curM].effect);
PRINT("\nChanging font to ", M[curM].name);
for (uint8_t i=0; i<strlen(M[curM].pMsg); i++)
{
PRINT(" ", (uint8_t) M[curM].pMsg[i]);
}
P.displayReset();
}
}

View File

@@ -0,0 +1,785 @@
// Data file for user example user defined fonts
#ifndef FONTS_DATA_H
#define FONTS_DATA_H
MD_MAX72XX::fontType_t fontGreek[] PROGMEM =
{
0, // 0
0, // 1
0, // 2
0, // 3
0, // 4
0, // 5
0, // 6
0, // 7
0, // 8
0, // 9
0, // 10
0, // 11
0, // 12
0, // 13
0, // 14
0, // 15
0, // 16
0, // 17
0, // 18
0, // 19
0, // 20
0, // 21
0, // 22
0, // 23
0, // 24
0, // 25
0, // 26
0, // 27
0, // 28
0, // 29
0, // 30
0, // 31
2,0,0, // 32
0, // 33
0, // 34
0, // 35
0, // 36
0, // 37
0, // 38
0, // 39
0, // 40
0, // 41
0, // 42
0, // 43
0, // 44
0, // 45
0, // 46
0, // 47
0, // 48
0, // 49
0, // 50
0, // 51
0, // 52
0, // 53
0, // 54
0, // 55
0, // 56
0, // 57
0, // 58
0, // 59
0, // 60
0, // 61
0, // 62
0, // 63
0, // 64
0, // 65
0, // 66
0, // 67
0, // 68
0, // 69
0, // 70
0, // 71
0, // 72
0, // 73
0, // 74
0, // 75
0, // 76
0, // 77
0, // 78
0, // 79
0, // 80
0, // 81
0, // 82
0, // 83
0, // 84
0, // 85
0, // 86
0, // 87
0, // 88
0, // 89
0, // 90
0, // 91
0, // 92
0, // 93
0, // 94
0, // 95
0, // 96
0, // 97
0, // 98
0, // 99
0, // 100
0, // 101
0, // 102
0, // 103
0, // 104
0, // 105
0, // 106
0, // 107
0, // 108
0, // 109
0, // 110
0, // 111
0, // 112
0, // 113
0, // 114
0, // 115
0, // 116
0, // 117
0, // 118
0, // 119
0, // 120
0, // 121
0, // 122
0, // 123
0, // 124
0, // 125
0, // 126
0, // 127
5, 124, 10, 9, 10, 124, // 128 - 'ALPHA'
5, 127, 73, 73, 73, 54, // 129 - 'BETA'
5, 127, 1, 1, 1, 3, // 130 - 'GAMMA'
5, 124, 66, 65, 66, 124, // 131 - 'DELTA'
5, 127, 73, 73, 73, 65, // 132 - 'EPSILON'
5, 99, 81, 73, 69, 99, // 133 - 'ZETA'
5, 127, 8, 8, 8, 127, // 134 - 'ETA'
5, 62, 73, 73, 73, 62, // 135 - 'THETA'
3, 65, 127, 65, // 136 - 'IOTA'
5, 127, 8, 20, 34, 65, // 137 - 'KAPPA'
5, 124, 2, 1, 2, 124, // 138 - 'LAMBDA'
5, 127, 2, 12, 2, 127, // 139 - 'MU'
5, 127, 2, 4, 8, 127, // 140 - 'NU'
5, 99, 73, 73, 73, 99, // 141 - 'XI'
5, 62, 65, 65, 65, 62, // 142 - 'OMICRON'
5, 1, 127, 1, 127, 1, // 143 - 'PI'
5, 127, 9, 9, 9, 6, // 144 - 'RHO'
5, 99, 85, 73, 65, 99, // 145 - 'SIGMA'
5, 3, 1, 127, 1, 3, // 146 - 'TAU'
5, 7, 8, 112, 8, 7, // 147 - 'UPSILON'
5, 8, 85, 127, 85, 8, // 148 - 'PHI'
5, 99, 20, 8, 20, 99, // 149 - 'CHI'
5, 7, 8, 127, 8, 7, // 150 - 'PSI'
5, 94, 97, 1, 97, 94, // 151 - 'OMEGA'
5, 56, 68, 72, 48, 72, // 152 - 'alpha'
4, 248, 84, 84, 40, // 153 - 'beta'
5, 2, 52, 72, 52, 2, // 154 - 'gamma'
4, 48, 74, 77, 49, // 155 - 'delta'
4, 40, 84, 84, 68, // 156 - 'epsilon'
4, 34, 50, 170, 198, // 157 - 'zeta'
4, 124, 8, 4, 248, // 158 - 'eta'
5, 56, 84, 84, 84, 56, // 159 - 'theta'
4, 60, 64, 64, 32, // 160 - 'iota'
4, 124, 16, 40, 68, // 161 - 'kappa'
4, 122, 9, 17, 126, // 162 - 'lambda'
5, 252, 32, 32, 16, 124, // 163 - 'mu'
5, 12, 48, 64, 48, 12, // 164 - 'nu'
5, 20, 42, 42, 170, 64, // 165 - 'xi'
5, 56, 68, 68, 68, 56, // 166 - 'omicron'
5, 4, 124, 4, 124, 4, // 167 - 'pi'
4, 248, 36, 36, 24, // 168 - 'rho'
5, 56, 68, 68, 60, 4, // 169 - 'sigma'
5, 72, 84, 84, 84, 36, // 170 - 'sigma (final)'
5, 4, 4, 60, 68, 4, // 171 - 'tau'
5, 60, 64, 64, 64, 60, // 172 - 'upsilon'
5, 12, 16, 124, 18, 12, // 173 - 'phi'
5, 68, 40, 16, 40, 68, // 174 - 'chi'
5, 12, 16, 124, 16, 12, // 175 - 'psi'
0, // 176
0, // 177
0, // 178
0, // 179
0, // 180
0, // 181
0, // 182
0, // 183
0, // 184
0, // 185
0, // 186
0, // 187
0, // 188
0, // 189
0, // 190
0, // 191
0, // 192
0, // 193
0, // 194
0, // 195
0, // 196
0, // 197
0, // 198
0, // 199
0, // 200
0, // 201
0, // 202
0, // 203
0, // 204
0, // 205
0, // 206
0, // 207
0, // 208
0, // 209
0, // 210
0, // 211
0, // 212
0, // 213
0, // 214
0, // 215
0, // 216
0, // 217
0, // 218
0, // 219
0, // 220
0, // 221
0, // 222
0, // 223
5, 56, 68, 48, 68, 56, // 224 - 'omega'
5, 56, 68, 73, 48, 72, // 225 - 'alpha tonos'
4, 40, 84, 85, 68, // 226 - 'epsilon tonos'
4, 124, 8, 5, 248, // 227 - 'eta tonos'
5, 1, 60, 65, 64, 32, // 228 - 'iota dialytika'
4, 61, 64, 64, 32, // 229 - 'iota tonos'
5, 56, 68, 69, 68, 56, // 230 - 'omicron tonos'
5, 60, 64, 65, 64, 60, // 231 - 'upsilon tonos'
5, 60, 65, 64, 65, 60, // 232 - 'upsilon dialytika'
5, 56, 68, 49, 68, 56, // 233 - 'omega tonos'
6, 1, 124, 10, 9, 10, 124, // 234 - 'ALPHA tonos'
5, 127, 73, 73, 73, 65, // 235 - 'EPSILON'
5, 127, 9, 8, 8, 127, // 236 - 'ETA tonos'
4, 3, 64, 127, 65, // 237 - 'IOTA tonos'
6, 1, 60, 66, 65, 65, 62, // 238 - 'OMICRON tonos'
6, 1, 6, 8, 112, 8, 7, // 239 - 'UPSILON tonos'
6, 1, 94, 97, 1, 97, 94, // 240 - 'OMEGA tonos'
0, // 241
0, // 242
0, // 243
3, 69, 124, 69, // 244 - 'IOTA dialytika'
5, 12, 17, 96, 17, 12, // 245 - 'UPSILON dialytika'
0, // 246
0, // 247
0, // 248
0, // 249
0, // 250
0, // 251
0, // 252
0, // 253
0, // 254
0, // 255
};
MD_MAX72XX::fontType_t fontArabic[] PROGMEM = // modern arabic
{
0, // 0
0, // 1
0, // 2
0, // 3
0, // 4
0, // 5
0, // 6
0, // 7
0, // 8
0, // 9
0, // 10
0, // 11
0, // 12
0, // 13
0, // 14
0, // 15
0, // 16
0, // 17
0, // 18
0, // 19
0, // 20
0, // 21
0, // 22
0, // 23
0, // 24
0, // 25
0, // 26
0, // 27
0, // 28
0, // 29
0, // 30
0, // 31
2, 0, 0, // 32 - 'Space'
1, 95, // 33 - '!'
3, 7, 0, 7, // 34 - '"'
5, 20, 127, 20, 127, 20, // 35 - '#'
5, 36, 42, 127, 42, 18, // 36 - '$'
5, 35, 19, 8, 100, 98, // 37 - '%'
5, 54, 73, 85, 34, 80, // 38 - '&'
3, 8, 7, 3, // 39 - '''
3, 28, 34, 65, // 40 - '('
3, 65, 34, 28, // 41 - ')'
5, 42, 28, 127, 28, 42, // 42 - '*'
5, 8, 8, 62, 8, 8, // 43 - '+'
3, 128, 112, 48, // 44 - ','
5, 8, 8, 8, 8, 8, // 45 - '-'
2, 96, 96, // 46 - '.'
5, 32, 16, 8, 4, 2, // 47 - '/'
5, 62, 81, 73, 69, 62, // 48 - '0'
3, 66, 127, 64, // 49 - '1'
5, 114, 73, 73, 73, 70, // 50 - '2'
5, 33, 65, 73, 77, 51, // 51 - '3'
5, 24, 20, 18, 127, 16, // 52 - '4'
5, 39, 69, 69, 69, 57, // 53 - '5'
5, 60, 74, 73, 73, 49, // 54 - '6'
5, 65, 33, 17, 9, 7, // 55 - '7'
5, 54, 73, 73, 73, 54, // 56 - '8'
5, 70, 73, 73, 41, 30, // 57 - '9'
1, 20, // 58 - ':'
2, 128, 104, // 59 - ';'
4, 8, 20, 34, 65, // 60 - '<'
5, 20, 20, 20, 20, 20, // 61 - '='
4, 65, 34, 20, 8, // 62 - '>'
5, 2, 1, 89, 9, 6, // 63 - '?'
5, 62, 65, 93, 89, 78, // 64 - '@'
5, 124, 18, 17, 18, 124, // 65 - 'A'
5, 127, 73, 73, 73, 54, // 66 - 'B'
5, 62, 65, 65, 65, 34, // 67 - 'C'
5, 127, 65, 65, 65, 62, // 68 - 'D'
5, 127, 73, 73, 73, 65, // 69 - 'E'
5, 127, 9, 9, 9, 1, // 70 - 'F'
5, 62, 65, 65, 81, 115, // 71 - 'G'
5, 127, 8, 8, 8, 127, // 72 - 'H'
3, 65, 127, 65, // 73 - 'I'
5, 32, 64, 65, 63, 1, // 74 - 'J'
5, 127, 8, 20, 34, 65, // 75 - 'K'
5, 127, 64, 64, 64, 64, // 76 - 'L'
5, 127, 2, 28, 2, 127, // 77 - 'M'
5, 127, 4, 8, 16, 127, // 78 - 'N'
5, 62, 65, 65, 65, 62, // 79 - 'O'
5, 127, 9, 9, 9, 6, // 80 - 'P'
5, 62, 65, 81, 33, 94, // 81 - 'Q'
5, 127, 9, 25, 41, 70, // 82 - 'R'
5, 38, 73, 73, 73, 50, // 83 - 'S'
5, 3, 1, 127, 1, 3, // 84 - 'T'
5, 63, 64, 64, 64, 63, // 85 - 'U'
5, 31, 32, 64, 32, 31, // 86 - 'V'
5, 63, 64, 56, 64, 63, // 87 - 'W'
5, 99, 20, 8, 20, 99, // 88 - 'X'
5, 3, 4, 120, 4, 3, // 89 - 'Y'
5, 97, 89, 73, 77, 67, // 90 - 'Z'
3, 127, 65, 65, // 91 - '['
5, 2, 4, 8, 16, 32, // 92 - '\'
3, 65, 65, 127, // 93 - ']'
5, 4, 2, 1, 2, 4, // 94 - '^'
5, 64, 64, 64, 64, 64, // 95 - '_'
3, 3, 7, 8, // 96 - '`'
5, 32, 84, 84, 120, 64, // 97 - 'a'
5, 127, 40, 68, 68, 56, // 98 - 'b'
5, 56, 68, 68, 68, 40, // 99 - 'c'
5, 56, 68, 68, 40, 127, // 100 - 'd'
5, 56, 84, 84, 84, 24, // 101 - 'e'
4, 8, 126, 9, 2, // 102 - 'f'
5, 24, 164, 164, 156, 120, // 103 - 'g'
5, 127, 8, 4, 4, 120, // 104 - 'h'
3, 68, 125, 64, // 105 - 'i'
4, 64, 128, 128, 122, // 106 - 'j'
4, 127, 16, 40, 68, // 107 - 'k'
3, 65, 127, 64, // 108 - 'l'
5, 124, 4, 120, 4, 120, // 109 - 'm'
5, 124, 8, 4, 4, 120, // 110 - 'n'
5, 56, 68, 68, 68, 56, // 111 - 'o'
5, 252, 24, 36, 36, 24, // 112 - 'p'
5, 24, 36, 36, 24, 252, // 113 - 'q'
5, 124, 8, 4, 4, 8, // 114 - 'r'
5, 72, 84, 84, 84, 36, // 115 - 's'
4, 4, 63, 68, 36, // 116 - 't'
5, 60, 64, 64, 32, 124, // 117 - 'u'
5, 28, 32, 64, 32, 28, // 118 - 'v'
5, 60, 64, 48, 64, 60, // 119 - 'w'
5, 68, 40, 16, 40, 68, // 120 - 'x'
5, 76, 144, 144, 144, 124, // 121 - 'y'
5, 68, 100, 84, 76, 68, // 122 - 'z'
3, 8, 54, 65, // 123 - '{'
1, 119, // 124 - '|'
3, 65, 54, 8, // 125 - '}'
5, 2, 1, 2, 4, 2, // 126 - '~'
5, 60, 38, 35, 38, 60, // 127 - 'Hollow Up Arrow'
0, // 128
5, 12, 18, 178, 2, 4, // 129 - 'Arabic ?'
2, 96, 32, // 130 - 'Hamza'
3, 1, 125, 1, // 131 - 'Alef with madda above'
2, 123, 1, // 132 - 'Alef with hamza above'
6, 3, 29, 34, 162, 162, 124, // 133 - 'Waw with hamza above'
2, 192, 95, // 134 - 'Alef with hamza below'
7, 56, 68, 64, 67, 89, 84, 36, // 135 - 'Yeh with hamza above'
1, 127, // 136 - 'Alef'
6, 28, 34, 160, 32, 32, 28, // 137 - 'Beh'
5, 56, 69, 68, 69, 56, // 138 - 'Teh marbuta'
6, 56, 68, 65, 64, 65, 60, // 139 - 'Teh '
6, 56, 68, 64, 66, 65, 58, // 140 - 'Theh'
6, 64, 34, 34, 162, 34, 28, // 141 - 'Jeem'
6, 128, 68, 68, 68, 68, 56, // 142 - 'Hah'
6, 128, 68, 68, 69, 68, 56, // 143 - 'Khah'
3, 64, 68, 56, // 144 - 'Dal'
3, 64, 69, 56, // 145 - 'Thal'
2, 128, 124, // 146 - 'Reh'
2, 128, 125, // 147 - 'Zain'
9, 56, 68, 64, 64, 60, 64, 60, 64, 60, // 148 - 'Seen'
9, 56, 68, 64, 64, 61, 64, 61, 64, 61, // 149 - 'Sheen'
10, 56, 68, 64, 64, 60, 68, 68, 68, 68, 56, // 150 - 'Sad'
10, 56, 68, 64, 64, 60, 68, 68, 69, 68, 56, // 151 - 'Dad'
8, 64, 64, 126, 68, 68, 68, 68, 56, // 152 - 'Tah'
8, 64, 64, 126, 68, 68, 69, 68, 56, // 153 - 'Zah'
5, 184, 68, 68, 68, 72, // 154 - 'Ain'
5, 184, 68, 69, 68, 72, // 155 - 'Ghain'
0, // 156
0, // 157
0, // 158
0, // 159
0, // 160
1, 64, // 161 - 'Tatweel'
9, 56, 68, 64, 64, 72, 84, 85, 84, 56, // 162 - 'Feh'
9, 120, 132, 128, 128, 152, 165, 164, 165, 120, // 163 - 'Qaf'
7, 48, 72, 64, 67, 65, 64, 63, // 164 - 'Kaf'
6, 96, 144, 128, 128, 128, 127, // 165 - 'Lam'
7, 248, 4, 60, 68, 68, 68, 56, // 166 - 'Meem'
5, 56, 68, 64, 65, 60, // 167 - 'Noon'
5, 56, 68, 68, 68, 56, // 168 - 'Heh'
5, 28, 34, 162, 162, 124, // 169 - 'Waw'
7, 56, 68, 64, 64, 88, 84, 36, // 170 - 'Alef maksura'
7, 28, 34, 160, 32, 172, 42, 18, // 171 - 'Yeh'
0, // 172
0, // 173
0, // 174
0, // 175
0, // 176
0, // 177
0, // 178
0, // 179
0, // 180
0, // 181
0, // 182
0, // 183
0, // 184
0, // 185
0, // 186
0, // 187
0, // 188
0, // 189
0, // 190
0, // 191
2, 48, 48, // 192 - 'Zero'
1, 126, // 193 - 'One'
4, 124, 2, 2, 2, // 194 - 'Two'
5, 126, 8, 6, 8, 6, // 195 - 'Three'
4, 52, 74, 74, 74, // 196 - 'Four'
5, 60, 66, 66, 66, 60, // 197 - 'Five'
4, 2, 2, 2, 124, // 198 - 'Six'
5, 62, 64, 64, 64, 62, // 199 - 'Seven'
5, 124, 2, 2, 2, 124, // 200 - 'Eight'
5, 12, 18, 18, 18, 124, // 201 - 'Nine'
0, // 202
0, // 203
0, // 204
0, // 205
0, // 206
0, // 207
0, // 208
0, // 209
0, // 210
0, // 211
0, // 212
0, // 213
0, // 214
0, // 215
0, // 216
0, // 217
0, // 218
0, // 219
0, // 220
0, // 221
0, // 222
0, // 223
0, // 224
0, // 225
0, // 226
0, // 227
0, // 228
0, // 229
0, // 230
0, // 231
0, // 232
0, // 233
0, // 234
0, // 235
0, // 236
0, // 237
0, // 238
0, // 239
0, // 240
0, // 241
0, // 242
0, // 243
0, // 244
0, // 245
0, // 246
0, // 247
0, // 248
0, // 249
0, // 250
0, // 251
0, // 252
0, // 253
0, // 254
0, // 255
};
MD_MAX72XX::fontType_t fontKatakana[] PROGMEM =
{
0, // 0
0, // 1
0, // 2
0, // 3
0, // 4
0, // 5
0, // 6
0, // 7
0, // 8
0, // 9
0, // 10
0, // 11
0, // 12
0, // 13
0, // 14
0, // 15
0, // 16
0, // 17
0, // 18
0, // 19
0, // 20
0, // 21
0, // 22
0, // 23
0, // 24
0, // 25
0, // 26
0, // 27
0, // 28
0, // 29
0, // 30
0, // 31
2,0,0, // 32
0, // 33
0, // 34
0, // 35
0, // 36
0, // 37
0, // 38
0, // 39
0, // 40
0, // 41
0, // 42
0, // 43
0, // 44
0, // 45
0, // 46
0, // 47
0, // 48
0, // 49
0, // 50
0, // 51
0, // 52
0, // 53
0, // 54
0, // 55
0, // 56
0, // 57
0, // 58
0, // 59
0, // 60
0, // 61
0, // 62
0, // 63
0, // 64
0, // 65
0, // 66
0, // 67
0, // 68
0, // 69
0, // 70
0, // 71
0, // 72
0, // 73
0, // 74
0, // 75
0, // 76
0, // 77
0, // 78
0, // 79
0, // 80
0, // 81
0, // 82
0, // 83
0, // 84
0, // 85
0, // 86
0, // 87
0, // 88
0, // 89
0, // 90
0, // 91
0, // 92
0, // 93
0, // 94
0, // 95
0, // 96
0, // 97
0, // 98
0, // 99
0, // 100
0, // 101
0, // 102
0, // 103
0, // 104
0, // 105
0, // 106
0, // 107
0, // 108
0, // 109
0, // 110
0, // 111
0, // 112
0, // 113
0, // 114
0, // 115
0, // 116
0, // 117
0, // 118
0, // 119
0, // 120
0, // 121
0, // 122
0, // 123
0, // 124
0, // 125
0, // 126
0, // 127
0, // 128
0, // 129
0, // 130
0, // 131
0, // 132
0, // 133
0, // 134
0, // 135
0, // 136
0, // 137
0, // 138
0, // 139
0, // 140
0, // 141
0, // 142
0, // 143
0, // 144
0, // 145
0, // 146
0, // 147
0, // 148
0, // 149
0, // 150
0, // 151
0, // 152
0, // 153
0, // 154
0, // 155
0, // 156
0, // 157
0, // 158
0, // 159
0, // 160
3, 112, 80, 112, // 161
3, 15, 1, 1, // 162
3, 64, 64, 120, // 163
3, 16, 32, 64, // 164
2, 12, 12, // 165
5, 10, 10, 74, 42, 30, // 166 - 'wo'
5, 66, 50, 18, 10, 6, // 167
5, 32, 16, 8, 124, 2, // 168
5, 24, 8, 76, 72, 56, // 169
5, 72, 72, 120, 72, 72, // 170
5, 72, 40, 24, 124, 8, // 171
5, 8, 124, 8, 40, 24, // 172
5, 64, 72, 72, 120, 64, // 173
5, 84, 84, 84, 84, 124, // 174
5, 24, 0, 88, 64, 56, // 175
5, 8, 8, 8, 8, 8, // 176
5, 1, 65, 61, 9, 7, // 177 - 'a'
5, 16, 8, 124, 2, 1, // 178 - 'i'
5, 14, 2, 67, 34, 30, // 179 - 'u'
5, 66, 66, 126, 66, 66, // 180 - 'e'
5, 34, 18, 10, 127, 2, // 181 - 'o'
5, 66, 63, 2, 66, 62, // 182 - 'ka'
5, 10, 10, 127, 10, 10, // 183 - 'ki'
5, 8, 70, 66, 34, 30, // 184 - 'ku'
5, 4, 3, 66, 62, 2, // 185 - 'ke'
5, 66, 66, 66, 66, 126, // 186 - 'ko'
5, 2, 79, 34, 31, 2, // 187 - 'sa'
5, 74, 74, 64, 32, 28, // 188 - 'shi'
5, 66, 34, 18, 42, 70, // 189 - 'su'
5, 2, 63, 66, 74, 70, // 190 - 'se'
5, 6, 72, 64, 32, 30, // 191 - 'so'
5, 8, 70, 74, 50, 30, // 192 - 'ta'
5, 10, 74, 62, 9, 8, // 193 - 'chi'
5, 14, 0, 78, 32, 30, // 194 - 'tsu'
5, 4, 69, 61, 5, 4, // 195 - 'te'
3, 127, 8, 16, // 196 - 'to'
5, 68, 36, 31, 4, 4, // 197 - 'na'
5, 32, 36, 36, 36, 32, // 198 - 'ni'
5, 66, 42, 18, 42, 6, // 199 - 'nu'
5, 34, 18, 123, 22, 34, // 200 - 'ne'
3, 64, 32, 31, // 201 - 'no'
5, 120, 0, 2, 4, 120, // 202 - 'ha'
5, 63, 68, 68, 68, 66, // 203 - 'hi'
5, 2, 66, 66, 34, 30, // 204 - 'fu'
5, 4, 2, 4, 8, 48, // 205 - 'he'
5, 50, 2, 127, 2, 50, // 206 - 'ho'
5, 2, 18, 34, 82, 14, // 207 - 'ma'
5, 42, 42, 42, 74, 16, // 208 - 'mi'
5, 56, 36, 34, 32, 112, // 209 - 'mu'
5, 64, 40, 16, 40, 6, // 210 - 'me'
5, 10, 62, 74, 74, 74, // 211 - 'mo'
5, 4, 127, 4, 20, 12, // 212 - 'ye'
6, 64, 66, 66, 126, 64, 64, // 213 - 'yu'
5, 74, 74, 74, 74, 126, // 214 - 'yo'
5, 4, 5, 69, 37, 28, // 215 - 'ra'
4, 15, 64, 32, 31, // 216 - 'ri'
6, 64, 60, 0, 126, 64, 48, // 217 - 'ru'
5, 126, 64, 32, 16, 8, // 218 - 're'
5, 126, 66, 66, 66, 126, // 219 - 'ro'
5, 14, 2, 66, 34, 30, // 220 - 'wa'
5, 66, 66, 64, 32, 24, // 221 - 'n'
4, 4, 8, 2, 4, // 222
3, 14, 10, 14, // 223
5, 56, 68, 72, 48, 76, // 224
5, 32, 85, 84, 85, 120, // 225
5, 252, 42, 42, 42, 20, // 226
5, 40, 84, 84, 68, 32, // 227
5, 252, 32, 32, 16, 60, // 228
5, 56, 68, 76, 84, 36, // 229
5, 240, 40, 36, 36, 24, // 230
5, 16, 168, 168, 168, 120, // 231
5, 32, 64, 62, 2, 2, // 232
4, 4, 4, 0, 14, // 233
4, 64, 128, 136, 122, // 234
3, 5, 2, 5, // 235
5, 24, 36, 126, 36, 16, // 236
5, 20, 127, 84, 64, 64, // 237
5, 124, 9, 5, 5, 120, // 238
5, 56, 69, 68, 69, 56, // 239
5, 252, 40, 36, 36, 24, // 240
5, 24, 36, 36, 40, 252, // 241
5, 62, 69, 69, 69, 62, // 242
5, 48, 40, 16, 40, 24, // 243
5, 88, 100, 4, 100, 88, // 244
5, 60, 65, 64, 33, 124, // 245
5, 99, 85, 73, 65, 65, // 246
5, 66, 62, 2, 126, 66, // 247
5, 69, 41, 17, 41, 69, // 248
5, 24, 160, 160, 160, 120, // 249
5, 20, 20, 124, 20, 18, // 250
5, 68, 60, 20, 20, 116, // 251 - 'Exit (jap)'
5, 124, 20, 28, 20, 124, // 252 - 'Entrance (jap)'
5, 8, 8, 42, 8, 8, // 253 - 'divide'
0, // 254
5, 127, 127, 127, 127, 127, // 255 - '5x7 block'
};
#endif

View File

@@ -0,0 +1,37 @@
// Program to demonstrate the MD_Parola library
//
// Simplest program that does something useful - Hello World!
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 4
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// Hardware SPI connection
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
void setup(void)
{
P.begin();
P.displayText("Hello", PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
}
void loop(void)
{
P.displayAnimate();
}

View File

@@ -0,0 +1,37 @@
// Program to demonstrate the MD_Parola library
//
// Simplest program that does something useful - Hello!
// Uses the Arduino Print Class extension
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 4
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// Hardware SPI connection
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
void setup(void)
{
P.begin();
P.print("Hello!");
}
void loop(void)
{
}

View File

@@ -0,0 +1,55 @@
// Program to demonstrate the MD_Parola library
//
// Uses the Arduino Print Class extension with various output types
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
const uint16_t WAIT_TIME = 1000;
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 4
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// Hardware SPI connection
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
void setup(void)
{
P.begin();
}
void loop(void)
{
P.print("Hello");
delay(WAIT_TIME);
P.print(1234, DEC);
delay(WAIT_TIME);
P.print(1234, HEX);
delay(WAIT_TIME);
P.print(12.5); // float not supported by Arduino Print class
delay(WAIT_TIME);
P.print(9876l);
delay(WAIT_TIME);
P.println("end"); // only get the /r/n characters - avoid using println
delay(WAIT_TIME);
P.write('A');
delay(WAIT_TIME);
P.write('B');
delay(WAIT_TIME);
P.write('C');
delay(WAIT_TIME);
}

View File

@@ -0,0 +1,167 @@
// Use the Parola library to scroll text on the display
//
// Demonstrates the use of the scrolling function to display text received
// from the serial interface
//
// User can enter text on the serial monitor and this will display as a
// scrolling message on the display.
// Speed for the display is controlled by a pot on SPEED_IN analog in.
// Scrolling direction is controlled by a switch on DIRECTION_SET digital in.
// Invert ON/OFF is set by a switch on INVERT_SET digital in.
//
// UISwitch library can be found at https://github.com/MajicDesigns/MD_UISwitch
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
// set to 1 if we are implementing the user interface pot, switch, etc
#define USE_UI_CONTROL 0
#if USE_UI_CONTROL
#include <MD_UISwitch.h>
#endif
// Turn on debug statements to the serial output
#define DEBUG 0
#if DEBUG
#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }
#define PRINTS(x) Serial.print(F(x))
#define PRINTX(x) Serial.println(x, HEX)
#else
#define PRINT(s, x)
#define PRINTS(x)
#define PRINTX(x)
#endif
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 8
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// HARDWARE SPI
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
// Scrolling parameters
#if USE_UI_CONTROL
const uint8_t SPEED_IN = A5;
const uint8_t DIRECTION_SET = 8; // change the effect
const uint8_t INVERT_SET = 9; // change the invert
const uint8_t SPEED_DEADBAND = 5;
#endif // USE_UI_CONTROL
uint8_t scrollSpeed = 25; // default frame delay value
textEffect_t scrollEffect = PA_SCROLL_LEFT;
textPosition_t scrollAlign = PA_LEFT;
uint16_t scrollPause = 2000; // in milliseconds
// Global message buffers shared by Serial and Scrolling functions
#define BUF_SIZE 75
char curMessage[BUF_SIZE] = { "" };
char newMessage[BUF_SIZE] = { "Hello! Enter new message?" };
bool newMessageAvailable = true;
#if USE_UI_CONTROL
MD_UISwitch_Digital uiDirection(DIRECTION_SET);
MD_UISwitch_Digital uiInvert(INVERT_SET);
void doUI(void)
{
// set the speed if it has changed
{
int16_t speed = map(analogRead(SPEED_IN), 0, 1023, 10, 150);
if ((speed >= ((int16_t)P.getSpeed() + SPEED_DEADBAND)) ||
(speed <= ((int16_t)P.getSpeed() - SPEED_DEADBAND)))
{
P.setSpeed(speed);
scrollSpeed = speed;
PRINT("\nChanged speed to ", P.getSpeed());
}
}
if (uiDirection.read() == MD_UISwitch::KEY_PRESS) // SCROLL DIRECTION
{
PRINTS("\nChanging scroll direction");
scrollEffect = (scrollEffect == PA_SCROLL_LEFT ? PA_SCROLL_RIGHT : PA_SCROLL_LEFT);
P.setTextEffect(scrollEffect, scrollEffect);
P.displayClear();
P.displayReset();
}
if (uiInvert.read() == MD_UISwitch::KEY_PRESS) // INVERT MODE
{
PRINTS("\nChanging invert mode");
P.setInvert(!P.getInvert());
}
}
#endif // USE_UI_CONTROL
void readSerial(void)
{
static char *cp = newMessage;
while (Serial.available())
{
*cp = (char)Serial.read();
if ((*cp == '\n') || (cp - newMessage >= BUF_SIZE-2)) // end of message character or full buffer
{
*cp = '\0'; // end the string
// restart the index for next filling spree and flag we have a message waiting
cp = newMessage;
newMessageAvailable = true;
}
else // move char pointer to next position
cp++;
}
}
void setup()
{
Serial.begin(57600);
Serial.print("\n[Parola Scrolling Display]\nType a message for the scrolling display\nEnd message line with a newline");
#if USE_UI_CONTROL
uiDirection.begin();
uiInvert.begin();
pinMode(SPEED_IN, INPUT);
doUI();
#endif // USE_UI_CONTROL
P.begin();
P.displayText(curMessage, scrollAlign, scrollSpeed, scrollPause, scrollEffect, scrollEffect);
}
void loop()
{
#if USE_UI_CONTROL
doUI();
#endif // USE_UI_CONTROL
if (P.displayAnimate())
{
if (newMessageAvailable)
{
strcpy(curMessage, newMessage);
newMessageAvailable = false;
}
P.displayReset();
}
readSerial();
}

View File

@@ -0,0 +1,347 @@
// Use the Parola library to scroll text on the display
//
// Demonstrates the use of the scrolling function to display text received
// from the serial interface
//
// User can enter text through a web browser and this will display as a
// scrolling message on the display. Some parameters for the text can also
// be controlled from the web page.
//
// IP address for the ESP8266 is displayed on the scrolling display
// after startup initialisation and connected to the WiFi network.
//
// Connections for ESP8266 hardware SPI are:
// Vcc 3v3 LED matrices seem to work at 3.3V
// GND GND GND
// DIN D7 HSPID or HMOSI
// CS or LD D8 HSPICS or HCS
// CLK D5 CLK or HCLK
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <ESP8266WiFi.h>
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
// Turn on debug statements to the serial output
#define DEBUG 0
#if DEBUG
#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }
#define PRINTS(x) Serial.print(F(x))
#define PRINTX(x) Serial.println(x, HEX)
#else
#define PRINT(s, x)
#define PRINTS(x)
#define PRINTX(x)
#endif
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers are for ESO8266 hardware SPI and will probably not
// work with your hardware and may need to be adapted
#define MAX_DEVICES 8
#define CLK_PIN D5 // or SCK
#define DATA_PIN D7 // or MOSI
#define CS_PIN D8 // or SS
// HARDWARE SPI
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
// WiFi login parameters - network name and password
const char* ssid = "";
const char* password = "";
// WiFi Server object and parameters
WiFiServer server(80);
// Scrolling parameters
uint8_t frameDelay = 25; // default frame delay value
textEffect_t scrollEffect = PA_SCROLL_LEFT;
// Global message buffers shared by Wifi and Scrolling functions
#define BUF_SIZE 512
char curMessage[BUF_SIZE];
char newMessage[BUF_SIZE];
bool newMessageAvailable = false;
const char WebResponse[] = "HTTP/1.1 200 OK\nContent-Type: text/html\n\n";
char WebPage[] =
"<!DOCTYPE html>" \
"<html>" \
"<head>" \
"<title>MajicDesigns Test Page</title>" \
"<script>" \
"strLine = \"\";" \
"function SendData()" \
"{" \
" nocache = \"/&nocache=\" + Math.random() * 1000000;" \
" var request = new XMLHttpRequest();" \
" strLine = \"&MSG=\" + document.getElementById(\"data_form\").Message.value;" \
" strLine = strLine + \"/&SD=\" + document.getElementById(\"data_form\").ScrollType.value;" \
" strLine = strLine + \"/&I=\" + document.getElementById(\"data_form\").Invert.value;" \
" strLine = strLine + \"/&SP=\" + document.getElementById(\"data_form\").Speed.value;" \
" request.open(\"GET\", strLine + nocache, false);" \
" request.send(null);" \
"}" \
"</script>" \
"</head>" \
"<body>" \
"<p><b>MD_Parola set message</b></p>" \
"<form id=\"data_form\" name=\"frmText\">" \
"<label>Message:<br><input type=\"text\" name=\"Message\" maxlength=\"255\"></label>" \
"<br><br>" \
"<input type = \"radio\" name = \"Invert\" value = \"0\" checked> Normal" \
"<input type = \"radio\" name = \"Invert\" value = \"1\"> Inverse" \
"<br>" \
"<input type = \"radio\" name = \"ScrollType\" value = \"L\" checked> Left Scroll" \
"<input type = \"radio\" name = \"ScrollType\" value = \"R\"> Right Scroll" \
"<br><br>" \
"<label>Speed:<br>Fast<input type=\"range\" name=\"Speed\"min=\"10\" max=\"200\">Slow"\
"<br>" \
"</form>" \
"<br>" \
"<input type=\"submit\" value=\"Send Data\" onclick=\"SendData()\">" \
"</body>" \
"</html>";
char *err2Str(wl_status_t code)
{
switch (code)
{
case WL_IDLE_STATUS: return("IDLE"); break; // WiFi is in process of changing between statuses
case WL_NO_SSID_AVAIL: return("NO_SSID_AVAIL"); break; // case configured SSID cannot be reached
case WL_CONNECTED: return("CONNECTED"); break; // successful connection is established
case WL_CONNECT_FAILED: return("CONNECT_FAILED"); break; // password is incorrect
case WL_DISCONNECTED: return("CONNECT_FAILED"); break; // module is not configured in station mode
default: return("??");
}
}
uint8_t htoi(char c)
{
c = toupper(c);
if ((c >= '0') && (c <= '9')) return(c - '0');
if ((c >= 'A') && (c <= 'F')) return(c - 'A' + 0xa);
return(0);
}
void getData(char *szMesg, uint8_t len)
// Message may contain data for:
// New text (/&MSG=)
// Scroll direction (/&SD=)
// Invert (/&I=)
// Speed (/&SP=)
{
char *pStart, *pEnd; // pointer to start and end of text
// check text message
pStart = strstr(szMesg, "/&MSG=");
if (pStart != NULL)
{
char *psz = newMessage;
pStart += 6; // skip to start of data
pEnd = strstr(pStart, "/&");
if (pEnd != NULL)
{
while (pStart != pEnd)
{
if ((*pStart == '%') && isdigit(*(pStart + 1)))
{
// replace %xx hex code with the ASCII character
char c = 0;
pStart++;
c += (htoi(*pStart++) << 4);
c += htoi(*pStart++);
*psz++ = c;
}
else
*psz++ = *pStart++;
}
*psz = '\0'; // terminate the string
newMessageAvailable = (strlen(newMessage) != 0);
PRINT("\nNew Msg: ", newMessage);
}
}
// check scroll direction
pStart = strstr(szMesg, "/&SD=");
if (pStart != NULL)
{
pStart += 5; // skip to start of data
PRINT("\nScroll direction: ", *pStart);
scrollEffect = (*pStart == 'R' ? PA_SCROLL_RIGHT : PA_SCROLL_LEFT);
P.setTextEffect(scrollEffect, scrollEffect);
P.displayReset();
}
// check invert
pStart = strstr(szMesg, "/&I=");
if (pStart != NULL)
{
pStart += 4; // skip to start of data
PRINT("\nInvert mode: ", *pStart);
P.setInvert(*pStart == '1');
}
// check speed
pStart = strstr(szMesg, "/&SP=");
if (pStart != NULL)
{
pStart += 5; // skip to start of data
int16_t speed = atoi(pStart);
PRINT("\nSpeed: ", P.getSpeed());
P.setSpeed(speed);
frameDelay = speed;
}
}
void handleWiFi(void)
{
static enum { S_IDLE, S_WAIT_CONN, S_READ, S_EXTRACT, S_RESPONSE, S_DISCONN } state = S_IDLE;
static char szBuf[1024];
static uint16_t idxBuf = 0;
static WiFiClient client;
static uint32_t timeStart;
switch (state)
{
case S_IDLE: // initialise
PRINTS("\nS_IDLE");
idxBuf = 0;
state = S_WAIT_CONN;
break;
case S_WAIT_CONN: // waiting for connection
{
client = server.available();
if (!client) break;
if (!client.connected()) break;
#if DEBUG
char szTxt[20];
sprintf(szTxt, "%03d:%03d:%03d:%03d", client.remoteIP()[0], client.remoteIP()[1], client.remoteIP()[2], client.remoteIP()[3]);
PRINT("\nNew client @ ", szTxt);
#endif
timeStart = millis();
state = S_READ;
}
break;
case S_READ: // get the first line of data
PRINTS("\nS_READ ");
while (client.available())
{
char c = client.read();
if ((c == '\r') || (c == '\n'))
{
szBuf[idxBuf] = '\0';
client.flush();
PRINT("\nRecv: ", szBuf);
state = S_EXTRACT;
}
else
szBuf[idxBuf++] = (char)c;
}
if (millis() - timeStart > 1000)
{
PRINTS("\nWait timeout");
state = S_DISCONN;
}
break;
case S_EXTRACT: // extract data
PRINTS("\nS_EXTRACT");
// Extract the string from the message if there is one
getData(szBuf, BUF_SIZE);
state = S_RESPONSE;
break;
case S_RESPONSE: // send the response to the client
PRINTS("\nS_RESPONSE");
// Return the response to the client (web page)
client.print(WebResponse);
client.print(WebPage);
state = S_DISCONN;
break;
case S_DISCONN: // disconnect client
PRINTS("\nS_DISCONN");
client.flush();
client.stop();
state = S_IDLE;
break;
default: state = S_IDLE;
}
}
void setup()
{
Serial.begin(57600);
PRINTS("\n[MD_Parola WiFi Message Display]\nType a message for the scrolling display from your internet browser");
P.begin();
P.displayClear();
P.displaySuspend(false);
P.displayScroll(curMessage, PA_LEFT, scrollEffect, frameDelay);
curMessage[0] = newMessage[0] = '\0';
// Connect to and initialise WiFi network
PRINT("\nConnecting to ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
PRINT("\n", err2Str(WiFi.status()));
delay(500);
}
PRINTS("\nWiFi connected");
// Start the server
server.begin();
PRINTS("\nServer started");
// Set up first message as the IP address
sprintf(curMessage, "%03d:%03d:%03d:%03d", WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3]);
PRINT("\nAssigned IP ", curMessage);
}
void loop()
{
handleWiFi();
if (P.displayAnimate())
{
if (newMessageAvailable)
{
strcpy(curMessage, newMessage);
newMessageAvailable = false;
}
P.displayReset();
}
}

View File

@@ -0,0 +1,211 @@
// Use the Parola library to scroll text on the display
//
// Demonstrates the use of the scrolling function to display text received
// from the serial interface on multiple lines of matrix displays
//
// User can enter text on the serial monitor and this will display as a
// scrolling message on the display.
// Message should be prefixed with the line number on which it should be displayed.
// Speed for the display is controlled by a pot on SPEED_IN analog in.
// Scrolling direction is controlled by a switch on DIRECTION_SET digital in.
// Invert ON/OFF is set by a switch on INVERT_SET digital in.
//
// UISwitch library can be found at https://github.com/MajicDesigns/MD_UISwitch
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
// set to 1 if we are implementing the user interface pot, switch, etc
#define USE_UI_CONTROL 1
#if USE_UI_CONTROL
#include <MD_UISwitch.h>
#endif
// Turn on debug statements to the serial output
#define DEBUG 0
#if DEBUG
#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }
#define PRINTS(x) Serial.print(F(x))
#define PRINTX(x) Serial.println(x, HEX)
#else
#define PRINT(s, x)
#define PRINTS(x)
#define PRINTX(x)
#endif
// Define the number of devices we have in the chain and the hardware interface
#define MAX_DEVICES 4
#define BUF_SIZE 75
struct LineDefinition
{
MD_Parola P; // object definition
char curMessage[BUF_SIZE]; // message for this display
boolean newMessageAvailable; // true if new message arrived
};
// Add new entries for more lines.
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
struct LineDefinition Line[] =
{
{ MD_Parola(11, 13, 10, MAX_DEVICES), "abc", false },
{ MD_Parola(11, 13, 9, MAX_DEVICES), "def", false }
};
#define MAX_LINES (sizeof(Line)/sizeof(LineDefinition))
#define PAUSE_TIME 1000
#define SPEED_DEADBAND 5
// Scrolling parameters
#if USE_UI_CONTROL
#define SPEED_IN A5
#define DIRECTION_SET 8 // change the effect
#define INVERT_SET 9 // change the invert
#endif // USE_UI_CONTROL
uint8_t frameDelay = 25; // default frame delay value
textEffect_t scrollEffect = PA_SCROLL_LEFT;
// Global message buffer shared by Serial and Scrolling functions
char newMessage[BUF_SIZE];
uint8_t putLine = 0;
#if USE_UI_CONTROL
MD_UISwitch_Digital uiDirection(DIRECTION_SET);
MD_UISwitch_Digital uiInvert(INVERT_SET);
void doUI(void)
{
// set the speed if it has changed
{
int16_t speed = map(analogRead(SPEED_IN), 0, 1023, 10, 150);
if ((speed >= ((int16_t)Line[0].P.getSpeed() + SPEED_DEADBAND)) ||
(speed <= ((int16_t)Line[0].P.getSpeed() - SPEED_DEADBAND)))
{
for (uint8_t i=0; i<MAX_LINES; i++)
{
Line[i].P.setSpeed(speed);
Line[i].P.setPause(speed);
frameDelay = speed;
}
PRINT("\nChanged speed to ", Line[0].P.getSpeed());
}
}
if (uiDirection.read() == MD_UISwitch::KEY_PRESS) // SCROLL DIRECTION
{
PRINTS("\nChanging scroll direction");
scrollEffect = (scrollEffect == PA_SCROLL_LEFT ? PA_SCROLL_RIGHT : PA_SCROLL_LEFT);
for (uint8_t i=0; i<MAX_LINES; i++)
{
Line[i].P.setTextEffect(scrollEffect, scrollEffect);
Line[i].P.displayReset();
}
}
if (uiInvert.read() == MD_UISwitch::KEY_PRESS) // INVERT MODE
{
PRINTS("\nChanging invert mode");
for (uint8_t i=0; i<MAX_LINES; i++)
{
Line[i].P.setInvert(!Line[i].P.getInvert());
}
}
}
#endif // USE_UI_CONTROL
void readSerial(void)
{
static int16_t putIndex = -1;
char c;
while (Serial.available())
{
c = (char)Serial.read();
if (putIndex == -1) // first character should be the line number
{
if ((c >= '0') && (c < '0' + MAX_LINES))
{
putLine = c - '0';
putIndex = 0;
}
}
else if ((c == '\n') || (putIndex >= BUF_SIZE-2)) // end of message character or full buffer
{
// put in a message separator and end the string
newMessage[putIndex] = '\0';
// restart the index for next filling spree and flag we have a message waiting
putIndex = -1;
Line[putLine].newMessageAvailable = true;
} else
// Just save the next char in next location
newMessage[putIndex++] = c;
}
}
void setup()
{
Serial.begin(57600);
#if USE_UI_CONTROL
uiDirection.begin();
uiInvert.begin();
pinMode(SPEED_IN, INPUT);
doUI();
#endif // USE_UI_CONTROL
for (uint8_t i=0; i<MAX_LINES; i++)
{
Line[i].P.begin();
Line[i].P.displayClear();
Line[i].P.displaySuspend(false);
Line[i].P.displayScroll(Line[i].curMessage, PA_LEFT, scrollEffect, frameDelay);
strcpy(Line[i].curMessage, "Hello! Enter new message?");
}
newMessage[0] = '\0';
Serial.begin(57600);
Serial.print("\n[Parola Scrolling Display Multi Line]\n");
Serial.print(MAX_LINES);
Serial.print(" lines\nType a message for the scrolling display\nStart message with display number\nEnd message line with a newline");
}
void loop()
{
#if USE_UI_CONTROL
doUI();
#endif // USE_UI_CONTROL
readSerial();
for (uint8_t i=0; i<MAX_LINES; i++)
{
if (Line[i].P.displayAnimate())
{
if (Line[i].newMessageAvailable)
{
strcpy(Line[i].curMessage, newMessage);
Line[i].newMessageAvailable = false;
PRINT("\nLine ", i);
PRINT(" msg: ", newMessage);
}
Line[i].P.displayReset();
}
}
}

View File

@@ -0,0 +1,444 @@
// Use the Parola library to scroll text on the display
//
// Demonstrates the use of the scrolling function to display text received
// from the serial interface and shared with a menu to change the parameters
// for the scrolling display and save to EEPROM.
//
// User can enter text on the serial monitor and this will display as a
// scrolling message on the display.
//
// Speed, scroll direction, brightness and invert are controlled from the menu.
//
// Interface for menu control can be either 3 momentary on (tact) switches or
// a rotary encoder with integrated switch.
//
// UISwitch library can be found at https://github.com/MajicDesigns/MD_UISwitch
// Rotary Encoder library can be found at https://github.com/MajicDesigns/MD_REncoder
// Menu library can be found at https://github.com/MajicDesigns/MD_Menu
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <EEPROM.h>
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include <MD_Menu.h>
// set to 1 if depending on the menu control interface
#define MENU_SWITCH 0 // tact switches
#define MENU_RENCODER 1 // rotary encoder
const uint16_t MENU_TIMEOUT = 5000; // in milliseconds
const uint16_t EEPROM_ADDRESS = 0; // config data address
// Turn on debug statements to the serial output
#define DEBUG 1
#if DEBUG
#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }
#define PRINTS(x) Serial.print(F(x))
#define PRINTX(x) Serial.println(x, HEX)
#else
#define PRINT(s, x)
#define PRINTS(x)
#define PRINTX(x)
#endif
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 8
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// HARDWARE SPI
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
// Scrolling parameters configuration block
struct cfgParameter_t
{
uint8_t signature[2]; // signature for EEPROM
uint8_t speed; // animation frame delay
uint16_t pause = 2000;// animation pause in milliseconds
uint8_t bright; // display intensity
textEffect_t effect; // text animation effect
textPosition_t align; // text alignment at pause
bool invert = false; // inverted display
} Config;
// Global message buffers shared by Serial and Scrolling functions
#define BUF_SIZE 75
char curMessage[BUF_SIZE] = { "" };
char newMessage[BUF_SIZE] = { "Hello! Enter new message?" };
bool newMessageAvailable = true;
// Function prototypes for Navigation/Display
bool display(MD_Menu::userDisplayAction_t, char*);
MD_Menu::userNavAction_t navigation(uint16_t &incDelta);
void *mnuValueRqst(MD_Menu::mnuId_t id, bool bGet);
// Menu definition
const PROGMEM MD_Menu::mnuHeader_t mnuHdr[] =
{
{ 10, "Menu", 10, 15, 0 },
};
const PROGMEM MD_Menu::mnuItem_t mnuItm[] =
{
// Starting (Root) menu
{ 10, "Speed", MD_Menu::MNU_INPUT, 10 },
{ 11, "Pause", MD_Menu::MNU_INPUT, 11 },
{ 12, "Scroll", MD_Menu::MNU_INPUT, 12 },
{ 13, "Align", MD_Menu::MNU_INPUT, 13 },
{ 14, "Bright", MD_Menu::MNU_INPUT, 14 },
{ 15, "Invert", MD_Menu::MNU_INPUT, 15 },
};
const PROGMEM char listAlign[] = "L|C|R";
const PROGMEM char listScroll[] = "L|R";
const PROGMEM MD_Menu::mnuInput_t mnuInp[] =
{
{ 10, "Spd", MD_Menu::INP_INT, mnuValueRqst, 3, 0, 0, 255, 0, 10, nullptr },
{ 11, "Pse", MD_Menu::INP_INT, mnuValueRqst, 4, 0, 0, 2000, 0, 10, nullptr },
{ 12, "Scrl", MD_Menu::INP_LIST, mnuValueRqst, 1, 0, 0, 0, 0, 0, listScroll },
{ 13, "Algn", MD_Menu::INP_LIST, mnuValueRqst, 1, 0, 0, 0, 0, 0, listAlign },
{ 14, "Bri", MD_Menu::INP_INT, mnuValueRqst, 2, 0, 0, 15, 0, 10, nullptr },
{ 15, "Inv", MD_Menu::INP_BOOL, mnuValueRqst, 1, 0, 0, 0, 0, 0, nullptr },
};
// Menu global object
MD_Menu M(navigation, display,// user navigation and display
mnuHdr, ARRAY_SIZE(mnuHdr), // menu header data
mnuItm, ARRAY_SIZE(mnuItm), // menu item data
mnuInp, ARRAY_SIZE(mnuInp));// menu input data
// Configuration Load/Save to/from EEPROM
void paramSave(void)
{
PRINTS("\nSaving Parameters");
EEPROM.put(EEPROM_ADDRESS, Config);
}
void paramLoad(void)
{
uint8_t sig[2] = { 0xa5, 0x5a };
PRINTS("\nLoading Parameters");
EEPROM.get(EEPROM_ADDRESS, Config);
if (Config.signature[0] != sig[0] ||
Config.signature[1] != sig[1])
{
PRINTS("\n\nSetting Default Parameters");
Config.signature[0] = sig[0];
Config.signature[1] = sig[1];
Config.speed = 25;
Config.bright = 7;
Config.effect = PA_SCROLL_LEFT;
Config.align = PA_LEFT;
Config.pause = 2000;
Config.invert = false;
paramSave();
}
}
// Menu system callback functions
void *mnuValueRqst(MD_Menu::mnuId_t id, bool bGet)
// Value request callback for variables
{
static MD_Menu::value_t v;
switch (id)
{
case 10: // Speed
if (bGet)
v.value = Config.speed;
else
{
Config.speed = v.value;
P.setSpeed(Config.speed);
PRINT("\nSet speed: ", Config.speed);
}
break;
case 11: // Pause
if (bGet)
v.value = Config.pause;
else
{
Config.pause = v.value;
P.setPause(Config.pause);
PRINT("\nSet pause: ", Config.pause);
}
break;
case 12: // Scroll
if (bGet)
v.value = (Config.effect == PA_SCROLL_LEFT ? 0 : 1);
else
{
Config.effect = (v.value == 0 ? PA_SCROLL_LEFT : PA_SCROLL_RIGHT);
P.setTextEffect(Config.effect, Config.effect);
PRINT("\nSet scroll effect: ", Config.effect);
}
break;
case 13: // Align
if (bGet)
{
switch (Config.align)
{
case PA_LEFT: v.value = 0; break;
case PA_CENTER: v.value = 1; break;
case PA_RIGHT: v.value = 2; break;
}
}
else
{
switch (v.value)
{
case 0: Config.align = PA_LEFT; break;
case 1: Config.align = PA_CENTER; break;
case 2: Config.align = PA_RIGHT; break;
}
P.setTextAlignment(Config.align);
PRINT("\nSet align: ", Config.align);
}
break;
case 14: // Bright
if (bGet)
v.value = Config.bright;
else
{
Config.bright = v.value;
P.setIntensity(Config.bright);
PRINT("\nSet intensity: ", Config.bright);
}
break;
case 15: // Invert
if (bGet)
v.value = Config.invert;
else
{
Config.invert = v.value;
P.setInvert(Config.invert);
PRINT("\nSet invert: ", Config.invert);
}
break;
}
// if things were requested, return the buffer
if (bGet)
return(&v);
else // save the parameters
paramSave();
return(nullptr);
}
bool display(MD_Menu::userDisplayAction_t action, char *msg)
// Simple output to a one line LED Matrix display managed
// by the Parola library.
{
switch (action)
{
case MD_Menu::DISP_CLEAR:
P.displayClear();
break;
case MD_Menu::DISP_L0:
// P.print(msg); // only one zone, no line 0
break;
case MD_Menu::DISP_L1:
P.print(msg);
break;
}
return(true);
}
#if MENU_SWITCH
// Implemented as momentary on 3 switches
// one switch each for INC, DEC
// one switch for SEL (click) or ESC (long press)
#include <MD_UISwitch.h>
const uint8_t INC_PIN = 9;
const uint8_t DEC_PIN = 8;
const uint8_t CTL_PIN = 6;
uint8_t pins[] = { INC_PIN, DEC_PIN, CTL_PIN };
MD_UISwitch_Digital swNav(pins, ARRAY_SIZE(pins));
void setupNav(void)
{
swNav.begin();
swNav.enableRepeat(false);
}
MD_Menu::userNavAction_t navigation(uint16_t &incDelta)
{
MD_Menu::userNavAction_t nav = MD_Menu::NAV_NULL;
switch (swNav.read())
{
case MD_UISwitch::KEY_PRESS:
{
switch (swNav.getKey())
{
case INC_PIN: nav = MD_Menu::NAV_INC; break;
case DEC_PIN: nav = MD_Menu::NAV_DEC; break;
case ESC_PIN: nav = MD_Menu::NAV_SEL; break;
}
}
break;
case MD_UISwitch::KEY_LONGPRESS:
{
if (swNav.getKey() == 2)
nav = MD_Menu::NAV_ESC;
}
break;
}
return(nav);
}
#endif // USE_UI_CONTROL
#if MENU_RENCODER
// Implemented as a rotary encoder with integrated push switch.
// Rotate encoder clockwise for INC, anti-clockwise for DEC
// Switch for SEL (press) or ESC (long press)
//
// If a value is being edited, the rotary encoder will also apply
// a factor for how fast the RE is being turned to increase the rate
// of change of values. This will be applied by the menu library to
// numeric input only.
#include <MD_REncoder.h>
#include <MD_UISwitch.h>
extern MD_Menu M;
const uint8_t RE_A_PIN = 2;
const uint8_t RE_B_PIN = 3;
const uint8_t CTL_PIN = 4;
MD_REncoder RE(RE_A_PIN, RE_B_PIN);
MD_UISwitch_Digital swCtl(CTL_PIN);
void setupNav(void)
{
RE.begin();
swCtl.begin();
swCtl.enableRepeat(false);
}
MD_Menu::userNavAction_t navigation(uint16_t &incDelta)
{
uint8_t re = RE.read();
if (re != DIR_NONE)
{
if (M.isInEdit()) incDelta = 1 << abs(RE.speed() >> 3);
return(re == DIR_CCW ? MD_Menu::NAV_DEC : MD_Menu::NAV_INC);
}
switch (swCtl.read())
{
case MD_UISwitch::KEY_PRESS: return(MD_Menu::NAV_SEL);
case MD_UISwitch::KEY_LONGPRESS: return(MD_Menu::NAV_ESC);
}
return(MD_Menu::NAV_NULL);
}
#endif
// Serial input for new message
void readSerial(void)
{
static char *cp = newMessage;
while (Serial.available())
{
*cp = (char)Serial.read();
if ((*cp == '\n') || (cp - newMessage >= BUF_SIZE-2)) // end of message character or full buffer
{
*cp = '\0'; // end the string
// restart the index for next filling spree and flag we have a message waiting
cp = newMessage;
newMessageAvailable = true;
}
else // move char pointer to next position
cp++;
}
}
void setup()
{
Serial.begin(57600);
Serial.print("\n[Parola Scrolling Display]\nPress SEL button for configuration menu");
Serial.print("\nType a message for the scrolling display\nEnd message line with a newline");
paramLoad();
setupNav();
M.begin();
M.setAutoStart(true);
M.setTimeout(MENU_TIMEOUT);
P.begin();
P.setInvert(Config.invert);
P.setIntensity(Config.bright);
}
void loop()
{
static bool wasInMenu = true; // ensure we initialise the display first
if (wasInMenu && !M.isInMenu()) // was running, but not any more
{
// Reset the display to show message
PRINTS("\nMenu Stopped, running message");
P.displayClear();
P.displayText(curMessage, Config.align, Config.speed, Config.pause, Config.effect, Config.effect);
wasInMenu = false;
}
wasInMenu = M.isInMenu(); // save current status
M.runMenu(); // run or autostart the menu
if (!M.isInMenu()) // not running the menu? do something else
{
// animate display and check swap message if ended
if (P.displayAnimate())
{
if (newMessageAvailable)
{
strcpy(curMessage, newMessage);
newMessageAvailable = false;
}
P.displayReset();
}
}
readSerial(); // receive new serial characters
}

View File

@@ -0,0 +1,148 @@
// Use the Parola library to scroll text on the display
//
// Demonstrates the use of the scrolling function to display text received
// from the serial interface and how to adjust the spacing between the end
// of one message at the start of the following one.
//
// User can enter text on the serial monitor and this will display as a
// scrolling message on the display.
// Spacing for the display is controlled by a pot on SPACE_IN analog in.
// Scrolling direction is controlled by a switch on DIRECTION_SET digital in.
// Invert ON/OFF is set by a switch on INVERT_SET digital in.
//
// UISwitch library can be found at https://github.com/MajicDesigns/MD_UISwitch
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include <MD_UISwitch.h>
// Turn on debug statements to the serial output
#define DEBUG 0
#if DEBUG
#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }
#define PRINTS(x) Serial.print(F(x))
#define PRINTX(x) Serial.println(x, HEX)
#else
#define PRINT(s, x)
#define PRINTS(x)
#define PRINTX(x)
#endif
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 8
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// HARDWARE SPI
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
#define PAUSE_TIME 0
#define FRAME_TIME 50
#define SPACE_DEADBAND 2
// Scrolling parameters
#define SPACE_IN A5
#define DIRECTION_SET 8 // change the effect
#define INVERT_SET 9 // change the invert
textEffect_t scrollEffect = PA_SCROLL_LEFT;
// Global message buffers shared by Serial and Scrolling functions
#define BUF_SIZE 75
char curMessage[BUF_SIZE] = { "" };
char newMessage[BUF_SIZE] = { "Hi! Enter new message?" };
bool newMessageAvailable = true;
MD_UISwitch_Digital uiDirection(DIRECTION_SET);
MD_UISwitch_Digital uiInvert(INVERT_SET);
void doUI(void)
{
// SPACING
{
uint16_t space = map(analogRead(SPACE_IN), 0, 1023, 0, (MAX_DEVICES+1)*COL_SIZE);
if (space != P.getScrollSpacing())
{
P.setScrollSpacing(space);
PRINT("\nChanged spacing to ", P.getScrollSpacing());
}
}
if (uiDirection.read() == MD_UISwitch::KEY_PRESS) // SCROLL DIRECTION
{
PRINTS("\nChanging scroll direction");
scrollEffect = (scrollEffect == PA_SCROLL_LEFT ? PA_SCROLL_RIGHT : PA_SCROLL_LEFT);
P.setTextEffect(scrollEffect, scrollEffect);
P.displayReset();
}
if (uiInvert.read() == MD_UISwitch::KEY_PRESS) // INVERT MODE
{
PRINTS("\nChanging invert mode");
P.setInvert(!P.getInvert());
}
}
void readSerial(void)
{
static char *cp = newMessage;
while (Serial.available())
{
*cp = (char)Serial.read();
if ((*cp == '\n') || (cp - newMessage >= BUF_SIZE-2)) // end of message character or full buffer
{
*cp = '\0'; // end the string
// restart the index for next filling spree and flag we have a message waiting
cp = newMessage;
newMessageAvailable = true;
}
else // move char pointer to next position
cp++;
}
}
void setup()
{
Serial.begin(57600);
Serial.print("\n[Parola Scrolling Spacing]\nType a message for the scrolling display\nEnd message line with a newline");
uiDirection.begin();
uiInvert.begin();
pinMode(SPACE_IN, INPUT);
doUI();
P.begin();
P.displayText(curMessage, PA_CENTER, FRAME_TIME, PAUSE_TIME, scrollEffect, scrollEffect);
}
void loop()
{
doUI();
if (P.displayAnimate())
{
if (newMessageAvailable)
{
strcpy(curMessage, newMessage);
newMessageAvailable = false;
}
P.displayReset();
}
readSerial();
}

View File

@@ -0,0 +1,265 @@
// Data file for user example user defined fonts
#ifndef FONTS_DATA_H
#define FONTS_DATA_H
MD_MAX72XX::fontType_t _fontVertical[] PROGMEM = {
0, // 0 - 'Empty Cell'
7, 28, 34, 54, 62, 42, 62, 28, // 1 - 'Sad Smiley'
7, 28, 54, 34, 62, 42, 62, 28, // 2 - 'Happy Smiley'
6, 8, 28, 62, 62, 62, 20, // 3 - 'Heart'
6, 8, 28, 62, 62, 28, 8, // 4 - 'Diamond'
7, 28, 8, 62, 42, 62, 20, 28, // 5 - 'Clubs'
7, 28, 8, 62, 62, 62, 28, 8, // 6 - 'Spades'
4, 8, 28, 28, 8, // 7 - 'Bullet Point'
8, 62, 62, 54, 34, 34, 54, 62, 62, // 8 - 'Rev Bullet Point'
4, 8, 20, 20, 8, // 9 - 'Hollow Bullet Point'
8, 62, 62, 54, 42, 42, 54, 62, 62, // 10 - 'Rev Hollow BP'
6, 4, 10, 10, 44, 48, 56, // 11 - 'Male'
7, 8, 62, 8, 28, 34, 34, 28, // 12 - 'Female'
7, 6, 4, 4, 4, 60, 36, 60, // 13 - 'Music Note 1'
7, 6, 52, 36, 36, 60, 36, 60, // 14 - 'Music Note 2'
8, 8, 42, 28, 54, 54, 28, 42, 8, // 15 - 'Snowflake'
7, 2, 6, 30, 62, 30, 6, 2, // 16 - 'Right Pointer'
7, 32, 48, 60, 62, 60, 48, 32, // 17 - 'Left Pointer'
7, 8, 28, 42, 8, 42, 28, 8, // 18 - 'UpDown Arrows'
7, 54, 0, 54, 54, 54, 54, 54, // 19 - 'Double Exclamation'
7, 40, 40, 40, 44, 42, 42, 60, // 20 - 'Paragraph Mark'
8, 12, 18, 18, 8, 20, 10, 18, 12, // 21 - 'Section Mark'
2, 62, 62, // 22 - 'Double Underline'
8, 62, 8, 28, 42, 8, 42, 28, 8, // 23 - 'UpDown Underlined'
6, 8, 8, 8, 42, 28, 8, // 24 - 'Up Arrow'
6, 8, 28, 42, 8, 8, 8, // 25 - 'Down Arrow'
5, 8, 16, 62, 16, 8, // 26 - 'Right Arrow'
5, 8, 4, 62, 4, 8, // 27 - 'Left Arrow'
5, 0, 62, 2, 2, 2, // 28 - 'Angled'
4, 20, 62, 62, 20, // 29 - 'Squashed #'
5, 62, 62, 28, 8, 8, // 30 - 'Up Pointer'
5, 8, 8, 28, 62, 62, // 31 - 'Down Pointer'
2, 0, 0, // 32 - 'Space'
7, 8, 0, 8, 8, 8, 8, 8, // 33 - '!'
4, 0, 20, 20, 20, // 34 - '"'
7, 20, 20, 62, 20, 62, 20, 20, // 35 - '#'
7, 8, 30, 40, 28, 10, 60, 8, // 36 - '$'
7, 48, 50, 4, 8, 16, 38, 6, // 37 - '%'
7, 44, 18, 42, 4, 10, 10, 4, // 38 - '&'
4, 4, 8, 24, 24, // 39 - '''
8, 0, 16, 8, 4, 4, 4, 8, 16, // 40 - '('
8, 0, 4, 8, 16, 16, 16, 8, 4, // 41 - ')'
8, 0, 8, 42, 28, 62, 28, 42, 8, // 42 - '*'
5, 8, 8, 62, 8, 8, // 43 - '+'
4, 4, 8, 24, 24, // 44 - ','
1, 62, // 45 - '-'
2, 12, 12, // 46 - '.'
5, 2, 4, 8, 16, 32, // 47 - '/'
7, 28, 34, 38, 42, 50, 34, 28, // 48 - '0'
7, 28, 8, 8, 8, 8, 12, 8, // 49 - '1'
7, 62, 2, 2, 28, 32, 34, 28, // 50 - '2'
7, 28, 34, 32, 24, 16, 32, 62, // 51 - '3'
7, 16, 16, 62, 18, 20, 24, 16, // 52 - '4'
7, 28, 34, 32, 32, 30, 2, 62, // 53 - '5'
7, 28, 34, 34, 30, 2, 4, 56, // 54 - '6'
7, 2, 4, 8, 16, 32, 32, 62, // 55 - '7'
7, 28, 34, 34, 28, 34, 34, 28, // 56 - '8'
7, 14, 16, 32, 60, 34, 34, 28, // 57 - '9'
3, 8, 0, 8, // 58 - ':'
5, 4, 8, 8, 0, 8, // 59 - ';'
7, 32, 16, 8, 4, 8, 16, 32, // 60 - '<'
3, 62, 0, 62, // 61 - '='
7, 4, 8, 16, 32, 16, 8, 4, // 62 - '>'
7, 8, 0, 8, 24, 32, 34, 28, // 63 - '?'
7, 60, 2, 26, 58, 42, 34, 28, // 64 - '@'
7, 34, 34, 62, 34, 34, 20, 8, // 65 - 'A'
7, 30, 34, 34, 30, 34, 34, 30, // 66 - 'B'
7, 28, 34, 2, 2, 2, 34, 28, // 67 - 'C'
7, 30, 34, 34, 34, 34, 34, 30, // 68 - 'D'
7, 62, 2, 2, 30, 2, 2, 62, // 69 - 'E'
7, 2, 2, 2, 30, 2, 2, 62, // 70 - 'F'
7, 60, 34, 50, 2, 2, 34, 60, // 71 - 'G'
7, 34, 34, 34, 62, 34, 34, 34, // 72 - 'H'
7, 28, 8, 8, 8, 8, 8, 28, // 73 - 'I'
7, 12, 18, 16, 16, 16, 16, 56, // 74 - 'J'
7, 34, 18, 10, 6, 10, 18, 34, // 75 - 'K'
7, 62, 2, 2, 2, 2, 2, 2, // 76 - 'L'
7, 34, 34, 42, 42, 42, 54, 34, // 77 - 'M'
7, 34, 34, 50, 42, 38, 34, 34, // 78 - 'N'
7, 28, 34, 34, 34, 34, 34, 28, // 79 - 'O'
7, 2, 2, 2, 30, 34, 34, 30, // 80 - 'P'
7, 44, 18, 42, 34, 34, 34, 28, // 81 - 'Q'
7, 34, 18, 10, 30, 34, 34, 30, // 82 - 'R'
7, 28, 34, 32, 28, 2, 34, 28, // 83 - 'S'
7, 8, 8, 8, 8, 8, 42, 62, // 84 - 'T'
7, 28, 34, 34, 34, 34, 34, 34, // 85 - 'U'
7, 8, 20, 34, 34, 34, 34, 34, // 86 - 'V'
7, 20, 42, 42, 42, 34, 34, 34, // 87 - 'W'
7, 34, 34, 20, 8, 20, 34, 34, // 88 - 'X'
7, 8, 8, 8, 8, 20, 34, 34, // 89 - 'Y'
7, 62, 2, 4, 28, 16, 32, 62, // 90 - 'Z'
7, 28, 4, 4, 4, 4, 4, 28, // 91 - '['
5, 32, 16, 8, 4, 2, // 92 - '\'
7, 28, 16, 16, 16, 16, 16, 28, // 93 - ']'
5, 0, 0, 34, 20, 8, // 94 - '^'
1, 62, // 95 - '_'
6, 0, 0, 16, 8, 12, 12, // 96 - '`'
5, 60, 18, 28, 16, 12, // 97 - 'a'
7, 26, 38, 34, 38, 26, 2, 2, // 98 - 'b'
5, 28, 34, 2, 34, 28, // 99 - 'c'
7, 44, 50, 34, 50, 44, 32, 32, // 100 - 'd'
5, 28, 2, 62, 34, 28, // 101 - 'e'
7, 8, 8, 8, 28, 8, 40, 16, // 102 - 'f'
7, 28, 34, 32, 44, 50, 50, 28, // 103 - 'g'
7, 34, 34, 34, 38, 26, 2, 2, // 104 - 'h'
8, 28, 8, 8, 8, 8, 12, 0, 8, // 105 - 'i'
8, 12, 18, 18, 16, 16, 16, 0, 16, // 106 - 'j'
7, 18, 10, 6, 10, 18, 2, 2, // 107 - 'k'
7, 28, 8, 8, 8, 8, 8, 12, // 108 - 'l'
5, 42, 42, 42, 42, 22, // 109 - 'm'
5, 34, 34, 34, 38, 26, // 110 - 'n'
5, 28, 34, 34, 34, 28, // 111 - 'o'
7, 2, 2, 2, 26, 38, 38, 26, // 112 - 'p'
7, 32, 32, 32, 44, 50, 50, 44, // 113 - 'q'
5, 2, 2, 2, 38, 26, // 114 - 'r'
5, 30, 32, 28, 2, 60, // 115 - 's'
7, 8, 20, 4, 4, 30, 4, 4, // 116 - 't'
5, 44, 50, 34, 34, 34, // 117 - 'u'
5, 8, 20, 34, 34, 34, // 118 - 'v'
5, 20, 42, 42, 34, 34, // 119 - 'w'
5, 34, 20, 8, 20, 34, // 120 - 'x'
7, 28, 34, 32, 60, 34, 34, 34, // 121 - 'y'
5, 62, 4, 8, 16, 62, // 122 - 'z'
7, 16, 8, 8, 4, 8, 8, 16, // 123 - '{'
7, 8, 8, 8, 0, 8, 8, 8, // 124 - '|'
7, 4, 8, 8, 16, 8, 8, 4, // 125 - '}'
3, 16, 42, 4, // 126 - '~'
6, 62, 34, 34, 54, 28, 8, // 127 - 'Hollow Up Arrow'
8, 12, 16, 28, 34, 2, 2, 34, 28, // 128 - 'C sedilla'
6, 44, 50, 34, 34, 0, 20, // 129 - 'u umlaut'
7, 60, 2, 62, 34, 28, 0, 48, // 130 - 'e acute'
7, 60, 18, 28, 16, 12, 0, 62, // 131 - 'a accent'
7, 60, 18, 28, 16, 12, 0, 34, // 132 - 'a umlaut'
7, 60, 18, 28, 16, 12, 0, 6, // 133 - 'a grave'
7, 60, 18, 28, 16, 12, 0, 24, // 134 - 'a acute'
6, 24, 16, 60, 6, 6, 60, // 135 - 'c sedilla'
7, 60, 2, 62, 34, 28, 0, 62, // 136 - 'e accent'
7, 60, 2, 62, 34, 28, 0, 20, // 137 - 'e umlaut'
7, 60, 2, 62, 34, 28, 0, 6, // 138 - 'e grave'
7, 28, 8, 8, 8, 12, 0, 20, // 139 - 'i umlaut'
7, 28, 8, 8, 8, 12, 18, 12, // 140 - 'i hat'
7, 28, 8, 8, 8, 12, 0, 6, // 141 - 'i grave'
9, 34, 34, 62, 34, 34, 20, 8, 0, 20, // 142 - 'A umlaut'
9, 34, 34, 62, 34, 34, 20, 8, 0, 8, // 143 - 'A dot'
9, 30, 2, 2, 14, 2, 2, 30, 0, 24, // 144 - 'E grave'
5, 124, 18, 124, 144, 124, // 145 - 'ae'
7, 242, 18, 18, 254, 18, 20, 248, // 146 - 'AE'
7, 28, 34, 34, 28, 0, 34, 28, // 147 - 'o hat'
6, 28, 34, 34, 28, 0, 20, // 148 - 'o umlaut'
6, 28, 34, 34, 28, 0, 6, // 149 - 'o grave'
7, 44, 50, 34, 34, 0, 34, 28, // 150 - 'u hat'
6, 44, 50, 34, 34, 0, 6, // 151 - 'u grave'
8, 14, 16, 28, 18, 18, 18, 0, 18, // 152 - 'y umlaut'
9, 28, 34, 34, 34, 34, 34, 28, 0, 20, // 153 - 'O umlaut'
9, 28, 34, 34, 34, 34, 34, 34, 0, 20, // 154 - 'U umlaut'
8, 8, 8, 62, 10, 10, 62, 8, 8, // 155 - 'Cents'
7, 62, 36, 4, 14, 36, 52, 24, // 156 - 'Pounds'
8, 8, 8, 62, 8, 62, 28, 54, 54, // 157 - 'Yen'
8, 18, 18, 58, 18, 14, 18, 18, 14, // 158 - 'R +'
8, 6, 10, 8, 8, 28, 8, 40, 48, // 159 - 'f notation'
7, 60, 18, 28, 16, 12, 0, 48, // 160 - 'a acute'
7, 28, 8, 8, 8, 12, 0, 24, // 161 - 'i acute'
6, 28, 34, 34, 28, 0, 48, // 162 - 'o acute'
6, 44, 50, 34, 34, 0, 48, // 163 - 'u acute'
7, 18, 18, 18, 18, 14, 0, 30, // 164 - 'n accent'
9, 34, 50, 50, 42, 42, 38, 38, 0, 62, // 165 - 'N accent'
6, 62, 0, 60, 18, 18, 28, // 166
6, 62, 0, 28, 34, 34, 28, // 167
7, 28, 34, 2, 12, 8, 0, 8, // 168 - 'Inverted ?'
3, 2, 2, 62, // 169
3, 32, 32, 62, // 170
8, 56, 8, 50, 36, 58, 18, 34, 2, // 171 - '1/2'
8, 32, 32, 58, 52, 42, 18, 34, 2, // 172 - '1/4'
7, 8, 8, 8, 8, 0, 8, 8, // 173 - '| split'
5, 40, 20, 10, 20, 40, // 174 - '<<'
5, 10, 20, 40, 20, 10, // 175 - '>>'
8, 17, 68, 17, 68, 17, 68, 17, 68, // 176 - '30% shading'
8, 170, 85, 170, 85, 170, 85, 170, 85, // 177 - '50% shading'
8, 16, 16, 16, 16, 16, 16, 16, 16, // 178 - 'Right side'
8, 16, 16, 16, 31, 16, 16, 16, 16, // 179 - 'Right T'
8, 16, 16, 16, 31, 16, 31, 16, 16, // 180 - 'Right T double H'
8, 20, 20, 20, 23, 20, 20, 20, 20, // 181 - 'Right T double V'
4, 20, 20, 20, 31, // 182 - 'Top Right double V'
6, 16, 16, 16, 31, 16, 31, // 183 - 'Top Right double H'
8, 20, 20, 20, 23, 16, 23, 20, 20, // 184 - 'Right T double all'
8, 20, 20, 20, 20, 20, 20, 20, 20, // 185 - 'Right side double'
6, 20, 20, 20, 23, 16, 31, // 186 - 'Top Right double'
8, 0, 0, 0, 31, 16, 23, 20, 20, // 187 - 'Bot Right double'
8, 0, 0, 0, 31, 20, 20, 20, 20, // 188 - 'Bot Right double V'
8, 0, 0, 0, 31, 16, 31, 16, 16, // 189 - 'Bot Right double H'
4, 16, 16, 16, 31, // 190 - 'Top Right'
8, 0, 0, 0, 24, 8, 8, 8, 8, // 191 - 'Bot Left'
8, 0, 0, 0, 31, 8, 8, 8, 8, // 192 - 'Bot T'
4, 8, 8, 8, 31, // 193 - 'Top T'
8, 8, 8, 8, 24, 8, 8, 8, 8, // 194 - 'Left T'
4, 0, 0, 0, 31, // 195 - 'Top side'
8, 8, 8, 8, 31, 8, 8, 8, 8, // 196 - 'Center +'
8, 8, 8, 8, 24, 8, 24, 8, 8, // 197 - 'Left side double H'
8, 20, 20, 20, 20, 20, 20, 20, 20, // 198 - 'Left side double'
6, 0, 0, 0, 232, 8, 248, // 199 - 'Bot Left double V'
6, 20, 20, 20, 20, 4, 28, // 200 - 'Top Left double V'
8, 0, 0, 0, 31, 0, 23, 20, 20, // 201 - 'Bot T double'
6, 20, 20, 20, 23, 0, 31, // 202 - 'Top T double'
8, 20, 20, 20, 20, 4, 20, 20, 20, // 203 - 'Left Side double spl'
6, 0, 0, 0, 31, 0, 31, // 204 - 'Center double'
8, 20, 20, 20, 23, 0, 23, 20, 20, // 205 - 'Center + double'
8, 0, 0, 0, 31, 0, 31, 8, 8, // 206 - 'Bot T double H'
8, 0, 0, 0, 31, 20, 20, 20, 20, // 207 - 'Bot Right double V'
6, 8, 8, 8, 31, 0, 31, // 208 - 'Top T double H'
4, 20, 20, 20, 31, // 209 - 'Top Right double V'
8, 0, 0, 0, 28, 20, 20, 20, 20, // 210 - 'Bot Left double V'
8, 0, 0, 0, 24, 8, 24, 8, 8, // 211 - 'Bot Right double H'
6, 8, 8, 8, 24, 8, 24, // 212 - 'Top Right double H'
4, 20, 20, 20, 28, // 213 - 'Top Right double V'
8, 20, 20, 20, 31, 20, 20, 20, 20, // 214 - 'Center + double V'
8, 8, 8, 8, 31, 8, 31, 8, 8, // 215 - 'Center + double H'
8, 0, 0, 0, 31, 16, 16, 16, 16, // 216 - 'Bot Right'
5, 0, 0, 0, 240, 16, // 217 - 'Top Left'
8, 255, 255, 255, 255, 255, 255, 255, 255, // 218 - 'Full Block'
5, 255, 255, 255, 255, 255, // 219 - 'Half Block Bottom'
8, 15, 15, 15, 15, 15, 15, 15, 15, // 220 - 'Half Block LHS'
8, 240, 240, 240, 240, 240, 240, 240, 240, // 221 - 'Half Block RHS'
8, 0, 0, 0, 0, 255, 255, 255, 255, // 222 - 'Half Block Top'
5, 44, 18, 18, 18, 44, // 223 - 'Alpha'
8, 2, 30, 34, 34, 30, 34, 34, 28, // 224 - 'Beta'
7, 2, 2, 2, 2, 2, 50, 62, // 225 - 'Gamma'
6, 20, 20, 20, 20, 20, 62, // 226 - 'Pi'
7, 62, 34, 4, 8, 4, 34, 62, // 227 - 'Sigma'
5, 12, 18, 18, 18, 60, // 228 - 'Theta'
6, 6, 44, 20, 20, 20, 20, // 229 - 'mu'
6, 8, 8, 8, 8, 10, 62, // 230 - 'Tau'
8, 62, 8, 28, 34, 34, 28, 8, 62, // 231
7, 8, 20, 34, 62, 34, 20, 8, // 232
7, 54, 20, 20, 34, 34, 20, 8, // 233
7, 28, 34, 34, 28, 24, 4, 24, // 234
4, 28, 42, 42, 28, // 235
8, 2, 28, 38, 42, 42, 50, 28, 32, // 236 - 'Zero Slashed'
7, 28, 2, 2, 30, 2, 2, 28, // 237
7, 34, 34, 34, 34, 34, 34, 28, // 238
5, 62, 0, 62, 0, 62, // 239 - '3 Bar Equals'
7, 62, 0, 8, 8, 62, 8, 8, // 240 - '+/-'
7, 62, 0, 4, 8, 16, 8, 4, // 241 - '>='
7, 62, 0, 16, 8, 4, 8, 16, // 242 - '<='
8, 8, 8, 8, 8, 8, 8, 40, 56, // 243 - 'Top of Integral'
8, 14, 10, 10, 8, 8, 8, 8, 8, // 244 - 'Bot of Integral'
7, 24, 24, 0, 126, 0, 24, 24, // 245 - 'Divide'
5, 58, 46, 0, 58, 46, // 246 - 'Wavy ='
4, 28, 54, 54, 28, // 247 - 'Degree'
2, 24, 24, // 248 - 'Math Product'
1, 24, // 249 - 'Short Dash'
8, 8, 12, 10, 10, 8, 8, 8, 56, // 250 - 'Square Root'
5, 36, 36, 36, 36, 28, // 251 - 'Superscript n'
5, 60, 12, 24, 48, 28, // 252 - 'Superscript 2'
4, 60, 60, 60, 60, // 253 - 'Centered Square'
8, 255, 129, 129, 129, 129, 129, 129, 255, // 254 - 'Full Frame'
8, 255, 255, 255, 255, 255, 255, 255, 255, // 255 - 'Full Block'
};
#endif

View File

@@ -0,0 +1,171 @@
// Use the Parola library to scroll text on the display
//
// Demonstrates the use of the scrolling function to display text received
// from the serial interface in a vertical display.
//
// User can enter text on the serial monitor and this will display as a
// scrolling message on the display.
// Speed for the display is controlled by a pot on SPEED_IN analog in.
// Scrolling direction is controlled by a switch on DIRECTION_SET digital in.
// Invert ON/OFF is set by a switch on INVERT_SET digital in.
//
// UISwitch library can be found at https://github.com/MajicDesigns/MD_UISwitch
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include "Parola_Fonts_data.h"
// set to 1 if we are implementing the user interface pot, switch, etc
#define USE_UI_CONTROL 0
#if USE_UI_CONTROL
#include <MD_UISwitch.h>
#endif
// Turn on debug statements to the serial output
#define DEBUG 0
#if DEBUG
#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }
#define PRINTS(x) Serial.print(F(x))
#define PRINTX(x) Serial.println(x, HEX)
#else
#define PRINT(s, x)
#define PRINTS(x)
#define PRINTX(x)
#endif
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 8
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// HARDWARE SPI
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
// Scrolling parameters
#if USE_UI_CONTROL
const uint8_t SPEED_IN = A5;
const uint8_t DIRECTION_SET = 8; // change the effect
const uint8_t INVERT_SET = 9; // change the invert
const uint8_t SPEED_DEADBAND = 5;
#endif // USE_UI_CONTROL
uint8_t scrollSpeed = 25; // default frame delay value
textEffect_t scrollEffect = PA_SCROLL_RIGHT;
textPosition_t scrollAlign = PA_CENTER;
uint16_t scrollPause = 2000; // in milliseconds
// Global message buffers shared by Serial and Scrolling functions
#define BUF_SIZE 75
char curMessage[BUF_SIZE] = { "" };
char newMessage[BUF_SIZE] = { "Hello! Enter new message?" };
bool newMessageAvailable = true;
#if USE_UI_CONTROL
MD_UISwitch_Digital uiDirection(DIRECTION_SET);
MD_UISwitch_Digital uiInvert(INVERT_SET);
void doUI(void)
{
// set the speed if it has changed
{
int16_t speed = map(analogRead(SPEED_IN), 0, 1023, 10, 150);
if ((speed >= ((int16_t)P.getSpeed() + SPEED_DEADBAND)) ||
(speed <= ((int16_t)P.getSpeed() - SPEED_DEADBAND)))
{
P.setSpeed(speed);
scrollSpeed = speed;
PRINT("\nChanged speed to ", P.getSpeed());
}
}
if (uiDirection.read() == MD_UISwitch::KEY_PRESS) // SCROLL DIRECTION
{
PRINTS("\nChanging scroll direction");
scrollEffect = (scrollEffect == PA_SCROLL_LEFT ? PA_SCROLL_RIGHT : PA_SCROLL_LEFT);
P.setTextEffect(scrollEffect, scrollEffect);
P.displayClear();
P.displayReset();
}
if (uiInvert.read() == MD_UISwitch::KEY_PRESS) // INVERT MODE
{
PRINTS("\nChanging invert mode");
P.setInvert(!P.getInvert());
}
}
#endif // USE_UI_CONTROL
void readSerial(void)
{
static char *cp = newMessage;
while (Serial.available())
{
*cp = (char)Serial.read();
if ((*cp == '\n') || (cp - newMessage >= BUF_SIZE-2)) // end of message character or full buffer
{
*cp = '\0'; // end the string
// restart the index for next filling spree and flag we have a message waiting
cp = newMessage;
newMessageAvailable = true;
}
else // move char pointer to next position
cp++;
}
}
void setup()
{
Serial.begin(57600);
Serial.print("\n[Parola Scrolling Display]\nType a message for the scrolling display\nEnd message line with a newline");
#if USE_UI_CONTROL
uiDirection.begin();
uiInvert.begin();
pinMode(SPEED_IN, INPUT);
doUI();
#endif // USE_UI_CONTROL
P.begin();
P.setFont(_fontVertical);
P.displayText(curMessage, scrollAlign, scrollSpeed, scrollPause, scrollEffect, scrollEffect);
}
void loop()
{
#if USE_UI_CONTROL
doUI();
#endif // USE_UI_CONTROL
if (P.displayAnimate())
{
if (newMessageAvailable)
{
strrev(newMessage); // reverse the string for proper display order
strcpy(curMessage, newMessage);
newMessageAvailable = false;
}
P.displayReset();
}
readSerial();
}

View File

@@ -0,0 +1,318 @@
// Program to exercise the MD_Parola library
//
// Demonstrates how to set up and use the user defined sprites for
// text animations.
//
// Speed for the display is controlled by a pot on SPEED_IN analog input.
// Digital switches used for control of text justification and invert mode.
// UI switches are normally HIGH.
//
// UISwitch library can be found at https://github.com/MajicDesigns/MD_UISwitch
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include <MD_UISwitch.h>
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 11
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// HARDWARE SPI
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
// Turn on debug statements to the serial output
#define DEBUG_ENABLE 0
#if DEBUG_ENABLE
#define DEBUG(s, x) { Serial.print(F(s)); Serial.print(x); }
#define DEBUGS(x) Serial.print(F(x))
#define DEBUGX(x) Serial.println(x, HEX)
#else
#define DEBUG(s, x)
#define DEBUGS(x)
#define DEBUGX(x)
#endif
// User interface pin and switch definitions
const uint8_t SPEED_IN = A5; // control the speed with an external pot
const uint8_t JUSTIFY_SET = 6; // change the justification
const uint8_t INVERSE_SET = 9; // set/reset the display to inverse
uint8_t uiPins[] = { JUSTIFY_SET, INVERSE_SET };
const uint16_t PAUSE_TIME = 1000; // in milliseconds
const uint8_t SPEED_DEADBAND = 5; // in analog units
// Global variables
uint8_t curString = 0;
const char *msg[] =
{
"Parola Sprites",
//"Animation"
};
MD_UISwitch_Digital uiSwitches(uiPins, ARRAY_SIZE(uiPins));
// Sprite Definitions
const uint8_t F_PMAN1 = 6;
const uint8_t W_PMAN1 = 8;
static const uint8_t PROGMEM pacman1[F_PMAN1 * W_PMAN1] = // gobbling pacman animation
{
0x00, 0x81, 0xc3, 0xe7, 0xff, 0x7e, 0x7e, 0x3c,
0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c,
0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c,
0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c,
0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c,
0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c,
};
const uint8_t F_PMAN2 = 6;
const uint8_t W_PMAN2 = 18;
static const uint8_t PROGMEM pacman2[F_PMAN2 * W_PMAN2] = // ghost pursued by a pacman
{
0x00, 0x81, 0xc3, 0xe7, 0xff, 0x7e, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x7b, 0xf3, 0x7f, 0xfb, 0x73, 0xfe,
0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x7b, 0xf3, 0x7f, 0xfb, 0x73, 0xfe,
0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x7b, 0xf3, 0x7f, 0xfb, 0x73, 0xfe,
0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x73, 0xfb, 0x7f, 0xf3, 0x7b, 0xfe,
0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x73, 0xfb, 0x7f, 0xf3, 0x7b, 0xfe,
0x00, 0x42, 0xe7, 0xe7, 0xff, 0xff, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0xfe, 0x73, 0xfb, 0x7f, 0xf3, 0x7b, 0xfe,
};
const uint8_t F_WAVE = 14;
const uint8_t W_WAVE = 14;
static const uint8_t PROGMEM wave[F_WAVE * W_WAVE] = // triangular wave / worm
{
0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10,
0x10, 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x40, 0x20,
0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x40,
0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
0x40, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
0x20, 0x40, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x10,
0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08,
0x08, 0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x02, 0x04,
0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x02,
0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01,
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02,
0x02, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04,
0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x40, 0x20, 0x10, 0x08,
};
const uint8_t F_ROLL1 = 4;
const uint8_t W_ROLL1 = 8;
static const uint8_t PROGMEM roll1[F_ROLL1 * W_ROLL1] = // rolling square
{
0xff, 0x8f, 0x8f, 0x8f, 0x81, 0x81, 0x81, 0xff,
0xff, 0xf1, 0xf1, 0xf1, 0x81, 0x81, 0x81, 0xff,
0xff, 0x81, 0x81, 0x81, 0xf1, 0xf1, 0xf1, 0xff,
0xff, 0x81, 0x81, 0x81, 0x8f, 0x8f, 0x8f, 0xff,
};
const uint8_t F_ROLL2 = 4;
const uint8_t W_ROLL2 = 8;
static const uint8_t PROGMEM roll2[F_ROLL2 * W_ROLL2] = // rolling octagon
{
0x3c, 0x4e, 0x8f, 0x8f, 0x81, 0x81, 0x42, 0x3c,
0x3c, 0x72, 0xf1, 0xf1, 0x81, 0x81, 0x42, 0x3c,
0x3c, 0x42, 0x81, 0x81, 0xf1, 0xf1, 0x72, 0x3c,
0x3c, 0x42, 0x81, 0x81, 0x8f, 0x8f, 0x4e, 0x3c,
};
const uint8_t F_LINES = 3;
const uint8_t W_LINES = 8;
static const uint8_t PROGMEM lines[F_LINES * W_LINES] = // spaced lines
{
0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00,
0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00,
0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
};
const uint8_t F_ARROW1 = 3;
const uint8_t W_ARROW1 = 10;
static const uint8_t PROGMEM arrow1[F_ARROW1 * W_ARROW1] = // arrow fading to center
{
0x18, 0x3c, 0x7e, 0xff, 0x7e, 0x00, 0x00, 0x3c, 0x00, 0x00,
0x18, 0x3c, 0x7e, 0xff, 0x00, 0x7e, 0x00, 0x00, 0x18, 0x00,
0x18, 0x3c, 0x7e, 0xff, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x18,
};
const uint8_t F_ARROW2 = 3;
const uint8_t W_ARROW2 = 10;
static const uint8_t PROGMEM arrow2[F_ARROW2 * W_ARROW2] = // arrow fading to outside
{
0x18, 0x3c, 0x7e, 0xff, 0xe7, 0x00, 0x00, 0xc3, 0x00, 0x00,
0x18, 0x3c, 0x7e, 0xff, 0x00, 0xe7, 0x00, 0x00, 0x81, 0x00,
0x18, 0x3c, 0x7e, 0xff, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x81,
};
const uint8_t F_SAILBOAT = 1;
const uint8_t W_SAILBOAT = 11;
static const uint8_t PROGMEM sailboat[F_SAILBOAT * W_SAILBOAT] = // sail boat
{
0x10, 0x30, 0x58, 0x94, 0x92, 0x9f, 0x92, 0x94, 0x98, 0x50, 0x30,
};
const uint8_t F_STEAMBOAT = 2;
const uint8_t W_STEAMBOAT = 11;
static const uint8_t PROGMEM steamboat[F_STEAMBOAT * W_STEAMBOAT] = // steam boat
{
0x10, 0x30, 0x50, 0x9c, 0x9e, 0x90, 0x91, 0x9c, 0x9d, 0x90, 0x71,
0x10, 0x30, 0x50, 0x9c, 0x9c, 0x91, 0x90, 0x9d, 0x9e, 0x91, 0x70,
};
const uint8_t F_HEART = 5;
const uint8_t W_HEART = 9;
static const uint8_t PROGMEM heart[F_HEART * W_HEART] = // beating heart
{
0x0e, 0x11, 0x21, 0x42, 0x84, 0x42, 0x21, 0x11, 0x0e,
0x0e, 0x1f, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x1f, 0x0e,
0x0e, 0x1f, 0x3f, 0x7e, 0xfc, 0x7e, 0x3f, 0x1f, 0x0e,
0x0e, 0x1f, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x1f, 0x0e,
0x0e, 0x11, 0x21, 0x42, 0x84, 0x42, 0x21, 0x11, 0x0e,
};
const uint8_t F_INVADER = 2;
const uint8_t W_INVADER = 10;
static const uint8_t PROGMEM invader[F_INVADER * W_INVADER] = // space invader
{
0x0e, 0x98, 0x7d, 0x36, 0x3c, 0x3c, 0x36, 0x7d, 0x98, 0x0e,
0x70, 0x18, 0x7d, 0xb6, 0x3c, 0x3c, 0xb6, 0x7d, 0x18, 0x70,
};
const uint8_t F_ROCKET = 2;
const uint8_t W_ROCKET = 11;
static const uint8_t PROGMEM rocket[F_ROCKET * W_ROCKET] = // rocket
{
0x18, 0x24, 0x42, 0x81, 0x99, 0x18, 0x99, 0x18, 0xa5, 0x5a, 0x81,
0x18, 0x24, 0x42, 0x81, 0x18, 0x99, 0x18, 0x99, 0x24, 0x42, 0x99,
};
const uint8_t F_FBALL = 2;
const uint8_t W_FBALL = 11;
static const uint8_t PROGMEM fireball[F_FBALL * W_FBALL] = // fireball
{
0x7e, 0xab, 0x54, 0x28, 0x52, 0x24, 0x40, 0x18, 0x04, 0x10, 0x08,
0x7e, 0xd5, 0x2a, 0x14, 0x24, 0x0a, 0x30, 0x04, 0x28, 0x08, 0x10,
};
struct {
uint8_t *data;
uint8_t width;
uint8_t frames;
} sprite[] =
{
{ rocket, W_ROCKET, F_ROCKET },
{ invader, W_INVADER, F_INVADER },
{ heart, W_HEART, F_HEART },
{ arrow1, W_ARROW1, F_ARROW1 },
{ steamboat, W_STEAMBOAT, F_STEAMBOAT },
{ fireball, W_FBALL, F_FBALL },
{ roll2, W_ROLL2, F_ROLL2 },
{ pacman2, W_PMAN2, F_PMAN2 },
{ lines, W_LINES, F_LINES },
{ roll1, W_ROLL1, F_ROLL1 },
{ sailboat, W_SAILBOAT, F_SAILBOAT },
{ arrow2, W_ARROW2, F_ARROW2 },
{ wave, W_WAVE, F_WAVE },
{ pacman1, W_PMAN1, F_PMAN1 },
};
void doUI(void)
{
// set the speed if it has changed - Analog read
{
int16_t speed = map(analogRead(SPEED_IN), 0, 1023, 0, 100);
if ((speed >= ((int16_t)P.getSpeed() + SPEED_DEADBAND)) ||
(speed <= ((int16_t)P.getSpeed() - SPEED_DEADBAND)))
{
P.setSpeed(speed);
DEBUG("\nChanged speed to ", P.getSpeed());
}
}
// now process the switch digital inputs
if (uiSwitches.read() == MD_UISwitch::KEY_PRESS) // a switch was pressed!
{
switch (uiSwitches.getKey())
{
case JUSTIFY_SET: // TEXT ALIGNMENT - nothing on initialise
{
static uint8_t curMode = 1;
textPosition_t align = P.getTextAlignment();
textPosition_t textAlign[] =
{
PA_CENTER,
PA_LEFT,
PA_RIGHT
};
DEBUG("\nChanging alignment to ", curMode);
P.setTextAlignment(textAlign[curMode]);
P.displayReset();
curMode = (curMode + 1) % ARRAY_SIZE(textAlign);
}
break;
case INVERSE_SET: // INVERSE
P.setInvert(!P.getInvert());
break;
}
}
}
void setup(void)
{
#if DEBUG_ENABLE
Serial.begin(57600);
DEBUGS("[Parola Test]");
#endif
// user interface switches
uiSwitches.begin();
// Parola object
P.begin();
P.displayText(msg[curString], PA_CENTER, P.getSpeed(), PAUSE_TIME, PA_SPRITE, PA_SPRITE);
P.setSpriteData(pacman1, W_PMAN1, F_PMAN1, pacman2, W_PMAN2, F_PMAN2);
curString++;
}
void loop(void)
{
static uint8_t curFX = 0;
doUI();
if (P.displayAnimate())
{
if (curString == ARRAY_SIZE(msg))
{
P.setSpriteData(sprite[curFX].data, sprite[curFX].width, sprite[curFX].frames, // entry sprite
sprite[curFX].data, sprite[curFX].width, sprite[curFX].frames); // exit sprite
curFX = (curFX + 1) % ARRAY_SIZE(sprite);
curString = 0;
}
P.setTextBuffer(msg[curString]);
P.displayReset();
curString++;
}
}

View File

@@ -0,0 +1,226 @@
// Program to exercise the MD_Parola library
//
// Demonstrates most of the functions of the Parola library.
// All animations can be run and tested under user control.
//
// Speed for the display is controlled by a pot on SPEED_IN analog input.
// Digital switches used for control of Justification, Effect progression,
// Pause between animations, LED intensity, Display flip, and invert mode.
// UI switches are normally HIGH.
//
// UISwitch library can be found at https://github.com/MajicDesigns/MD_UISwitch
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include <MD_UISwitch.h>
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 11
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// HARDWARE SPI
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
// Turn on debug statements to the serial output
#define DEBUG_ENABLE 1
#if DEBUG_ENABLE
#define DEBUG(s, x) { Serial.print(F(s)); Serial.print(x); }
#define DEBUGS(x) Serial.print(F(x))
#define DEBUGX(x) Serial.println(x, HEX)
#else
#define DEBUG(s, x)
#define DEBUGS(x)
#define DEBUGX(x)
#endif
// User interface pin and switch definitions
const uint8_t SPEED_IN = A5; // control the speed with an external pot
const uint8_t PAUSE_SET = 4; // toggle pause time
const uint8_t FLIP_SET = 5; // toggle flip status
const uint8_t JUSTIFY_SET = 6; // change the justification
const uint8_t INTENSITY_SET = 7; // change the intensity of the display
const uint8_t EFFECT_SET = 8; // change the effect
const uint8_t INVERSE_SET = 9; // set/reset the display to inverse
uint8_t uiPins[] = { PAUSE_SET, FLIP_SET, JUSTIFY_SET, INTENSITY_SET, EFFECT_SET, INVERSE_SET };
const uint16_t PAUSE_TIME = 1000; // in milliseconds
const uint8_t SPEED_DEADBAND = 5; // in analog units
// Global variables
uint8_t curString = 0;
const char *msg[] =
{
"Parola for",
"Arduino",
"LED Matrix",
"Display"
};
#define NEXT_STRING ((curString + 1) % ARRAY_SIZE(msg))
MD_UISwitch_Digital uiSwitches(uiPins, ARRAY_SIZE(uiPins));
void doUI(void)
{
// set the speed if it has changed - Analog read
{
int16_t speed = map(analogRead(SPEED_IN), 0, 1023, 0, 100);
if ((speed >= ((int16_t)P.getSpeed() + SPEED_DEADBAND)) ||
(speed <= ((int16_t)P.getSpeed() - SPEED_DEADBAND)))
{
P.setSpeed(speed);
DEBUG("\nChanged speed to ", P.getSpeed());
}
}
// now process the switch digital inputs
if (uiSwitches.read() == MD_UISwitch::KEY_PRESS) // a switch was pressed!
{
switch (uiSwitches.getKey())
{
case JUSTIFY_SET: // TEXT ALIGNMENT - nothing on initialise
{
static uint8_t curMode = 1;
textPosition_t align = P.getTextAlignment();
textPosition_t textAlign[] =
{
PA_CENTER,
PA_LEFT,
PA_RIGHT
};
DEBUG("\nChanging alignment to ", curMode);
P.setTextAlignment(textAlign[curMode]);
P.displayReset();
curMode = (curMode + 1) % ARRAY_SIZE(textAlign);
}
break;
case EFFECT_SET: // EFFECT CHANGE
{
static uint8_t curFX = 1;
textEffect_t effect[] =
{
PA_PRINT, PA_SCROLL_UP, PA_SCROLL_DOWN, PA_SCROLL_LEFT, PA_SCROLL_RIGHT,
#if ENA_MISC
PA_SLICE, PA_FADE, PA_MESH, PA_BLINDS, PA_DISSOLVE, PA_RANDOM,
#endif
#if ENA_SPRITE
PA_ROCKET, PA_FIREBALL,
#endif
#if ENA_WIPE
PA_WIPE, PA_WIPE_CURSOR,
#endif
#if ENA_OPNCLS
PA_OPENING, PA_OPENING_CURSOR, PA_CLOSING, PA_CLOSING_CURSOR,
#endif
#if ENA_SCR_DIA
PA_SCROLL_UP_LEFT, PA_SCROLL_UP_RIGHT, PA_SCROLL_DOWN_LEFT, PA_SCROLL_DOWN_RIGHT,
#endif
#if ENA_SCAN
PA_SCAN_HORIZ, PA_SCAN_HORIZX, PA_SCAN_VERT, PA_SCAN_VERTX,
#endif
#if ENA_GROW
PA_GROW_UP, PA_GROW_DOWN,
#endif
};
DEBUG("\nChanging effect to ", curFX);
P.setTextEffect(effect[curFX], effect[curFX]);
P.displayClear();
P.displayReset();
curFX = (curFX + 1) % ARRAY_SIZE(effect);
}
break;
case PAUSE_SET: // PAUSE DELAY
{
DEBUGS("\nChanging pause");
if ((P.getPause() <= P.getSpeed()))
P.setPause(PAUSE_TIME);
else
P.setPause(0);
}
break;
case INTENSITY_SET: // INTENSITY
{
static uint8_t intensity = MAX_INTENSITY/2;
if (intensity == 0)
{
P.displayShutdown(true);
DEBUG("\nDisplay shutdown ", intensity);
}
else
{
P.setIntensity(intensity);
P.displayShutdown(false);
DEBUG("\nChanged intensity to ", intensity);
}
intensity = (intensity + 1) % (MAX_INTENSITY + 1);
}
break;
case INVERSE_SET: // INVERSE
{
P.setInvert(!P.getInvert());
}
break;
case FLIP_SET: // FLIP
{
P.setZoneEffect(0, !P.getZoneEffect(0, PA_FLIP_LR), PA_FLIP_LR);
P.setZoneEffect(0, !P.getZoneEffect(0, PA_FLIP_UD), PA_FLIP_UD);
}
break;
}
}
}
void setup(void)
{
#if DEBUG_ENABLE
Serial.begin(57600);
DEBUGS("[Parola Test]");
#endif
// user interface switches
uiSwitches.begin();
// Parola object
P.begin();
P.displayText(msg[curString], PA_CENTER, P.getSpeed(), PAUSE_TIME, PA_PRINT, PA_PRINT);
curString = NEXT_STRING;
}
void loop(void)
{
doUI();
if (P.displayAnimate())
{
P.setTextBuffer(msg[curString]);
P.displayReset();
curString = NEXT_STRING;
}
}

View File

@@ -0,0 +1,256 @@
// Program to exercise the MD_Parola library
//
// Demonstrates most of the functions of the Parola library Text and Graphics combined.
//
// Speed for the display is controlled by a pot on SPEED_IN analog input.
// Digital switches used for control of Justification, Effect progression,
// Pause between animations, LED intensity, Display flip, and invert mode.
// UI switches are normally HIGH.
//
// UISwitch library can be found at https://github.com/MajicDesigns/MD_UISwitch
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include <MD_UISwitch.h>
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 8
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// HARDWARE SPI
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
// Turn on debug statements to the serial output
#define DEBUG_ENABLE 1
#if DEBUG_ENABLE
#define DEBUG(s, x) { Serial.print(F(s)); Serial.print(x); }
#define DEBUGS(x) Serial.print(F(x))
#define DEBUGX(x) Serial.println(x, HEX)
#else
#define DEBUG(s, x)
#define DEBUGS(x)
#define DEBUGX(x)
#endif
// User interface pin and switch definitions
const uint8_t SPEED_IN = A5; // control the speed with an external pot
const uint8_t PAUSE_SET = 4; // toggle pause time
const uint8_t FLIP_SET = 5; // toggle flip status
const uint8_t JUSTIFY_SET = 6; // change the justification
const uint8_t INTENSITY_SET = 7; // change the intensity of the display
const uint8_t EFFECT_SET = 8; // change the effect
const uint8_t INVERSE_SET = 9; // set/reset the display to inverse
uint8_t uiPins[] = { PAUSE_SET, FLIP_SET, JUSTIFY_SET, INTENSITY_SET, EFFECT_SET, INVERSE_SET };
const uint16_t PAUSE_TIME = 1000; // in milliseconds
const uint8_t SPEED_DEADBAND = 5; // in analog units
// Global variables
uint8_t curString = 0;
const char *msg[] =
{
"Parola for",
"Arduino",
"LED Matrix",
"Display"
};
#define NEXT_STRING ((curString + 1) % ARRAY_SIZE(msg))
MD_UISwitch_Digital uiSwitches(uiPins, ARRAY_SIZE(uiPins));
void doUI(void)
{
// set the speed if it has changed - Analog read
{
int16_t speed = map(analogRead(SPEED_IN), 0, 1023, 0, 100);
if ((speed >= ((int16_t)P.getSpeed() + SPEED_DEADBAND)) ||
(speed <= ((int16_t)P.getSpeed() - SPEED_DEADBAND)))
{
P.setSpeed(speed);
DEBUG("\nChanged speed to ", P.getSpeed());
}
}
// now process the switch digital inputs
if (uiSwitches.read() == MD_UISwitch::KEY_PRESS) // a switch was pressed!
{
switch (uiSwitches.getKey())
{
case JUSTIFY_SET: // TEXT ALIGNMENT - nothing on initialise
{
static uint8_t curMode = 1;
textPosition_t align = P.getTextAlignment();
textPosition_t textAlign[] =
{
PA_CENTER,
PA_LEFT,
PA_RIGHT
};
DEBUG("\nChanging alignment to ", curMode);
P.setTextAlignment(textAlign[curMode]);
P.displayReset();
curMode = (curMode + 1) % ARRAY_SIZE(textAlign);
}
break;
case EFFECT_SET: // EFFECT CHANGE
{
static uint8_t curFX = 1;
textEffect_t effect[] =
{
PA_PRINT, PA_SCROLL_UP, PA_SCROLL_DOWN, PA_SCROLL_LEFT, PA_SCROLL_RIGHT,
#if ENA_MISC
PA_SLICE, PA_FADE, PA_MESH, PA_BLINDS, PA_DISSOLVE, PA_RANDOM,
#endif
#if ENA_WIPE
PA_WIPE, PA_WIPE_CURSOR,
#endif
#if ENA_OPNCLS
PA_OPENING, PA_OPENING_CURSOR, PA_CLOSING, PA_CLOSING_CURSOR,
#endif
#if ENA_SCR_DIA
PA_SCROLL_UP_LEFT, PA_SCROLL_UP_RIGHT, PA_SCROLL_DOWN_LEFT, PA_SCROLL_DOWN_RIGHT,
#endif
#if ENA_SCAN
PA_SCAN_HORIZ, PA_SCAN_HORIZX, PA_SCAN_VERT, PA_SCAN_VERTX,
#endif
#if ENA_GROW
PA_GROW_UP, PA_GROW_DOWN,
#endif
};
DEBUG("\nChanging effect to ", curFX);
P.setTextEffect(effect[curFX], effect[curFX]);
P.displayClear();
P.displayReset();
curFX = (curFX + 1) % ARRAY_SIZE(effect);
}
break;
case PAUSE_SET: // PAUSE DELAY
{
DEBUGS("\nChanging pause");
if ((P.getPause() <= P.getSpeed()))
P.setPause(PAUSE_TIME);
else
P.setPause(0);
}
break;
case INTENSITY_SET: // INTENSITY
{
static uint8_t intensity = MAX_INTENSITY/2;
if (intensity == 0)
{
P.displayShutdown(true);
DEBUG("\nDisplay shutdown ", intensity);
}
else
{
P.setIntensity(intensity);
P.displayShutdown(false);
DEBUG("\nChanged intensity to ", intensity);
}
intensity = (intensity + 1) % (MAX_INTENSITY + 1);
}
break;
case INVERSE_SET: // INVERSE
{
P.setInvert(!P.getInvert());
}
break;
case FLIP_SET: // FLIP
{
P.setZoneEffect(0, !P.getZoneEffect(0, PA_FLIP_LR), PA_FLIP_LR);
P.setZoneEffect(0, !P.getZoneEffect(0, PA_FLIP_UD), PA_FLIP_UD);
}
break;
}
}
}
void setup(void)
{
#if DEBUG_ENABLE
Serial.begin(57600);
DEBUGS("[Parola T+G Test]");
#endif
// user interface switches
uiSwitches.begin();
// Parola object
P.begin();
P.displayText(msg[curString], PA_CENTER, P.getSpeed(), PAUSE_TIME, PA_PRINT, PA_PRINT);
curString = NEXT_STRING;
}
void rectangle(MD_MAX72XX *M, uint8_t r1, uint16_t c1, uint8_t r2, uint16_t c2)
// Draw a rectangle with a cross through it
{
M->update(MD_MAX72XX::OFF);
M->drawLine(r1, c1, r2, c1, true);
M->drawLine(r2, c1, r2, c2, true);
M->drawLine(r2, c2, r1, c2, true);
M->drawLine(r1, c2, r1, c1, true);
M->drawLine(r1, c1, r2, c2, true);
M->drawLine(r1, c2, r2, c1, true);
M->update(MD_MAX72XX::ON);
}
void loop(void)
{
doUI();
if (P.displayAnimate())
{
P.setTextBuffer(msg[curString]);
P.displayReset();
curString = NEXT_STRING;
}
if (P.isAnimationAdvanced())
{
MD_MAX72XX *M;
uint16_t startDisp, endDisp;
uint16_t startText, endText;
DEBUGS("\nAnimated!");
P.getDisplayExtent(startDisp, endDisp);
DEBUG("\nDisplay extents from ", startDisp);
DEBUG(" to ", endDisp);
P.getTextExtent(startText, endText);
DEBUG("\nText extents for '", msg[curString]);
DEBUG("' from ", startText);
DEBUG(" to ", endText);
M = P.getGraphicObject();
rectangle(M, 0, startDisp, ROW_SIZE-1, endText-2);
rectangle(M, 0, endDisp, ROW_SIZE-1, startText+2);
}
}

View File

@@ -0,0 +1,265 @@
// Data file for UTF-8 example user defined fonts
#ifndef FONTS_DATA_H
#define FONTS_DATA_H
MD_MAX72XX::fontType_t ExtASCII[] PROGMEM =
{
0, // 0 - 'Unused'
0, // 1 - 'Unused'
0, // 2 - 'Unused'
0, // 3 - 'Unused'
0, // 4 - 'Unused'
0, // 5 - 'Unused'
0, // 6 - 'Unused'
0, // 7 - 'Unused'
0, // 8 - 'Unused'
0, // 9 - 'Unused'
0, // 10 - 'Unused'
0, // 11 - 'Unused'
0, // 12 - 'Unused'
0, // 13 - 'Unused'
0, // 14 - 'Unused'
0, // 15 - 'Unused'
0, // 16 - 'Unused'
0, // 17 - 'Unused'
0, // 18 - 'Unused'
0, // 19 - 'Unused'
0, // 20 - 'Unused'
0, // 21 - 'Unused'
0, // 22 - 'Unused'
0, // 23 - 'Unused'
0, // 24 - 'Unused'
0, // 25 - 'Unused'
0, // 26 - 'Unused'
0, // 27 - 'Unused'
0, // 28 - 'Unused'
0, // 29 - 'Unused'
0, // 30 - 'Unused'
0, // 31 - 'Unused'
2, 0, 0, // 32 - 'Space'
1, 95, // 33 - '!'
3, 7, 0, 7, // 34 - '"'
5, 20, 127, 20, 127, 20, // 35 - '#'
5, 36, 42, 127, 42, 18, // 36 - '$'
5, 35, 19, 8, 100, 98, // 37 - '%'
5, 54, 73, 86, 32, 80, // 38 - '&'
2, 4, 3, // 39
3, 28, 34, 65, // 40 - '('
3, 65, 34, 28, // 41 - ')'
5, 42, 28, 127, 28, 42, // 42 - '*'
5, 8, 8, 62, 8, 8, // 43 - '+'
2, 128, 96, // 44 - ','
5, 8, 8, 8, 8, 8, // 45 - '-'
2, 96, 96, // 46 - '.'
5, 32, 16, 8, 4, 2, // 47 - '/'
5, 62, 81, 73, 69, 62, // 48 - '0'
3, 66, 127, 64, // 49 - '1'
5, 114, 73, 73, 73, 70, // 50 - '2'
5, 33, 65, 73, 77, 51, // 51 - '3'
5, 24, 20, 18, 127, 16, // 52 - '4'
5, 39, 69, 69, 69, 57, // 53 - '5'
5, 60, 74, 73, 73, 49, // 54 - '6'
5, 65, 33, 17, 9, 7, // 55 - '7'
5, 54, 73, 73, 73, 54, // 56 - '8'
5, 70, 73, 73, 41, 30, // 57 - '9'
1, 20, // 58 - ':'
2, 128, 104, // 59 - ';'
4, 8, 20, 34, 65, // 60 - '<'
5, 20, 20, 20, 20, 20, // 61 - '='
4, 65, 34, 20, 8, // 62 - '>'
5, 2, 1, 89, 9, 6, // 63 - '?'
5, 62, 65, 93, 89, 78, // 64 - '@'
5, 124, 18, 17, 18, 124, // 65 - 'A'
5, 127, 73, 73, 73, 54, // 66 - 'B'
5, 62, 65, 65, 65, 34, // 67 - 'C'
5, 127, 65, 65, 65, 62, // 68 - 'D'
5, 127, 73, 73, 73, 65, // 69 - 'E'
5, 127, 9, 9, 9, 1, // 70 - 'F'
5, 62, 65, 65, 81, 115, // 71 - 'G'
5, 127, 8, 8, 8, 127, // 72 - 'H'
3, 65, 127, 65, // 73 - 'I'
5, 32, 64, 65, 63, 1, // 74 - 'J'
5, 127, 8, 20, 34, 65, // 75 - 'K'
5, 127, 64, 64, 64, 64, // 76 - 'L'
5, 127, 2, 28, 2, 127, // 77 - 'M'
5, 127, 4, 8, 16, 127, // 78 - 'N'
5, 62, 65, 65, 65, 62, // 79 - 'O'
5, 127, 9, 9, 9, 6, // 80 - 'P'
5, 62, 65, 81, 33, 94, // 81 - 'Q'
5, 127, 9, 25, 41, 70, // 82 - 'R'
5, 38, 73, 73, 73, 50, // 83 - 'S'
5, 3, 1, 127, 1, 3, // 84 - 'T'
5, 63, 64, 64, 64, 63, // 85 - 'U'
5, 31, 32, 64, 32, 31, // 86 - 'V'
5, 63, 64, 56, 64, 63, // 87 - 'W'
5, 99, 20, 8, 20, 99, // 88 - 'X'
5, 3, 4, 120, 4, 3, // 89 - 'Y'
5, 97, 89, 73, 77, 67, // 90 - 'Z'
3, 127, 65, 65, // 91 - '['
5, 2, 4, 8, 16, 32, // 92 - '\'
3, 65, 65, 127, // 93 - ']'
5, 4, 2, 1, 2, 4, // 94 - '^'
5, 64, 64, 64, 64, 64, // 95 - '_'
2, 3, 4, // 96 - '`'
5, 32, 84, 84, 120, 64, // 97 - 'a'
5, 127, 40, 68, 68, 56, // 98 - 'b'
5, 56, 68, 68, 68, 40, // 99 - 'c'
5, 56, 68, 68, 40, 127, // 100 - 'd'
5, 56, 84, 84, 84, 24, // 101 - 'e'
4, 8, 126, 9, 2, // 102 - 'f'
5, 24, 164, 164, 156, 120, // 103 - 'g'
5, 127, 8, 4, 4, 120, // 104 - 'h'
3, 68, 125, 64, // 105 - 'i'
4, 64, 128, 128, 122, // 106 - 'j'
4, 127, 16, 40, 68, // 107 - 'k'
3, 65, 127, 64, // 108 - 'l'
5, 124, 4, 120, 4, 120, // 109 - 'm'
5, 124, 8, 4, 4, 120, // 110 - 'n'
5, 56, 68, 68, 68, 56, // 111 - 'o'
5, 252, 24, 36, 36, 24, // 112 - 'p'
5, 24, 36, 36, 24, 252, // 113 - 'q'
5, 124, 8, 4, 4, 8, // 114 - 'r'
5, 72, 84, 84, 84, 36, // 115 - 's'
4, 4, 63, 68, 36, // 116 - 't'
5, 60, 64, 64, 32, 124, // 117 - 'u'
5, 28, 32, 64, 32, 28, // 118 - 'v'
5, 60, 64, 48, 64, 60, // 119 - 'w'
5, 68, 40, 16, 40, 68, // 120 - 'x'
5, 76, 144, 144, 144, 124, // 121 - 'y'
5, 68, 100, 84, 76, 68, // 122 - 'z'
3, 8, 54, 65, // 123 - '{'
1, 119, // 124 - '|'
3, 65, 54, 8, // 125 - '}'
5, 2, 1, 2, 4, 2, // 126 - '~'
0, // 127 - 'Unused'
6, 20, 62, 85, 85, 65, 34, // 128 - 'Euro sign'
0, // 129 - 'Not used'
2, 128, 96, // 130 - 'Single low 9 quotation mark'
5, 192, 136, 126, 9, 3, // 131 - 'f with hook'
4, 128, 96, 128, 96, // 132 - 'Single low 9 quotation mark'
8, 96, 96, 0, 96, 96, 0, 96, 96, // 133 - 'Horizontal ellipsis'
3, 4, 126, 4, // 134 - 'Dagger'
3, 20, 126, 20, // 135 - 'Double dagger'
4, 2, 1, 1, 2, // 136 - 'Modifier circumflex'
7, 35, 19, 104, 100, 2, 97, 96, // 137 - 'Per mille sign'
5, 72, 85, 86, 85, 36, // 138 - 'S with caron'
3, 8, 20, 34, // 139 - '< quotation'
6, 62, 65, 65, 127, 73, 73, // 140 - 'OE'
0, // 141 - 'Not used'
5, 68, 101, 86, 77, 68, // 142 - 'z with caron'
0, // 143 - 'Not used'
0, // 144 - 'Not used'
2, 3, 4, // 145 - 'Left single quote mark'
2, 4, 3, // 146 - 'Right single quote mark'
4, 3, 4, 3, 4, // 147 - 'Left double quote marks'
4, 4, 3, 4, 3, // 148 - 'Right double quote marks'
4, 0, 24, 60, 24, // 149 - 'Bullet Point'
3, 8, 8, 8, // 150 - 'En dash'
5, 8, 8, 8, 8, 8, // 151 - 'Em dash'
4, 2, 1, 2, 1, // 152 - 'Small ~'
7, 1, 15, 1, 0, 15, 2, 15, // 153 - 'TM'
5, 72, 85, 86, 85, 36, // 154 - 's with caron'
3, 34, 20, 8, // 155 - '> quotation'
7, 56, 68, 68, 124, 84, 84, 8, // 156 - 'oe'
0, // 157 - 'Not used'
5, 68, 101, 86, 77, 68, // 158 - 'z with caron'
5, 12, 17, 96, 17, 12, // 159 - 'Y diaresis'
2, 0, 0, // 160 - 'Non-breaking space'
1, 125, // 161 - 'Inverted !'
5, 60, 36, 126, 36, 36, // 162 - 'Cent sign'
5, 72, 126, 73, 65, 102, // 163 - 'Pound sign'
5, 34, 28, 20, 28, 34, // 164 - 'Currency sign'
5, 43, 47, 252, 47, 43, // 165 - 'Yen'
1, 119, // 166 - '|'
4, 102, 137, 149, 106, // 167 - 'Section sign'
3, 1, 0, 1, // 168 - 'Spacing diaresis'
7, 62, 65, 93, 85, 85, 65, 62, // 169 - 'Copyright'
3, 13, 13, 15, // 170 - 'Feminine Ordinal Ind.'
5, 8, 20, 42, 20, 34, // 171 - '<<'
5, 8, 8, 8, 8, 56, // 172 - 'Not sign'
0, // 173 - 'Soft Hyphen'
7, 62, 65, 127, 75, 117, 65, 62, // 174 - 'Registered Trademark'
5, 1, 1, 1, 1, 1, // 175 - 'Spacing Macron Overline'
3, 2, 5, 2, // 176 - 'Degree'
5, 68, 68, 95, 68, 68, // 177 - '+/-'
3, 25, 21, 19, // 178 - 'Superscript 2'
3, 17, 21, 31, // 179 - 'Superscript 3'
2, 2, 1, // 180 - 'Acute accent'
4, 252, 64, 64, 60, // 181 - 'micro (mu)'
5, 6, 9, 127, 1, 127, // 182 - 'Paragraph Mark'
2, 24, 24, // 183 - 'Middle Dot'
3, 128, 128, 96, // 184 - 'Spacing sedilla'
2, 2, 31, // 185 - 'Superscript 1'
4, 6, 9, 9, 6, // 186 - 'Masculine Ordinal Ind.'
5, 34, 20, 42, 20, 8, // 187 - '>>'
6, 64, 47, 16, 40, 52, 250, // 188 - '1/4'
6, 64, 47, 16, 200, 172, 186, // 189 - '1/2'
6, 85, 53, 31, 40, 52, 250, // 190 - '3/4'
5, 48, 72, 77, 64, 32, // 191 - 'Inverted ?'
5, 120, 20, 21, 22, 120, // 192 - 'A grave'
5, 120, 22, 21, 20, 120, // 193 - 'A acute'
5, 122, 21, 21, 21, 122, // 194 - 'A circumflex'
5, 120, 22, 21, 22, 121, // 195 - 'A tilde'
5, 120, 21, 20, 21, 120, // 196 - 'A diaresis'
5, 120, 20, 21, 20, 120, // 197 - 'A ring above'
6, 124, 10, 9, 127, 73, 73, // 198 - 'AE'
5, 30, 161, 161, 97, 18, // 199 - 'C sedilla'
4, 124, 85, 86, 68, // 200 - 'E grave'
4, 124, 86, 85, 68, // 201 - 'E acute'
4, 126, 85, 85, 70, // 202 - 'E circumflex'
4, 124, 85, 84, 69, // 203 - 'E diaresis'
3, 68, 125, 70, // 204 - 'I grave'
3, 68, 126, 69, // 205 - 'I acute'
3, 70, 125, 70, // 206 - 'I circumplex'
3, 69, 124, 69, // 207 - 'I diaresis'
6, 4, 127, 69, 65, 65, 62, // 208 - 'Capital Eth'
5, 124, 10, 17, 34, 125, // 209 - 'N tilde'
5, 56, 68, 69, 70, 56, // 210 - 'O grave'
5, 56, 70, 69, 68, 56, // 211 - 'O acute'
5, 58, 69, 69, 69, 58, // 212 - 'O circumflex'
5, 56, 70, 69, 70, 57, // 213 - 'O tilde'
5, 56, 69, 68, 69, 56, // 214 - 'O diaresis'
5, 34, 20, 8, 20, 34, // 215 - 'Multiplication sign'
7, 64, 62, 81, 73, 69, 62, 1, // 216 - 'O slashed'
5, 60, 65, 66, 64, 60, // 217 - 'U grave'
5, 60, 64, 66, 65, 60, // 218 - 'U acute'
5, 58, 65, 65, 65, 58, // 219 - 'U circumflex'
5, 60, 65, 64, 65, 60, // 220 - 'U diaresis'
5, 12, 16, 98, 17, 12, // 221 - 'Y acute'
4, 127, 18, 18, 12, // 222 - 'Capital thorn'
4, 254, 37, 37, 26, // 223 - 'Small letter sharp S'
5, 32, 84, 85, 122, 64, // 224 - 'a grave'
5, 32, 84, 86, 121, 64, // 225 - 'a acute'
5, 34, 85, 85, 121, 66, // 226 - 'a circumflex'
5, 32, 86, 85, 122, 65, // 227 - 'a tilde'
5, 32, 85, 84, 121, 64, // 228 - 'a diaresis'
5, 32, 84, 85, 120, 64, // 229 - 'a ring above'
7, 32, 84, 84, 124, 84, 84, 8, // 230 - 'ae'
5, 24, 36, 164, 228, 40, // 231 - 'c sedilla'
5, 56, 84, 85, 86, 88, // 232 - 'e grave'
5, 56, 84, 86, 85, 88, // 233 - 'e acute'
5, 58, 85, 85, 85, 90, // 234 - 'e circumflex'
5, 56, 85, 84, 85, 88, // 235 - 'e diaresis'
3, 68, 125, 66, // 236 - 'i grave'
3, 68, 126, 65, // 237 - 'i acute'
3, 70, 125, 66, // 238 - 'i circumflex'
3, 69, 124, 65, // 239 - 'i diaresis'
4, 48, 75, 74, 61, // 240 - 'Small eth'
4, 122, 9, 10, 113, // 241 - 'n tilde'
5, 56, 68, 69, 70, 56, // 242 - 'o grave'
5, 56, 70, 69, 68, 56, // 243 - 'o acute'
5, 58, 69, 69, 69, 58, // 244 - 'o circumflex'
5, 56, 70, 69, 70, 57, // 245 - 'o tilde'
5, 56, 69, 68, 69, 56, // 246 - 'o diaresis'
5, 8, 8, 42, 8, 8, // 247 - 'Division sign'
6, 64, 56, 84, 76, 68, 58, // 248 - 'o slashed'
5, 60, 65, 66, 32, 124, // 249 - 'u grave'
5, 60, 64, 66, 33, 124, // 250 - 'u acute'
5, 58, 65, 65, 33, 122, // 251 - 'u circumflex'
5, 60, 65, 64, 33, 124, // 252 - 'u diaresis'
4, 156, 162, 161, 124, // 253 - 'y acute'
4, 252, 72, 72, 48, // 254 - 'small thorn'
4, 157, 160, 160, 125, // 255 - 'y diaresis'
};
#endif

View File

@@ -0,0 +1,179 @@
// Program to demonstrate the MD_Parola library
//
// Demonstrated how UTF-8 multi-byte characters can be mapped to Extended ASCII
// characters that can be displayed with a suitable font file.
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include "Parola_Fonts_data.h"
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 8
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// Hardware SPI connection
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
const uint16_t PAUSE_TIME = 2000;
// Turn on debug statements to the serial output
#define DEBUG 0
#if DEBUG
#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }
#define PRINTS(x) Serial.print(F(x))
#define PRINTX(s, x) { Serial.print(F(s)); Serial.print(x, HEX); }
#else
#define PRINT(s, x)
#define PRINTS(x)
#define PRINTX(s, x)
#endif
// Global variables
char *pc[] =
{
"abcABC",
"äöüßÄÖÜ",
"50€/kg³",
"Español",
"30m/s²",
"Français",
"20µs/°C",
};
uint8_t utf8Ascii(uint8_t ascii)
// Convert a single Character from UTF8 to Extended ASCII according to ISO 8859-1,
// also called ISO Latin-1. Codes 128-159 contain the Microsoft Windows Latin-1
// extended characters:
// - codes 0..127 are identical in ASCII and UTF-8
// - codes 160..191 in ISO-8859-1 and Windows-1252 are two-byte characters in UTF-8
// + 0xC2 then second byte identical to the extended ASCII code.
// - codes 192..255 in ISO-8859-1 and Windows-1252 are two-byte characters in UTF-8
// + 0xC3 then second byte differs only in the first two bits to extended ASCII code.
// - codes 128..159 in Windows-1252 are different, but usually only the €-symbol will be needed from this range.
// + The euro symbol is 0x80 in Windows-1252, 0xa4 in ISO-8859-15, and 0xe2 0x82 0xac in UTF-8.
//
// Modified from original code at http://playground.arduino.cc/Main/Utf8ascii
// Extended ASCII encoding should match the characters at http://www.ascii-code.com/
//
// Return "0" if a byte has to be ignored.
{
static uint8_t cPrev;
uint8_t c = '\0';
if (ascii < 0x7f) // Standard ASCII-set 0..0x7F, no conversion
{
cPrev = '\0';
c = ascii;
}
else
{
switch (cPrev) // Conversion depending on preceding UTF8-character
{
case 0xC2: c = ascii; break;
case 0xC3: c = ascii | 0xC0; break;
case 0x82: if (ascii==0xAC) c = 0x80; // Euro symbol special case
}
cPrev = ascii; // save last char
}
PRINTX("\nConverted 0x", ascii);
PRINTX(" to 0x", c);
return(c);
}
void utf8Ascii(char* s)
// In place conversion UTF-8 string to Extended ASCII
// The extended ASCII string is always shorter.
{
uint8_t c, k = 0;
char *cp = s;
PRINT("\nConverting: ", s);
while (*s != '\0')
{
c = utf8Ascii(*s++);
if (c != '\0')
*cp++ = c;
}
*cp = '\0'; // terminate the new string
}
void setup(void)
{
#if DEBUG
Serial.begin(57600);
#endif
PRINTS("\n[Parola UTF-8 display Test]");
// Do one time in-place conversion of the strings to be displayed
for (uint8_t i=0; i<ARRAY_SIZE(pc); i++)
utf8Ascii(pc[i]);
// Initialise the Parola library
P.begin();
P.setInvert(false);
P.setPause(PAUSE_TIME);
P.setFont(ExtASCII);
}
void loop(void)
{
static uint32_t timeLast = PAUSE_TIME;
static uint16_t idx = 0;
static bool showMessage = true;
if (millis() - timeLast <= PAUSE_TIME)
return;
timeLast = millis();
if (showMessage)
{
// show the strings with the UTF-8 characters
PRINT("\nS:", idx);
PRINT(" - ", pc[idx]);
P.print(pc[idx]);
// Set the display for the next string.
idx++;
if (idx == ARRAY_SIZE(pc))
{
showMessage = false;
idx = 128;
}
}
else
{
// show the list of characters in order
char szMsg[20];
sprintf(szMsg, "%3d %c", idx, idx);
PRINT("\nC:", idx);
PRINT(" - ", szMsg);
P.print(szMsg);
// set up for next character
idx++;
if (idx == 256)
{
idx = 0;
showMessage = true;
}
}
}

View File

@@ -0,0 +1,164 @@
// Program to demonstrate the MD_Parola library
//
// For every string defined by pc[] iterate through all combinations
// of entry and exit effects in each zone independently.
//
// Animation speed can be controlled using a pot on pin SPEED_IN
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 9
#define MAX_ZONES 3
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// set to 1 if we are implementing the user interface pot
#define USE_UI_CONTROL 0
#if USE_UI_CONTROL
#define SPEED_IN A5
#endif // USE_UI_CONTROL
// Hardware SPI connection
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
#define SPEED_TIME 25
#define PAUSE_TIME 1000
// Turn on debug statements to the serial output
#define DEBUG 0
#if DEBUG
#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }
#define PRINTS(x) Serial.print(F(x))
#define PRINTX(x) Serial.println(x, HEX)
#else
#define PRINT(s, x)
#define PRINTS(x)
#define PRINTX(x)
#endif
// Global variables
uint8_t curText;
char *pc[MAX_ZONES] =
{
"GHI",
"DEF",
"ABC",
};
textEffect_t effect[] =
{
PA_RANDOM,
PA_PRINT,
PA_SCAN_HORIZ,
PA_SCROLL_LEFT,
PA_WIPE,
PA_ROCKET,
PA_SCAN_VERTX,
PA_SCROLL_UP_LEFT,
PA_SCROLL_UP,
PA_FADE,
PA_OPENING_CURSOR,
PA_GROW_UP,
PA_SCROLL_UP_RIGHT,
PA_BLINDS,
PA_CLOSING,
PA_GROW_DOWN,
PA_PACMAN2,
PA_SCAN_VERT,
PA_SCROLL_DOWN_LEFT,
PA_WIPE_CURSOR,
PA_SCAN_HORIZX,
PA_DISSOLVE,
PA_MESH,
PA_OPENING,
PA_CLOSING_CURSOR,
PA_SCROLL_DOWN_RIGHT,
PA_SCROLL_RIGHT,
PA_SLICE,
PA_SCROLL_DOWN,
PA_PACMAN1,
};
uint8_t inFX[MAX_ZONES] = { 0, ARRAY_SIZE(effect) / 3, 2 * ARRAY_SIZE(effect) / 3 };
uint8_t outFX[MAX_ZONES] = { 0, ARRAY_SIZE(effect) / 3, 2 * ARRAY_SIZE(effect) / 3 };
#if USE_UI_CONTROL
void doUI(void)
{
// set the speed if it has changed
{
int16_t speed = map(analogRead(SPEED_IN), 0, 1023, 0, 250);
if (speed != (int16_t)P.getSpeed())
{
P.setSpeed(speed);
P.setPause(speed);
PRINT("\nChanged speed to ", P.getSpeed());
}
}
}
#endif // USE_UI_CONTROL
void setup(void)
{
#if DEBUG
Serial.begin(57600);
PRINTS("[Parola Zone Display Demo]");
#endif
#if USE_UI_CONTROL
pinMode(SPEED_IN, INPUT);
doUI();
#endif // USE_UI_CONTROL
P.begin(MAX_ZONES);
P.setInvert(false);
P.setZone(0, 0, 2);
P.setZone(1, 3, 5);
P.setZone(2, 6, 8);
for (uint8_t i=0; i<MAX_ZONES; i++)
P.displayZoneText(i, pc[i], PA_CENTER, SPEED_TIME, PAUSE_TIME, effect[inFX[i]], effect[outFX[i]]);
}
void loop(void)
{
#if USE_UI_CONTROL
doUI();
#endif // USE_UI_CONTROL
if (P.displayAnimate()) // animates and returns true when an animation is completed
{
for (uint8_t i=0; i<MAX_ZONES; i++)
{
if (P.getZoneStatus(i))
{
outFX[i] = (++outFX[i]) % ARRAY_SIZE(effect);
if (outFX[i] == 0)
inFX[i] = (++inFX[i]) % ARRAY_SIZE(effect);
P.setTextEffect(i, effect[inFX[i]], effect[outFX[i]]);
// Tell Parola we have a new animation
P.displayReset(i);
}
}
}
}

View File

@@ -0,0 +1,110 @@
// Program to demonstrate using dynamic (changing) zones with the MD_Parola library
//
// Zones are changed by 2 modules for each iteration and a simple string
// is displayed in the zone.
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
// Turn on debug statements to the serial output
#define DEBUG 0
#if DEBUG
#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }
#define PRINTS(x) Serial.print(F(x))
#define PRINTX(x) Serial.println(x, HEX)
#else
#define PRINT(s, x)
#define PRINTS(x)
#define PRINTX(x)
#endif
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 8
#define MAX_ZONES 2
#define STEP_SIZE 2
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// Hardware SPI connection
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
#define SPEED_TIME 25
#define PAUSE_TIME 1000
// Global variables
char *pc[MAX_ZONES] =
{
"Zone0",
"Zone1",
};
void setZones(void)
{
static uint8_t zoneBoundary = 0;
PRINTS("\nZones");
if (zoneBoundary != 0)
{
P.setZone(0, 0, zoneBoundary-1);
PRINT(" [0] 0:", zoneBoundary - 1);
P.displayZoneText(0, pc[0], PA_CENTER, SPEED_TIME, PAUSE_TIME, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
P.displayReset(0);
}
if (zoneBoundary != MAX_DEVICES)
{
P.setZone(1, zoneBoundary, MAX_DEVICES-1);
PRINT(" [1] ", zoneBoundary);
PRINT(":", MAX_DEVICES-1);
P.displayZoneText(1, pc[1], PA_CENTER, SPEED_TIME, PAUSE_TIME, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
P.displayReset(1);
}
// Set new zone sizes
zoneBoundary += STEP_SIZE;
if (zoneBoundary > MAX_DEVICES) zoneBoundary = 0;
P.synchZoneStart();
}
void setup(void)
{
#if DEBUG
Serial.begin(57600);
#endif
PRINTS("[Parola Dynamic Zone Demo]");
P.begin(MAX_ZONES);
P.setInvert(false);
setZones();
}
void loop(void)
{
if (P.displayAnimate()) // animates and returns true when an animation is completed
{
boolean bAllDone = true;
for (uint8_t i=0; i<MAX_ZONES && bAllDone; i++)
{
bAllDone = bAllDone && P.getZoneStatus(i);
}
if (bAllDone) setZones();
}
}

View File

@@ -0,0 +1,130 @@
// Program to demonstrate the MD_Parola library
//
// Display messages in the zones. Wait for each zone to display before continuing
//
// Animation speed can be controlled using a pot on pin SPEED_IN
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 8
#define MAX_ZONES 4
#define ZONE_SIZE (MAX_DEVICES/MAX_ZONES) // integer multiple works best
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// Hardware SPI connection
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
#define SPEED_TIME 25
#define PAUSE_TIME 1000
// Turn on debug statements to the serial output
#define DEBUG 0
#if DEBUG
#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }
#define PRINTS(x) Serial.print(F(x))
#define PRINTX(x) Serial.println(x, HEX)
#else
#define PRINT(s, x)
#define PRINTS(x)
#define PRINTX(x)
#endif
// Global variables
uint8_t curText;
char *pc[] =
{
"M1",
"M2",
"M3",
"M4",
"M5",
};
uint8_t curFX = 0;
textEffect_t effect[] =
{
PA_PRINT,
PA_SCAN_HORIZ,
PA_SCROLL_LEFT,
PA_WIPE,
PA_RANDOM,
PA_SCROLL_UP_LEFT,
PA_SCROLL_UP,
PA_FADE,
PA_OPENING_CURSOR,
PA_GROW_UP,
PA_SCROLL_UP_RIGHT,
PA_BLINDS,
PA_MESH,
PA_CLOSING,
PA_GROW_DOWN,
PA_SCAN_VERT,
PA_SCROLL_DOWN_LEFT,
PA_WIPE_CURSOR,
PA_DISSOLVE,
PA_OPENING,
PA_CLOSING_CURSOR,
PA_SCROLL_DOWN_RIGHT,
PA_SCROLL_RIGHT,
PA_SLICE,
PA_SCROLL_DOWN,
};
void setup(void)
{
#if DEBUG
Serial.begin(57600);
PRINTS("[Parola Zone Mesg Demo]");
#endif
P.begin(MAX_ZONES);
P.setInvert(false);
for (uint8_t i=0; i<MAX_ZONES; i++)
{
P.setZone(i, ZONE_SIZE*i, (ZONE_SIZE*(i+1))-1);
PRINT("\nZ", i);
PRINT(" from ", ZONE_SIZE*i);
PRINT(" to ", (ZONE_SIZE*(i+1))-1);
}
}
void loop(void)
{
static uint8_t curZone = 0;
uint8_t inFX = ++curFX % ARRAY_SIZE(effect);
uint8_t outFX = ++curFX % ARRAY_SIZE(effect);
PRINT("\nNew Z", curZone);
PRINT(": ", pc[curText]);
PRINT(" @ ", millis());
P.displayZoneText(curZone, pc[curText], PA_CENTER, SPEED_TIME, PAUSE_TIME, effect[inFX], effect[outFX]);
// Check for individual zone completion. Note that we check the status of the zone rather than use the
// return status of the displayAnimate() method as the other unused zones are completed, but we
// still need to call it to run the animations.
while (!P.getZoneStatus(curZone))
P.displayAnimate();
// increment for next time
curText = ++curText % ARRAY_SIZE(pc);
curZone = ++curZone % MAX_ZONES;
}

View File

@@ -0,0 +1,125 @@
// Program to demonstrate the MD_Parola library
//
// Iterate through all combinations of entry and exit effects
// in 2 zones - one in normal mode and the second in inverted
// mirrored mode.
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 8
#define MAX_ZONES 2
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// Hardware SPI connection
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
#define SPEED_TIME 25
#define PAUSE_TIME 1000
// Turn on debug statements to the serial output
#define DEBUG 0
#if DEBUG
#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }
#define PRINTS(x) Serial.print(F(x))
#define PRINTX(x) Serial.println(x, HEX)
#else
#define PRINT(s, x)
#define PRINTS(x)
#define PRINTX(x)
#endif
// Global variables
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
// Global data
typedef struct
{
textEffect_t effect; // text effect to display
char * psz; // text string nul terminated
uint16_t speed; // speed multiplier of library default
uint16_t pause; // pause multiplier for library default
} sCatalog;
sCatalog catalog[] =
{
{ PA_PRINT, "PRINT", 1, 1 },
// { PA_SLICE, "SLICE", 1, 1 },
{ PA_MESH, "MESH", 20, 1 },
{ PA_WIPE, "WIPE", 3, 1 },
{ PA_WIPE_CURSOR, "WPE_C", 4, 1 },
{ PA_RANDOM, "RAND", 3, 1 },
{ PA_OPENING, "OPEN", 3, 1 },
{ PA_OPENING_CURSOR, "OPN_C", 4, 1 },
{ PA_CLOSING, "CLOSE", 3, 1 },
{ PA_CLOSING_CURSOR, "CLS_C", 4, 1 },
{ PA_BLINDS, "BLIND", 7, 1 },
{ PA_DISSOLVE, "DSLVE", 7, 1 },
{ PA_SCROLL_UP, "SC_U", 5, 1 },
{ PA_SCROLL_DOWN, "SC_D", 5, 1 },
// { PA_SCROLL_LEFT, "SC_L", 5, 1 },
// { PA_SCROLL_RIGHT, "SC_R", 5, 1 },
{ PA_SCROLL_UP_LEFT, "SC_UL", 7, 1 },
{ PA_SCROLL_UP_RIGHT, "SC_UR", 7, 1 },
{ PA_SCROLL_DOWN_LEFT, "SC_DL", 7, 1 },
{ PA_SCROLL_DOWN_RIGHT, "SC_DR", 7, 1 },
{ PA_SCAN_HORIZ, "SCNH", 4, 1 },
{ PA_SCAN_HORIZX, "SCNHX", 4, 1 },
{ PA_SCAN_VERT, "SCNV", 3, 1 },
{ PA_SCAN_VERTX, "SCNVX", 3, 1 },
{ PA_GROW_UP, "GRW_U", 7, 1 },
{ PA_GROW_DOWN, "GRW_D", 7, 1 },
};
void setup(void)
{
#if DEBUG
Serial.begin(57600);
PRINTS("[Parola Zone Mirror]");
#endif
P.begin(MAX_ZONES);
P.setInvert(false);
for (uint8_t i=0; i<ARRAY_SIZE(catalog); i++)
{
catalog[i].speed *= P.getSpeed(); // use the library defaults as multiplier
catalog[i].pause *= 500;
}
P.setZone(0, 0, (MAX_DEVICES/2) - 1);
P.setZone(1, MAX_DEVICES/2, MAX_DEVICES-1);
P.setZoneEffect(1, true, PA_FLIP_UD);
P.setZoneEffect(1, true, PA_FLIP_LR);
}
void loop(void)
{
static uint8_t nCurIdx = 0;
// animates and returns true when an animation is completed. These are synchronised, so assume they are all done.
if (P.displayAnimate())
{
for (uint8_t z=0; z<MAX_ZONES; z++)
P.displayZoneText(z, catalog[nCurIdx].psz, PA_CENTER, catalog[nCurIdx].speed, catalog[nCurIdx].pause, catalog[nCurIdx].effect, catalog[nCurIdx].effect);
nCurIdx = (nCurIdx + 1) % ARRAY_SIZE(catalog);
}
}

View File

@@ -0,0 +1,81 @@
// Program to demonstrate the MD_Parola library
//
// Demonstrate use of effects on different zones to create an animated sign
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 8
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
uint8_t frameDelay = 25; // default frame delay value
// Hardware SPI connection
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
#define SPEED_TIME 25
#define SPLAT_PAUSE_TIME 50
#define TEXT_PAUSE_TIME 1000
// Global variables
uint8_t curText;
char *pc[] = { "\x00f", "Evacuate" };
void setup(void)
{
P.begin(3);
P.setZone(0, 0, 0);
P.setZone(1, 1, MAX_DEVICES-2);
P.setZone(2, MAX_DEVICES-1, MAX_DEVICES-1);
// All zones
P.setInvert(false);
P.setIntensity(4);
// Specific zones
P.displayZoneText(0, pc[0], PA_CENTER, SPEED_TIME, SPLAT_PAUSE_TIME, PA_PRINT);
P.displayZoneText(1, pc[1], PA_CENTER, SPEED_TIME, TEXT_PAUSE_TIME, PA_PRINT);
P.displayZoneText(2, pc[0], PA_CENTER, SPEED_TIME, SPLAT_PAUSE_TIME, PA_PRINT);
}
void loop(void)
{
static uint8_t inten = 0;
static int8_t offset = 1;
if (P.displayAnimate()) // animates and returns true when an animation is completed
{
// Splats
if (P.getZoneStatus(0)) // in sync with zone 2, so do both
{
inten += offset;
if (inten == 15 || inten == 0)
offset = -offset;
P.setIntensity(0, inten);
P.setIntensity(2, 15-inten);
P.displayReset(0);
P.displayReset(2);
}
// Message
if (P.getZoneStatus(1))
{
P.setInvert(1, !P.getInvert(1));
P.displayReset(1);
}
}
}

View File

@@ -0,0 +1,265 @@
// Data file for user example user defined fonts
#ifndef FONTDATA_H
#define FONTDATA_H
MD_MAX72XX::fontType_t numeric7Seg[] PROGMEM =
{
0, // 0
0, // 1
0, // 2
0, // 3
0, // 4
0, // 5
0, // 6
0, // 7
0, // 8
0, // 9
0, // 10
0, // 11
0, // 12
0, // 13
0, // 14
0, // 15
0, // 16
0, // 17
0, // 18
0, // 19
0, // 20
0, // 21
0, // 22
0, // 23
0, // 24
0, // 25
0, // 26
0, // 27
0, // 28
0, // 29
0, // 30
0, // 31
1, 0, // 32 - 'Space'
0, // 33 - '!'
0, // 34 - '"'
0, // 35 - '#'
0, // 36 - '$'
0, // 37 - '%'
0, // 38 - '&'
0, // 39 - '''
0, // 40 - '('
0, // 41 - ')'
0, // 42 - '*'
0, // 43 - '+'
0, // 44 - ','
0, // 45 - '-'
1, 64, // 46 - '.'
0, // 47 - '/'
5, 127, 65, 65, 65, 127, // 48 - '0'
5, 0, 0, 127, 0, 0, // 49 - '1'
5, 121, 73, 73, 73, 79, // 50 - '2'
5, 73, 73, 73, 73, 127, // 51 - '3'
5, 15, 8, 8, 8, 127, // 52 - '4'
5, 79, 73, 73, 73, 121, // 53 - '5'
5, 127, 73, 73, 73, 121, // 54 - '6'
5, 1, 1, 1, 1, 127, // 55 - '7'
5, 127, 73, 73, 73, 127, // 56 - '8'
5, 79, 73, 73, 73, 127, // 57 - '9'
1, 20, // 58 - ':'
0, // 59 - ';'
0, // 60 - '<'
0, // 61 - '='
0, // 62 - '>'
0, // 63 - '?'
0, // 64 - '@'
5, 127, 9, 9, 9, 127, // 65 - 'A'
5, 127, 73, 73, 73, 54, // 66 - 'B'
5, 127, 65, 65, 65, 65, // 67 - 'C'
5, 127, 65, 65, 65, 62, // 68 - 'D'
5, 127, 73, 73, 73, 73, // 69 - 'E'
5, 127, 9, 9, 9, 9, // 70 - 'F'
0, // 71 - 'G'
0, // 72 - 'H'
0, // 73 - 'I'
0, // 74 - 'J'
0, // 75 - 'K'
0, // 76 - 'L'
0, // 77 - 'M'
0, // 78 - 'N'
0, // 79 - 'O'
0, // 80 - 'P'
0, // 81 - 'Q'
0, // 82 - 'R'
0, // 83 - 'S'
0, // 84 - 'T'
0, // 85 - 'U'
0, // 86 - 'V'
0, // 87 - 'W'
0, // 88 - 'X'
0, // 89 - 'Y'
0, // 90 - 'Z'
0, // 91 - '['
0, // 92 - '\'
0, // 93 - ']'
0, // 94 - '^'
0, // 95 - '_'
0, // 96 - '`'
5, 127, 9, 9, 9, 127, // 97 - 'a'
5, 127, 73, 73, 73, 54, // 98 - 'b'
5, 127, 65, 65, 65, 65, // 99 - 'c'
5, 127, 65, 65, 65, 62, // 100 - 'd'
5, 127, 73, 73, 73, 73, // 101 - 'e'
5, 127, 9, 9, 9, 9, // 102 - 'f'
0, // 103 - 'g'
0, // 104 - 'h'
0, // 105 - 'i'
0, // 106 - 'j'
0, // 107 - 'k'
0, // 108 - 'l'
0, // 109 - 'm'
0, // 110 - 'n'
0, // 111 - 'o'
0, // 112 - 'p'
0, // 113 - 'q'
0, // 114 - 'r'
0, // 115 - 's'
0, // 116 - 't'
0, // 117 - 'u'
0, // 118 - 'v'
0, // 119 - 'w'
0, // 120 - 'x'
0, // 121 - 'y'
0, // 122 - 'z'
0, // 123 - '{'
1, 127, // 124 - '|'
0, // 125
0, // 126
0, // 127
0, // 128
0, // 129
0, // 130
0, // 131
0, // 132
0, // 133
0, // 134
0, // 135
0, // 136
0, // 137
0, // 138
0, // 139
0, // 140
0, // 141
0, // 142
0, // 143
0, // 144
0, // 145
0, // 146
0, // 147
0, // 148
0, // 149
0, // 150
0, // 151
0, // 152
0, // 153
0, // 154
0, // 155
0, // 156
0, // 157
0, // 158
0, // 159
0, // 160
0, // 161
0, // 162
0, // 163
0, // 164
0, // 165
0, // 166
0, // 167
0, // 168
0, // 169
0, // 170
0, // 171
0, // 172
0, // 173
0, // 174
0, // 175
0, // 176
0, // 177
0, // 178
0, // 179
0, // 180
0, // 181
0, // 182
0, // 183
0, // 184
0, // 185
0, // 186
0, // 187
0, // 188
0, // 189
0, // 190
0, // 191
0, // 192
0, // 193
0, // 194
0, // 195
0, // 196
0, // 197
0, // 198
0, // 199
0, // 200
0, // 201
0, // 202
0, // 203
0, // 204
0, // 205
0, // 206
0, // 207
0, // 208
0, // 209
0, // 210
0, // 211
0, // 212
0, // 213
0, // 214
0, // 215
0, // 216
0, // 217
0, // 218
0, // 219
0, // 220
0, // 221
0, // 222
0, // 223
0, // 224
0, // 225
0, // 226
0, // 227
0, // 228
0, // 229
0, // 230
0, // 231
0, // 232
0, // 233
0, // 234
0, // 235
0, // 236
0, // 237
0, // 238
0, // 239
0, // 240
0, // 241
0, // 242
0, // 243
0, // 244
0, // 245
0, // 246
0, // 247
0, // 248
0, // 249
0, // 250
0, // 251
0, // 252
0, // 253
0, // 254
0, // 255
};
#endif

View File

@@ -0,0 +1,243 @@
// Program to demonstrate the MD_Parola library
//
// Display the time in one zone and other information scrolling through in
// another zone.
// - Time is shown in a user defined fixed width font
// - Scrolling text uses the default font
// - Temperature display uses user defined characters
// - Optional use of DS1307 module for time and DHT11 sensor for temp and humidity
// - DS1307 library (MD_DS1307) found at https://github.com/MajicDesigns/DS1307
// - DHT11 library (DHT11_lib) found at http://arduino.cc/playground/Main/DHT11Lib
//
// NOTE: MD_MAX72xx library must be installed and configured for the LED
// matrix type being used. Refer documentation included in the MD_MAX72xx
// library or see this link:
// https://majicdesigns.github.io/MD_MAX72XX/page_hardware.html
//
// Use the DHT11 temp and humidity sensor
#define USE_DHT11 0
// Use the DS1307 clock module
#define USE_DS1307 0
// Header file includes
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include "Font_Data.h"
// Define the number of devices we have in the chain and the hardware interface
// NOTE: These pin numbers will probably not work with your hardware and may
// need to be adapted
#define MAX_DEVICES 10
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
#if USE_DHT11
#include <dht11.h>
#define DHT11_PIN 2
dht11 DHT11;
#endif
#if USE_DS1307
#include <MD_DS1307.h>
#include <Wire.h>
#endif
// Hardware SPI connection
MD_Parola P = MD_Parola(CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
#define SPEED_TIME 75
#define PAUSE_TIME 0
#define MAX_MESG 20
// Turn on debug statements to the serial output
#define DEBUG 0
// Global variables
char szTime[9]; // mm:ss\0
char szMesg[MAX_MESG+1] = "";
uint8_t degC[] = { 6, 3, 3, 56, 68, 68, 68 }; // Deg C
uint8_t degF[] = { 6, 3, 3, 124, 20, 20, 4 }; // Deg F
char *mon2str(uint8_t mon, char *psz, uint8_t len)
// Get a label from PROGMEM into a char array
{
static const __FlashStringHelper* str[] =
{
F("Jan"), F("Feb"), F("Mar"), F("Apr"),
F("May"), F("Jun"), F("Jul"), F("Aug"),
F("Sep"), F("Oct"), F("Nov"), F("Dec")
};
strncpy_P(psz, (const char PROGMEM *)str[mon-1], len);
psz[len] = '\0';
return(psz);
}
char *dow2str(uint8_t code, char *psz, uint8_t len)
{
static const __FlashStringHelper* str[] =
{
F("Sunday"), F("Monday"), F("Tuesday"),
F("Wednesday"), F("Thursday"), F("Friday"),
F("Saturday")
};
strncpy_P(psz, (const char PROGMEM *)str[code-1], len);
psz[len] = '\0';
return(psz);
}
void getTime(char *psz, bool f = true)
// Code for reading clock time
{
#if USE_DS1307
RTC.readTime();
sprintf(psz, "%02d%c%02d", RTC.h, (f ? ':' : ' '), RTC.m);
#else
uint16_t h, m, s;
s = millis()/1000;
m = s/60;
h = m/60;
m %= 60;
s %= 60;
sprintf(psz, "%02d%c%02d", h, (f ? ':' : ' '), m);
#endif
}
void getDate(char *psz)
// Code for reading clock date
{
#if USE_DS1307
char szBuf[10];
RTC.readTime();
sprintf(psz, "%d %s %04d", RTC.dd, mon2str(RTC.mm, szBuf, sizeof(szBuf)-1), RTC.yyyy);
#else
strcpy(szMesg, "29 Feb 2016");
#endif
}
void setup(void)
{
P.begin(2);
P.setInvert(false);
P.setZone(0, 0, MAX_DEVICES-5);
P.setZone(1, MAX_DEVICES-4, MAX_DEVICES-1);
P.setFont(1, numeric7Seg);
P.displayZoneText(1, szTime, PA_CENTER, SPEED_TIME, PAUSE_TIME, PA_PRINT, PA_NO_EFFECT);
P.displayZoneText(0, szMesg, PA_CENTER, SPEED_TIME, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
P.addChar('$', degC);
P.addChar('&', degF);
#if USE_DS1307
RTC.control(DS1307_CLOCK_HALT, DS1307_OFF);
RTC.control(DS1307_12H, DS1307_OFF);
#endif
getTime(szTime);
}
void loop(void)
{
static uint32_t lastTime = 0; // millis() memory
static uint8_t display = 0; // current display mode
static bool flasher = false; // seconds passing flasher
P.displayAnimate();
if (P.getZoneStatus(0))
{
switch (display)
{
case 0: // Temperature deg C
P.setTextEffect(0, PA_SCROLL_LEFT, PA_SCROLL_UP_LEFT);
display++;
#if USE_DHT11
if (DHT11.read(DHT11_PIN) == 0)
{
dtostrf(DHT11.temperature, 3, 1, szMesg);
strcat(szMesg, "$");
}
#else
strcpy(szMesg, "22.0$");
#endif
break;
case 1: // Temperature deg F
P.setTextEffect(0, PA_SCROLL_UP_LEFT, PA_SCROLL_LEFT);
display++;
#if USE_DHT11
if (DHT11.read(DHT11_PIN) == 0)
{
dtostrf((1.8 * DHT11.temperature)+32, 3, 1, szMesg);
strcat(szMesg, "&");
}
#else
strcpy(szMesg, "71.6&");
#endif
break;
case 2: // Relative Humidity
P.setTextEffect(0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
display++;
#if USE_DHT11
if (DHT11.read(DHT11_PIN) == 0)
{
dtostrf(DHT11.humidity, 3, 0, szMesg);
strcat(szMesg, "% RH");
}
#else
strcpy(szMesg, "36 % RH");
#endif
break;
case 3: // day of week
P.setTextEffect(0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
display++;
#if USE_DS1307
dow2str(RTC.dow, szMesg, MAX_MESG);
#else
dow2str(4, szMesg, MAX_MESG);
#endif
break;
default: // Calendar
P.setTextEffect(0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
display = 0;
getDate(szMesg);
break;
}
P.displayReset(0);
}
// Finally, adjust the time string if we have to
if (millis() - lastTime >= 1000)
{
lastTime = millis();
getTime(szTime, flasher);
flasher = !flasher;
P.displayReset(1);
}
}

View File

@@ -0,0 +1,96 @@
#######################################
# Syntax Coloring Map
#######################################
#######################################
# Classes and datatypes (KEYWORD1)
#######################################
MD_Parola KEYWORD1
MD_PZone KEYWORD1
textPosition_t KEYWORD1
textEffect_t KEYWORD1
#######################################
# Methods and functions (KEYWORD2)
#######################################
addChar KEYWORD2
delChar KEYWORD2
begin KEYWORD2
displayAnimate KEYWORD2
displayClear KEYWORD2
displayReset KEYWORD2
displayScroll KEYWORD2
displayText KEYWORD2
displaySuspend KEYWORD2
displayShutdown KEYWORD2
getCharSpacing KEYWORD2
getDisplayExtent KEYWORD2
getGraphicObject KEYWORD2
getIntensity KEYWORD2
getInvert KEYWORD2
getPause KEYWORD2
getScrollSpacing KEYWORD2
getSpeed KEYWORD2
getStatus KEYWORD2
getTextAlignment KEYWORD2
getTextExtent KEYWORD2
getZoneEffect KEYWORD2
getZoneExtent KEYWORD2
isAnimationAdvanced KEYWORD2
setCharSpacing KEYWORD2
setFont KEYWORD2
setIntensity KEYWORD2
setInvert KEYWORD2
setPause KEYWORD2
setScrollSpacing KEYWORD2
setSpeed KEYWORD2
setSpriteData KEYWORD2
setTextAlignment KEYWORD2
setTextBuffer KEYWORD2
setTextEffect KEYWORD2
setZoneEffect KEYWORD2
setZone KEYWORD2
synchZoneStart KEYWORD2
displayZoneText KEYWORD2
######################################
# Constants/defines (LITERAL1)
#######################################
PA_LEFT LITERAL1
PA_CENTER LITERAL1
PA_RIGHT LITERAL1
PA_NO_EFFECT LITERAL1
PA_PRINT LITERAL1
PA_SLICE LITERAL1
PA_WIPE LITERAL1
PA_MESH LITERAL1
PA_FADE LITERAL1
PA_RANDOM LITERAL1
PA_WIPE_CURSOR LITERAL1
PA_OPENING LITERAL1
PA_OPENING_CURSOR LITERAL1
PA_CLOSING LITERAL1
PA_CLOSING_CURSOR LITERAL1
PA_BLINDS LITERAL1
PA_DISSOLVE LITERAL1
PA_SCROLL_UP LITERAL1
PA_SCROLL_DOWN LITERAL1
PA_SCROLL_LEFT LITERAL1
PA_SCROLL_RIGHT LITERAL1
PA_SCROLL_UP_LEFT LITERAL1
PA_SCROLL_UP_RIGHT LITERAL1
PA_SCROLL_DOWN_LEFT LITERAL1
PA_SCROLL_DOWN_RIGHT LITERAL1
PA_SCAN_HORIZ LITERAL1
PA_SCAN_HORIZX LITERAL1
PA_SCAN_VERT LITERAL1
PA_SCAN_VERTX LITERAL1
PA_GROW_UP LITERAL1
PA_GROW_DOWN LITERAL1
PA_SCAN_HORIZ LITERAL1
PA_SCAN_VERT LITERAL1
PA_FLIP_UD LITERAL1
PA_FLIP_LR LITERAL1
PA_PACMAN1 LITERAL1
PA_PACMAN2 LITERAL1
PA_ROCKET LITERAL1

View File

@@ -0,0 +1,10 @@
name=MD_Parola
version=2.7.4
author=majicDesigns
maintainer=marco_c <8136821@gmail.com>
sentence=LED matrix text display special effects
paragraph=Implemented using the MD_MAX72xx library for hardware control. Provides functions to simplify the implementation of text special effects on the LED matrix.
category=Display
url=https://github.com/MajicDesigns/MD_Parola
architectures=*
includes=MD_Parola.h,MD_MAX72xx.h,SPI.h

View File

@@ -0,0 +1,602 @@
/*
MD_Parola - Library for modular scrolling text and Effects
See header file for comments
Copyright (C) 2013 Marco Colli. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <MD_Parola.h>
#include <MD_Parola_lib.h>
#include <MD_MAX72xx.h>
/**
* \file
* \brief Implements MD_PZone class methods
*/
MD_PZone::MD_PZone(void) : _fsmState(END), _scrollDistance(0), _zoneEffect(0), _charSpacing(1),
_fontDef(nullptr), _userChars(nullptr), _cBufSize(0), _cBuf(nullptr)
#if ENA_SPRITE
, _spriteInData(nullptr), _spriteOutData(nullptr)
#endif
{
};
MD_PZone::~MD_PZone(void)
{
// release the memory for user defined characters
charDef_t *p = _userChars;
while (p!= nullptr)
{
charDef_t *pt = p;
p = pt->next;
delete pt;
};
// release memory for the character buffer
delete[] _cBuf;
}
void MD_PZone::begin(MD_MAX72XX *p)
{
_MX = p;
allocateFontBuffer();
}
void MD_PZone::allocateFontBuffer(void)
{
uint8_t size = _MX->getMaxFontWidth() + getCharSpacing();
PRINTS("\nallocateFontBuffer");
if (size > _cBufSize)
{
delete[] _cBuf;
_cBufSize = size;
PRINT(" new size ", _cBufSize);
_cBuf = new uint8_t[_cBufSize];
}
}
void MD_PZone::setZoneEffect(boolean b, zoneEffect_t ze)
{
switch (ze)
{
case PA_FLIP_LR: _zoneEffect = (b ? ZE_SET(_zoneEffect, ZE_FLIP_LR_MASK) : ZE_RESET(_zoneEffect, ZE_FLIP_LR_MASK)); break;
case PA_FLIP_UD: _zoneEffect = (b ? ZE_SET(_zoneEffect, ZE_FLIP_UD_MASK) : ZE_RESET(_zoneEffect, ZE_FLIP_UD_MASK)); break;
}
return;
}
boolean MD_PZone::getZoneEffect(zoneEffect_t ze)
{
switch (ze)
{
case PA_FLIP_LR: return(ZE_TEST(_zoneEffect, ZE_FLIP_LR_MASK)); break;
case PA_FLIP_UD: return(ZE_TEST(_zoneEffect, ZE_FLIP_UD_MASK)); break;
}
return(false);
}
#if ENA_SPRITE
void MD_PZone::setSpriteData(uint8_t *inData, uint8_t inWidth, uint8_t inFrames, uint8_t* outData, uint8_t outWidth, uint8_t outFrames)
{
_spriteInData = inData;
_spriteInWidth = inWidth;
_spriteInFrames = inFrames;
_spriteOutData = outData;
_spriteOutWidth = outWidth;
_spriteOutFrames = outFrames;
}
#endif
void MD_PZone::setInitialConditions(void)
// set the global variables initial conditions for all display effects
{
PRINTS("\nsetInitialConditions");
if (_pText == nullptr)
return;
_pCurChar = _pText;
_limitOverflow = !calcTextLimits(_pText);
}
void MD_PZone::setInitialEffectConditions(void)
// set the initial conditions for loops in the FSM
{
PRINTS("\nsetInitialFSMConditions");
_startPos = _nextPos = (_textAlignment == PA_RIGHT ? _limitRight : _limitLeft);
_endPos = (_textAlignment == PA_RIGHT ? _limitLeft : _limitRight);
_posOffset = (_textAlignment == PA_RIGHT ? 1 : -1);
}
uint16_t MD_PZone::getTextWidth(char *p)
// Get the width in columns for the text string passed to the function
// This is the sum of all the characters and the space between them.
{
uint16_t sum = 0;
PRINT("\ngetTextWidth: ", p);
while (*p != '\0')
{
sum += findChar(*p++, _cBufSize, _cBuf);
if (*p) sum += _charSpacing; // next character is not nul, so add inter-character spacing
}
PRINT("\ngetTextWidth: W=", sum);
return(sum);
}
bool MD_PZone::calcTextLimits(char *p)
// Work out left and right sides for the text to be displayed,
// depending on the text alignment. If the message will not fit
// in the current display the return false, otherwise true.
{
bool b = true;
uint16_t displayWidth = ZONE_END_COL(_zoneEnd) - ZONE_START_COL(_zoneStart) + 1;
_textLen = getTextWidth(p);
PRINT("\ncalcTextLimits: disp=", displayWidth);
PRINT(" text=", _textLen);
switch (_textAlignment)
{
case PA_LEFT:
_limitLeft = ZONE_END_COL(_zoneEnd);
if (_textLen > displayWidth)
{
_limitRight = ZONE_START_COL(_zoneStart);
b = false;
}
else
{
_limitRight = _limitLeft - _textLen + 1;
}
break;
case PA_RIGHT:
_limitRight = ZONE_START_COL(_zoneStart);
if (_textLen > displayWidth)
{
_limitLeft = ZONE_END_COL(_zoneEnd);
b = false;
}
else
{
_limitLeft = _limitRight + _textLen - 1;
}
break;
case PA_CENTER:
if (_textLen > displayWidth)
{
_limitLeft = ZONE_END_COL(_zoneEnd);
_limitRight = ZONE_START_COL(_zoneStart);
b= false;
}
else
{
_limitRight = ZONE_START_COL(_zoneStart) + ((displayWidth - _textLen)/2);
_limitLeft = _limitRight + _textLen - 1;
}
break;
}
PRINT(" -> L:", _limitLeft);
PRINT(" R:", _limitRight);
PRINT(" Oveflow:", !b);
return (b);
}
bool MD_PZone::addChar(uint8_t code, uint8_t *data)
// Add a user defined character to the replacement list
{
charDef_t *pcd;
if (code == 0)
return(false);
PRINTX("\naddChar 0x", code);
// first see if we have the code in our list
pcd = _userChars;
while (pcd != nullptr)
{
if (pcd->code == code)
{
pcd->data = data;
PRINTS(" found existing in list");
return(true);
}
pcd = pcd->next;
}
// Now see if we have an empty slot in our list
pcd = _userChars;
while (pcd != nullptr)
{
if (pcd->code == 0)
{
pcd->code = code;
pcd->data = data;
PRINTS(" found empty slot");
return(true);
}
pcd = pcd->next;
}
// default is to add a new node to the front of the list
if ((pcd = new charDef_t) != nullptr)
{
pcd->code = code;
pcd->data = data;
pcd->next = _userChars;
_userChars = pcd;
PRINTS(" added new node");
}
else
{
PRINTS(" failed allocating new node");
}
return(pcd != nullptr);
}
bool MD_PZone::delChar(uint8_t code)
// Delete a user defined character from the replacement list
{
charDef_t *pcd = _userChars;
if (code == 0)
return(false);
// Scan down the linked list
while (pcd != nullptr)
{
if (pcd->code == code)
{
pcd->code = 0;
pcd->data = nullptr;
break;
}
pcd = pcd->next;
}
return(pcd != nullptr);
}
uint8_t MD_PZone::findChar(uint8_t code, uint8_t size, uint8_t *cBuf)
// Find a character either in user defined list or from font table
{
charDef_t *pcd = _userChars;
uint8_t len;
PRINTX("\nfindUserChar 0x", code);
// check local list first
while (pcd != nullptr)
{
PRINTX(" ", pcd->code);
if (pcd->code == code) // found it
{
PRINTS(" found character");
len = min(size, pcd->data[0]);
memcpy(cBuf, &pcd->data[1], len);
return(len);
}
pcd = pcd->next;
}
// get it from the standard font
PRINTS(" no user char");
_MX->setFont(_fontDef); // change to the font for this zone
len = _MX->getChar(code, size, cBuf);
return(len);
}
uint8_t MD_PZone::makeChar(char c, bool addBlank)
// Load a character bitmap and add in trailing char spacing blanks
{
uint8_t len;
// look for the character
len = findChar((uint8_t)c, _cBufSize, _cBuf);
PRINTX("\nmakeChar 0x", c);
PRINT(", len=", len);
// Add in the inter char spacing
if (addBlank)
{
for (uint8_t i = 0; i < _charSpacing; i++)
{
if (len < _cBufSize)
_cBuf[len++] = 0;
}
}
return(len);
}
void MD_PZone::reverseBuf(uint8_t *p, uint8_t size)
// reverse the elements of the specified buffer
// useful when we are scrolling right and want to insert the columns in reverse order
{
for (uint8_t i=0; i<size/2; i++)
{
uint8_t t;
t = p[i];
p[i] = p[size-1-i];
p[size-1-i] = t;
}
}
void MD_PZone::invertBuf(uint8_t *p, uint8_t size)
// invert the elements of the specified buffer
// used when the character needs to be inverted when ZE_FLIP_UD
{
for (uint8_t i=0; i<size; i++)
{
uint8_t v = p[i];
v = ((v >> 1) & 0x55) | ((v & 0x55) << 1); // swap odd and even bits
v = ((v >> 2) & 0x33) | ((v & 0x33) << 2); // swap consecutive pairs
v = ((v >> 4) & 0x0F) | ((v & 0x0F) << 4); // swap nibbles ...
p[i] = v;
}
}
void MD_PZone::moveTextPointer(void)
// This method works when increment is done AFTER processing the character
// The _endOfText flag is set as a look ahead (ie, when the last character
// is still valid)
// We need to move a pointer forward or back, depending on the way we are
// travelling through the text buffer.
{
PRINTS("\nMovePtr");
if ((!ZE_TEST(_zoneEffect, ZE_FLIP_LR_MASK) && SFX(PA_SCROLL_RIGHT)) ||
(ZE_TEST(_zoneEffect, ZE_FLIP_LR_MASK) && !SFX(PA_SCROLL_RIGHT)))
{
PRINTS(" --");
_endOfText = (_pCurChar == _pText);
_pCurChar--;
}
else
{
PRINTS(" ++");
_pCurChar++;
_endOfText = (*_pCurChar == '\0');
}
PRINT(": endOfText ", _endOfText);
}
uint8_t MD_PZone::getFirstChar(void)
// load the first char into the char buffer
// return 0 if there are no characters
{
uint8_t len = 0;
PRINT("\ngetFirst SFX(RIGHT):", SFX(PA_SCROLL_RIGHT));
PRINT(" ZETEST(UD):", ZE_TEST(_zoneEffect, ZE_FLIP_UD_MASK));
PRINT(" ZETEST(LR):", ZE_TEST(_zoneEffect, ZE_FLIP_LR_MASK));
// initialise pointers and make sure we have a good string to process
_pCurChar = _pText;
if ((_pCurChar == nullptr) || (*_pCurChar == '\0'))
{
_endOfText = true;
return(0);
}
_endOfText = false;
if ((!ZE_TEST(_zoneEffect, ZE_FLIP_LR_MASK) && (SFX(PA_SCROLL_RIGHT))) ||
(ZE_TEST(_zoneEffect, ZE_FLIP_LR_MASK) && !SFX(PA_SCROLL_RIGHT)))
{
PRINTS("\nReversed String");
_pCurChar += strlen(_pText) - 1;
}
// good string, get the first char into the current buffer
len = makeChar(*_pCurChar, *(_pCurChar+1) != '\0');
if ((!ZE_TEST(_zoneEffect, ZE_FLIP_LR_MASK) && (SFX(PA_SCROLL_RIGHT))) ||
(ZE_TEST(_zoneEffect, ZE_FLIP_LR_MASK) && !SFX(PA_SCROLL_RIGHT)))
{
PRINTS("\nReverse Buffer");
reverseBuf(_cBuf, len);
}
if ZE_TEST(_zoneEffect, ZE_FLIP_UD_MASK)
{
PRINTS("\nInvert buffer");
invertBuf(_cBuf, len);
}
moveTextPointer();
return(len);
}
uint8_t MD_PZone::getNextChar(void)
// load the next char into the char buffer
// return 0 if there are no characters
{
uint8_t len = 0;
PRINT("\ngetNexChar SFX(RIGHT):", SFX(PA_SCROLL_RIGHT));
PRINT(" ZETEST(UD):", ZE_TEST(_zoneEffect, ZE_FLIP_UD_MASK));
PRINT(" ZETEST(LR):", ZE_TEST(_zoneEffect, ZE_FLIP_LR_MASK));
if (_endOfText)
return(0);
len = makeChar(*_pCurChar, *(_pCurChar + 1) != '\0');
if ((!ZE_TEST(_zoneEffect, ZE_FLIP_LR_MASK) && (SFX(PA_SCROLL_RIGHT))) ||
(ZE_TEST(_zoneEffect, ZE_FLIP_LR_MASK) && !SFX(PA_SCROLL_RIGHT)))
{
PRINTS("\nReversed Buffer");
reverseBuf(_cBuf, len);
}
if ZE_TEST(_zoneEffect, ZE_FLIP_UD_MASK)
{
PRINTS("\nInvert Buffer");
invertBuf(_cBuf, len);
}
moveTextPointer();
return(len);
}
bool MD_PZone::zoneAnimate(void)
{
#if TIME_PROFILING
static uint32_t cycleStartTime;
#endif
_animationAdvanced = false; // assume this will not happen this time around
if (_fsmState == END)
return(true);
// work through things that stop us running this at all
if (((_fsmState == PAUSE) && (millis() - _lastRunTime < _pauseTime)) ||
(millis() - _lastRunTime < _tickTime) ||
(_suspend))
return(false);
// save the time now, before we run the animation, so that the animation is part of the
// delay between animations giving more accurate frame timing.
_lastRunTime = millis();
_animationAdvanced = true; // we now know it will happen!
// any text to display?
if (_pText != nullptr)
{
switch (_fsmState)
{
case END: // do nothing in this state
PRINT_STATE("ANIMATE");
break;
case INITIALISE:
PRINT_STATE("ANIMATE");
#if TIME_PROFILING
cycleStartTime = millis();
#endif
setInitialConditions();
_moveIn = true;
// fall through to process the effect, first call will be with INITIALISE
default: // All state except END are handled by the special effect functions
PRINT_STATE("ANIMATE");
switch (_moveIn ? _effectIn : _effectOut)
{
case PA_PRINT: effectPrint(_moveIn); break;
case PA_SCROLL_UP: effectVScroll(true, _moveIn); break;
case PA_SCROLL_DOWN: effectVScroll(false, _moveIn); break;
case PA_SCROLL_LEFT: effectHScroll(true, _moveIn); break;
case PA_SCROLL_RIGHT: effectHScroll(false, _moveIn); break;
#if ENA_MISC
case PA_SLICE: effectSlice(_moveIn); break;
case PA_MESH: effectMesh(_moveIn); break;
case PA_FADE: effectFade(_moveIn); break;
case PA_BLINDS: effectBlinds(_moveIn); break;
case PA_DISSOLVE: effectDissolve(_moveIn); break;
case PA_RANDOM: effectRandom(_moveIn); break;
#endif // ENA_MISC
#if ENA_SPRITE
case PA_SPRITE:
effectSprite(_moveIn, _moveIn ? _effectIn : _effectOut); break;
#endif // ENA_SPRITE
#if ENA_WIPE
case PA_WIPE: effectWipe(false, _moveIn); break;
case PA_WIPE_CURSOR: effectWipe(true, _moveIn); break;
#endif // ENA_WIPE
#if ENA_SCAN
case PA_SCAN_HORIZX: effectHScan(_moveIn, true); break;
case PA_SCAN_HORIZ: effectHScan(_moveIn, false); break;
case PA_SCAN_VERTX: effectVScan(_moveIn, true); break;
case PA_SCAN_VERT: effectVScan(_moveIn, false); break;
#endif // ENA_SCAN
#if ENA_OPNCLS
case PA_OPENING: effectOpen(false, _moveIn); break;
case PA_OPENING_CURSOR: effectOpen(true, _moveIn); break;
case PA_CLOSING: effectClose(false, _moveIn);break;
case PA_CLOSING_CURSOR: effectClose(true, _moveIn); break;
#endif // ENA_OPNCLS
#if ENA_SCR_DIA
case PA_SCROLL_UP_LEFT: effectDiag(true, true, _moveIn); break;
case PA_SCROLL_UP_RIGHT: effectDiag(true, false, _moveIn); break;
case PA_SCROLL_DOWN_LEFT: effectDiag(false, true, _moveIn); break;
case PA_SCROLL_DOWN_RIGHT: effectDiag(false, false, _moveIn);break;
#endif // ENA_SCR_DIA
#if ENA_GROW
case PA_GROW_UP: effectGrow(true, _moveIn); break;
case PA_GROW_DOWN: effectGrow(false, _moveIn); break;
#endif // ENA_GROW
default:
_fsmState = END;
}
// one way toggle for input to output, reset on initialize
_moveIn = _moveIn && !(_fsmState == PAUSE);
break;
}
}
#if TIME_PROFILING
Serial.print("\nAnim time: ");
Serial.print(millis()-_lastRunTime);
if (_fsmState == END)
{
Serial.print("\nCycle time: ");
Serial.print(millis()-cycleStartTime);
}
#endif
return(_fsmState == END);
}
#if DEBUG_PAROLA_FSM
char *MD_PZone::state2string(fsmState_t s)
{
switch (s)
{
case INITIALISE: return("INIT");
case GET_FIRST_CHAR: return("FIRST");
case GET_NEXT_CHAR: return("NEXT");
case PUT_CHAR: return("PUT");
case PUT_FILLER: return("FILLER");
case PAUSE: return("PAUSE");
case END: return("END");
}
return("???");
};
#endif

View File

@@ -0,0 +1,140 @@
/*
MD_Parola - Library for modular scrolling text and Effects
See header file for comments
Copyright (C) 2013 Marco Colli. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <MD_Parola.h>
#include <MD_Parola_lib.h>
#include <MD_MAX72xx.h>
/**
* \file
* \brief Implements core MD_Parola class methods
*/
MD_Parola::MD_Parola(uint8_t dataPin, uint8_t clkPin, uint8_t csPin, uint8_t numDevices):
_D(dataPin, clkPin, csPin, numDevices), _numModules(numDevices)
{
}
MD_Parola::MD_Parola(uint8_t csPin, uint8_t numDevices):
_D(csPin, numDevices), _numModules(numDevices)
{
}
void MD_Parola::begin(uint8_t numZones)
{
_D.begin();
// Check boundaries for the number of zones
if (numZones == 0) numZones = 1;
if (numZones > MAX_ZONES) numZones = MAX_ZONES;
_numZones = numZones;
// Create the zone objects array
//_Z = new MD_PZone[_numZones]; // for dynamic array
for (uint8_t i = 0; i < _numZones; i++)
_Z[i].begin(&_D);
// for one zone automatically make it all modules, user will override if not intended
if (_numZones == 1)
setZone(0, 0, _numModules - 1);
// initialise zone-independent options
setSpeed(10);
setPause(10*getSpeed());
setCharSpacing(1);
setScrollSpacing(0);
setTextAlignment(PA_LEFT);
setTextEffect(PA_PRINT, PA_NO_EFFECT);
setTextBuffer(nullptr);
setInvert(false);
setIntensity(MAX_INTENSITY/2);
// Now set the default viewing parameters for this library
_D.setFont(nullptr);
}
MD_Parola::~MD_Parola(void)
{
// release the zone array (dynamically alocated)
//delete [] _Z;
}
bool MD_Parola::setZone(uint8_t z, uint8_t moduleStart, uint8_t moduleEnd)
{
if ((moduleStart <= moduleEnd) && (moduleEnd < _numModules) && (z < _numZones))
{
_Z[z].setZone(moduleStart, moduleEnd);
return(true);
}
return(false);
}
void MD_Parola::displayZoneText(uint8_t z, char *pText, textPosition_t align, uint16_t speed, uint16_t pause, textEffect_t effectIn, textEffect_t effectOut)
{
setTextBuffer(z, pText);
setTextAlignment(z, align);
setSpeed(z, speed);
setPause(z, pause);
setTextEffect(z, effectIn, effectOut);
displayReset(z);
}
bool MD_Parola::displayAnimate(void)
{
bool b = false;
// suspend the display while we animate a frame
_D.update(MD_MAX72XX::OFF);
for (uint8_t i = 0; i < _numZones; i++)
b |= _Z[i].zoneAnimate();
// re-enable and update the display
_D.update(MD_MAX72XX::ON);
return(b);
}
size_t MD_Parola::write(const char *str)
{
displayText((char *)str, getTextAlignment(), 0, 0, PA_PRINT, PA_NO_EFFECT);
while (displayAnimate())
/* do nothing */;
return(strlen(str));
}
size_t MD_Parola::write(const uint8_t *buffer, size_t size)
{
char *psz = (char *)malloc(sizeof(char) * (size + 1));
if (psz == nullptr) return(0);
memcpy(psz, buffer, size);
psz[size] = '\0';
write(psz);
free(psz);
return(size);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,88 @@
/*
MD_Parola - Library for modular scrolling text and Effects
See header file for comments
Copyright (C) 2013 Marco Colli. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <MD_Parola.h>
#include <MD_Parola_lib.h>
/**
* \file
* \brief Implements blinds effect
*/
const uint8_t BLINDS_SIZE = 4; ///< The width of the blinds in pixels
void MD_PZone::effectBlinds(bool bIn)
// Transfer between messages with blinds effects
{
switch (_fsmState)
{
case INITIALISE: // bIn = true
case PAUSE: // bIn = false
PRINT_STATE("IO BLIND");
_nextPos = 0;
_fsmState = GET_FIRST_CHAR;
// fall through
case GET_FIRST_CHAR: // blinds closing
PRINT_STATE("IO BLIND");
_nextPos++;
for (int16_t i=ZONE_START_COL(_zoneStart); i<=ZONE_END_COL(_zoneEnd); i++)
{
if (i % BLINDS_SIZE < _nextPos)
_MX->setColumn(i, LIGHT_BAR);
}
if (_nextPos == BLINDS_SIZE)
{
_nextPos = BLINDS_SIZE;
_fsmState = GET_NEXT_CHAR;
}
break;
case GET_NEXT_CHAR: // blinds opening
PRINT_STATE("IO BLIND");
zoneClear();
if (bIn) commonPrint(); // only do this when putting the message up
_nextPos--;
for (int16_t i=ZONE_START_COL(_zoneStart); i<=ZONE_END_COL(_zoneEnd); i++)
{
if (i % BLINDS_SIZE < _nextPos)
_MX->setColumn(i, LIGHT_BAR);
}
if (_nextPos == 0)
_fsmState = PUT_CHAR;
break;
case PUT_CHAR:
PRINT_STATE("IO BLIND");
zoneClear();
if (bIn) commonPrint();
_fsmState = (bIn ? PAUSE : END);
break;
default:
PRINT_STATE("IO BLIND");
_fsmState = (bIn ? PAUSE : END);
}
}

View File

@@ -0,0 +1,132 @@
/*
MD_Parola - Library for modular scrolling text and Effects
See header file for comments
Copyright (C) 2013 Marco Colli. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <MD_Parola.h>
#include <MD_Parola_lib.h>
/**
* \file
* \brief Implements closing effect
*/
void MD_PZone::effectClose(bool bLightBar, bool bIn)
// Dissolve the current message in/out
{
if (bIn)
{
switch (_fsmState)
{
case INITIALISE:
case GET_FIRST_CHAR:
case GET_NEXT_CHAR:
PRINT_STATE("I CLOSE");
_nextPos = 0;
zoneClear();
if (bLightBar)
{
_MX->setColumn(_limitLeft, LIGHT_BAR);
_MX->setColumn(_limitRight,LIGHT_BAR);
}
_fsmState = PUT_CHAR;
// fall through
case PUT_CHAR:
PRINT_STATE("I CLOSE");
FSMPRINT(" - offset ", _nextPos);
zoneClear();
commonPrint();
{
const int16_t halfWidth = (_limitLeft - _limitRight)/2;
if (_nextPos > halfWidth)
{
_fsmState = PAUSE;
}
else
{
for (int16_t i = _limitRight + _nextPos + 1; i < _limitLeft - _nextPos; i++)
_MX->setColumn(i, EMPTY_BAR);
_nextPos++;
if (bLightBar && (_nextPos <= halfWidth))
{
_MX->setColumn(_limitLeft - _nextPos, LIGHT_BAR);
_MX->setColumn(_limitRight + _nextPos, LIGHT_BAR);
}
}
}
break;
default:
PRINT_STATE("I CLOSE");
_fsmState = PAUSE;
}
}
else // exiting
{
switch (_fsmState)
{
case PAUSE:
case GET_FIRST_CHAR:
case GET_NEXT_CHAR:
PRINT_STATE("O CLOSE");
FSMPRINT(" - limits R:", _limitRight);
FSMPRINT(" L:", _limitLeft);
_nextPos = (_limitLeft-_limitRight)/2;
FSMPRINT(" O:", _nextPos);
zoneClear();
commonPrint();
if (bLightBar)
{
_MX->setColumn(_limitLeft - _nextPos, LIGHT_BAR);
_MX->setColumn(_limitRight + _nextPos, LIGHT_BAR);
}
_fsmState = PUT_CHAR;
break;
case PUT_CHAR:
PRINT_STATE("O CLOSE");
FSMPRINT(" - offset ", _nextPos);
if (_nextPos < 0)
{
_fsmState = END;
}
else
{
_MX->setColumn(_limitLeft - _nextPos, EMPTY_BAR);
_MX->setColumn(_limitRight + _nextPos, EMPTY_BAR);
_nextPos--;
if (bLightBar && (_nextPos >= 0))
{
_MX->setColumn(_limitLeft - _nextPos, LIGHT_BAR);
_MX->setColumn(_limitRight + _nextPos, LIGHT_BAR);
}
}
break;
default:
PRINT_STATE("O CLOSE");
_fsmState = END;
}
}
}

View File

@@ -0,0 +1,105 @@
/*
MD_Parola - Library for modular scrolling text and Effects
See header file for comments
Copyright (C) 2013 Marco Colli. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <MD_Parola.h>
#include <MD_Parola_lib.h>
/**
* \file
* \brief Implements diagonal scroll effect
*/
void MD_PZone::effectDiag(bool bUp, bool bLeft, bool bIn)
// Scroll the display diagonally up or down, left or right, depending on the selected effect
{
if (bIn) // incoming
{
switch (_fsmState)
{
case INITIALISE:
PRINT_STATE("I DIAG");
_nextPos = 0; // the position in the animation
_MX->control(_zoneStart, _zoneEnd, MD_MAX72XX::WRAPAROUND, MD_MAX72XX::OFF);
_fsmState = PUT_CHAR;
// fall through to next state
case GET_FIRST_CHAR:
case GET_NEXT_CHAR:
case PUT_CHAR:
case PAUSE:
PRINT_STATE("I DIAG");
zoneClear();
commonPrint();
for (uint8_t i = _nextPos; i < 7; i++)
{
// scroll the whole display so that the message appears to be animated
// Note: Directions are reversed because we start with the message in the
// middle position thru commonPrint() and to see it animated move DOWN we
// need to scroll it UP, and vice versa.
_MX->transform(_zoneStart, _zoneEnd, bUp ? MD_MAX72XX::TSD : MD_MAX72XX::TSU);
_MX->transform(_zoneStart, _zoneEnd, bLeft ? MD_MAX72XX::TSR : MD_MAX72XX::TSL);
}
// check if we have finished
if (_nextPos == 7) _fsmState = PAUSE;
_nextPos++;
break;
default:
PRINT_STATE("I DIAG");
_fsmState = PAUSE;
}
}
else // exiting
{
switch (_fsmState)
{
case PAUSE:
case INITIALISE:
PRINT_STATE("O DIAG");
_nextPos = 0;
_fsmState = PUT_CHAR;
// fall through to next state
case GET_FIRST_CHAR:
case GET_NEXT_CHAR:
case PUT_CHAR:
PRINT_STATE("O DIAG");
_MX->transform(_zoneStart, _zoneEnd, bUp ? MD_MAX72XX::TSU : MD_MAX72XX::TSD);
_MX->transform(_zoneStart, _zoneEnd, bLeft ? MD_MAX72XX::TSL : MD_MAX72XX::TSR);
// check if we have finished
if (_nextPos == 7) _fsmState = END;
_nextPos++;
break;
default:
PRINT_STATE("O DIAG");
_fsmState = END;
break;
}
}
}

View File

@@ -0,0 +1,74 @@
/*
MD_Parola - Library for modular scrolling text and Effects
See header file for comments
Copyright (C) 2013 Marco Colli. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <MD_Parola.h>
#include <MD_Parola_lib.h>
/**
* \file
* \brief Implements dissolve effect
*/
void MD_PZone::effectDissolve(bool bIn)
// Dissolve the current message in/out
{
switch (_fsmState)
{
case INITIALISE: // bIn = true
case PAUSE: // bIn = false
case GET_FIRST_CHAR: // first stage dissolve
PRINT_STATE("IO DISS");
for (int16_t i=ZONE_START_COL(_zoneStart); i<=ZONE_END_COL(_zoneEnd); i++)
{
uint8_t col = DATA_BAR(_MX->getColumn(i));
col |= (i&1 ? 0x55 : 0xaa); // checkerboard pattern
_MX->setColumn(i, DATA_BAR(col));
}
_fsmState = GET_NEXT_CHAR;
break;
case GET_NEXT_CHAR: // second stage dissolve
PRINT_STATE("IO DISS");
zoneClear();
if (bIn) commonPrint();
for (int16_t i=ZONE_START_COL(_zoneStart); i<=ZONE_END_COL(_zoneEnd); i++)
{
uint8_t col = DATA_BAR(_MX->getColumn(i));
col |= (i&1 ? 0xaa : 0x55); // alternate checkerboard pattern
_MX->setColumn(i, DATA_BAR(col));
}
_fsmState = PUT_CHAR;
break;
case PUT_CHAR:
PRINT_STATE("IO DISS");
zoneClear();
if (bIn) commonPrint();
_fsmState = (bIn ? PAUSE : END);
break;
default:
PRINT_STATE("IO DISS");
_fsmState = (bIn ? PAUSE : END);
}
}

View File

@@ -0,0 +1,121 @@
/*
MD_Parola - Library for modular scrolling text and Effects
See header file for comments
Copyright (C) 2016 Marco Colli. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <MD_Parola.h>
#include <MD_Parola_lib.h>
/**
* \file
* \brief Implements FADE effect
*/
void MD_PZone::effectFade(bool bIn)
// Fade the display in and out.
// If the overall intensity is changed while the animation is running, the
// intensity at the start of the animation will be restored at the end, overriding
// any user code changes.
{
if (bIn) // incoming
{
switch (_fsmState)
{
case INITIALISE:
PRINT_STATE("I FADE");
_nextPos = 0;
_endPos = getIntensity();
zoneClear();
_fsmState = GET_FIRST_CHAR;
break;
case GET_FIRST_CHAR:
FSMPRINT(" I:", _nextPos);
FSMPRINT("/", _endPos);
setIntensity(_nextPos++);
commonPrint();
_fsmState = PUT_CHAR;
break;
case GET_NEXT_CHAR:
case PUT_CHAR:
case PAUSE:
PRINT_STATE("I FADE");
FSMPRINT(" I:", _nextPos);
FSMPRINT("/", _endPos);
// check if we have finished
if (_nextPos > _endPos)
_fsmState = PAUSE;
else
setIntensity(_nextPos++);
break;
default:
PRINT_STATE("I FADE");
_fsmState = PAUSE;
}
}
else // exiting
{
switch (_fsmState)
{
case PAUSE:
case INITIALISE:
PRINT_STATE("O FADE");
_nextPos = _endPos = getIntensity();
FSMPRINT(" I:", _nextPos);
FSMPRINT("/", _endPos);
setIntensity(_nextPos);
commonPrint();
_fsmState = PUT_CHAR;
break;
case GET_FIRST_CHAR:
case GET_NEXT_CHAR:
case PUT_CHAR:
PRINT_STATE("O FADE");
FSMPRINT(" I:", _nextPos);
FSMPRINT("/", _endPos);
// check if we have finished
if (_nextPos < 0)
{
setIntensity(_endPos); // set to original conditions
zoneClear(); // display nothing - we are currently at 0
_fsmState = END;
}
else
setIntensity(_nextPos--);
break;
default:
PRINT_STATE("O FADE");
_fsmState = END;
break;
}
}
}

View File

@@ -0,0 +1,125 @@
/*
MD_Parola - Library for modular scrolling text and Effects
See header file for comments
Copyright (C) 2013 Marco Colli. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <MD_Parola.h>
#include <MD_Parola_lib.h>
/**
* \file
* \brief Implements grow effects
*/
void MD_PZone::effectGrow(bool bUp, bool bIn)
// Scan the message over with a new one
// Print up the whole message and then remove the parts we
// don't need in order to do the animation.
{
if (bIn) // incoming
{
switch (_fsmState)
{
case INITIALISE:
PRINT_STATE("I GROW");
setInitialEffectConditions();
_nextPos = (bUp ? 0xff : 1); // this is the bit mask
_fsmState = PUT_CHAR;
// fall through to next state
case GET_FIRST_CHAR:
case GET_NEXT_CHAR:
case PUT_CHAR:
case PAUSE:
PRINT_STATE("I GROW");
commonPrint();
// check if we have finished
if (_nextPos == (bUp ? 0 : 0xff)) // all bits covered
{
_fsmState = PAUSE;
break;
}
// blank out the part of the display we don't need
FSMPRINT("Keep bits ", _nextPos);
for (int16_t i = _startPos; i != _endPos+_posOffset; i += _posOffset)
{
uint8_t c = DATA_BAR(_MX->getColumn(i)) & (bUp ? ~_nextPos : _nextPos);
_MX->setColumn(i, DATA_BAR(c));
}
// for the next time around
if (bUp)
_nextPos >>= 1;
else
_nextPos = (_nextPos << 1) | 1;
break;
default:
PRINT_STATE("I GROW");
_fsmState = PAUSE;
}
}
else // exiting
{
switch (_fsmState)
{
case PAUSE:
case INITIALISE:
PRINT_STATE("O GROW");
setInitialEffectConditions();
_nextPos = (bUp ? 1 : 0xff); // this is the bit mask
_fsmState = PUT_CHAR;
// fall through to next state
case GET_FIRST_CHAR:
case GET_NEXT_CHAR:
case PUT_CHAR:
PRINT_STATE("O GROW");
commonPrint();
// blank out the part of the display we don't need
FSMPRINT(" Keep bits ", _nextPos);
for (int16_t i=_startPos; i != _endPos+_posOffset; i += _posOffset)
{
uint8_t c = DATA_BAR(_MX->getColumn(i)) & (bUp ? ~_nextPos : _nextPos);
_MX->setColumn(i, DATA_BAR(c));
}
// check if we have finished
if (_nextPos == (bUp ? 0xff : 0x0)) // all bits covered
_fsmState = END;
// for the next time around
if (bUp)
_nextPos = (_nextPos << 1) | 1;
else
_nextPos >>= 1;
break;
default:
PRINT_STATE("O GROW");
_fsmState = END;
break;
}
}
}

View File

@@ -0,0 +1,151 @@
/*
MD_Parola - Library for modular scrolling text and Effects
See header file for comments
Copyright (C) 2013 Marco Colli. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <MD_Parola.h>
#include <MD_Parola_lib.h>
/**
* \file
* \brief Implements horizontal scrolling effect
*/
#define START_POSITION (bLeft) ? ZONE_START_COL(_zoneStart) : ZONE_END_COL(_zoneEnd) ///< Start position depends on the scrolling direction
void MD_PZone::effectHScroll(bool bLeft, bool bIn)
{
if (bIn)
{
switch(_fsmState)
{
case INITIALISE:
case GET_FIRST_CHAR: // Load the first character from the font table
PRINT_STATE("I HSCROLL");
if ((_charCols = getFirstChar()) == 0)
{
_fsmState = END;
break;
}
_countCols = 0;
_fsmState = PUT_CHAR;
break;
case GET_NEXT_CHAR: // Load the next character from the font table
PRINT_STATE("I HSCROLL");
// Have we reached the end of the characters string?
_charCols = getNextChar();
FSMPRINT("\ncharCols ", _charCols);
if (_charCols == 0)
{
_fsmState = PAUSE;
break;
}
_countCols = 0;
_fsmState = PUT_CHAR;
FSMPRINTS(", fall thru");
// !! fall through to next state to start displaying
case PUT_CHAR: // display the next part of the character
PRINT_STATE("I HSCROLL");
_MX->transform(_zoneStart, _zoneEnd, bLeft ? MD_MAX72XX::TSL : MD_MAX72XX::TSR);
_MX->setColumn(START_POSITION, DATA_BAR(_cBuf[_countCols++]));
FSMPRINTS(", scroll");
// end of this buffer - we may need to get another one
if (_countCols == _charCols)
{
if (!_endOfText)
_fsmState = GET_NEXT_CHAR;
else
{
// work out the number of filler columns
_countCols = (bLeft ? _limitLeft-_textLen-ZONE_START_COL(_zoneStart) + 1 : ZONE_END_COL(_zoneEnd)-_limitLeft);
FSMPRINT(", filler count ", _countCols);
_fsmState = (_countCols <= 0) ? PAUSE : PUT_FILLER;
}
}
break;
case PUT_FILLER: // keep sending out blank columns until aligned
PRINT_STATE("I HSCROLL");
_MX->transform(_zoneStart, _zoneEnd, bLeft ? MD_MAX72XX::TSL : MD_MAX72XX::TSR);
_MX->setColumn(START_POSITION, EMPTY_BAR);
FSMPRINTS(", fill");
if (--_countCols == 0)
_fsmState = PAUSE;
break;
default:
_fsmState = PAUSE;
break;
}
}
else // exiting
{
switch(_fsmState)
{
case PAUSE:
PRINT_STATE("O HSCROLL");
_fsmState = PUT_FILLER;
FSMPRINTS(" falling thru");
// fall through
case PUT_FILLER:
PRINT_STATE("O HSCROLL");
_MX->transform(_zoneStart, _zoneEnd, bLeft ? MD_MAX72XX::TSL : MD_MAX72XX::TSR);
_MX->setColumn(START_POSITION, EMPTY_BAR);
// check if enough scrolled off to say that new message should start
// how we count depends on the direction for scrolling
{
uint16_t spaceCount = 0;
uint16_t maxCount = (_zoneEnd - _zoneStart + 1) * COL_SIZE;
if ((_scrollDistance != 0) && (maxCount > _scrollDistance)) maxCount = _scrollDistance;
if (bLeft)
{
for (int16_t i = ZONE_START_COL(_zoneStart);
(i <= ZONE_END_COL(_zoneEnd)) && (_MX->getColumn(i) == EMPTY_BAR);
i++, spaceCount++);
}
else
{
for (int16_t i = ZONE_END_COL(_zoneEnd);
(i >= ZONE_START_COL(_zoneStart)) && (_MX->getColumn(i) == EMPTY_BAR);
i--, spaceCount++);
}
if (maxCount <= spaceCount) _fsmState = END; // enough of a space between messages, end this FSM
}
break;
default:
_fsmState = END;
break;
}
}
}

View File

@@ -0,0 +1,113 @@
/*
MD_Parola - Library for modular scrolling text and Effects
See header file for comments
Copyright (C) 2013 Marco Colli. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <MD_Parola.h>
#include <MD_Parola_lib.h>
/**
* \file
* \brief Implements mesh effect
*/
void MD_PZone::effectMesh(bool bIn)
// Text enters with alternating up/down columns
{
bool bUp = true;
if (bIn) // incoming
{
switch (_fsmState)
{
case INITIALISE:
PRINT_STATE("I MESH");
_nextPos = 0;
_fsmState = PUT_CHAR;
// fall through to next state
case GET_FIRST_CHAR:
case GET_NEXT_CHAR:
case PUT_CHAR:
case PAUSE:
PRINT_STATE("I MESH");
zoneClear();
commonPrint();
for (uint8_t c = ZONE_START_COL(_zoneStart); c <= ZONE_END_COL(_zoneEnd); c++)
{
// scroll the whole display so that the message appears to be animated
// Note: Directions are reversed because we start with the message in the
// middle position thru commonPrint() and to see it animated move DOWN we
// need to scroll it UP, and vice versa.
uint8_t col = _MX->getColumn(c);
col = (bUp ? col >> (COL_SIZE-1-_nextPos) : col << (COL_SIZE-1-_nextPos));
_MX->setColumn(c, col);
bUp = !bUp;
}
// check if we have finished
_nextPos++;
if (_nextPos == COL_SIZE) _fsmState = PAUSE;
break;
default:
PRINT_STATE("I MESH");
_fsmState = PAUSE;
}
}
else // exiting
{
switch (_fsmState)
{
case PAUSE:
case INITIALISE:
PRINT_STATE("O MESH");
_nextPos = 1;
_fsmState = PUT_CHAR;
// fall through to next state
case GET_FIRST_CHAR:
case GET_NEXT_CHAR:
case PUT_CHAR:
PRINT_STATE("O MESH");
for (uint8_t c = ZONE_START_COL(_zoneStart); c <= ZONE_END_COL(_zoneEnd); c++)
{
uint8_t col = _MX->getColumn(c);
col = (bUp ? col << _nextPos : col >> _nextPos);
_MX->setColumn(c, col);
bUp = !bUp;
}
// check if we have finished
_nextPos++;
if (_nextPos == COL_SIZE) _fsmState = END;
break;
default:
PRINT_STATE("O MESH");
_fsmState = END;
break;
}
}
}

View File

@@ -0,0 +1,127 @@
/*
MD_Parola - Library for modular scrolling text and Effects
See header file for comments
Copyright (C) 2013 Marco Colli. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <MD_Parola.h>
#include <MD_Parola_lib.h>
/**
* \file
* \brief Implements opening effect
*/
void MD_PZone::effectOpen(bool bLightBar, bool bIn)
// Open the current message in/out
{
if (bIn)
{
switch (_fsmState)
{
case INITIALISE:
case GET_FIRST_CHAR:
case GET_NEXT_CHAR:
PRINT_STATE("I OPEN");
FSMPRINT(" - limits R:", _limitRight);
FSMPRINT(" L:", _limitLeft);
_nextPos = 1 + (_limitLeft - _limitRight)/2;
FSMPRINT(" O:", _nextPos);
if (bLightBar)
{
_MX->setColumn(_limitLeft - _nextPos, LIGHT_BAR);
_MX->setColumn(_limitRight + _nextPos, LIGHT_BAR);
}
_fsmState = PUT_CHAR;
break;
case PUT_CHAR:
PRINT_STATE("I OPEN");
FSMPRINT(" - offset ", _nextPos);
if (_nextPos < 0)
{
_fsmState = PAUSE;
}
else
{
commonPrint();
for (int16_t i=0; i<_nextPos; i++)
{
_MX->setColumn(_limitRight + i, EMPTY_BAR);
_MX->setColumn(_limitLeft - i, EMPTY_BAR);
}
_nextPos--;
if (bLightBar && (_nextPos >= 0))
{
_MX->setColumn(_limitRight + _nextPos, LIGHT_BAR);
_MX->setColumn(_limitLeft - _nextPos, LIGHT_BAR);
}
}
break;
default:
PRINT_STATE("I OPEN");
_fsmState = PAUSE;
}
}
else // exiting
{
switch (_fsmState)
{
case PAUSE:
case GET_FIRST_CHAR:
case GET_NEXT_CHAR:
PRINT_STATE("O OPEN");
zoneClear();
commonPrint();
_nextPos = 0;
if (bLightBar)
{
_MX->setColumn(_limitLeft, LIGHT_BAR);
_MX->setColumn(_limitRight,LIGHT_BAR);
}
_fsmState = PUT_CHAR;
// fall through
case PUT_CHAR:
PRINT_STATE("O OPEN");
FSMPRINT(" - offset ", _nextPos);
if (_nextPos > (_limitLeft - _limitRight)/2)
{
_fsmState = END;
}
else
{
_MX->setColumn(_limitLeft - _nextPos, EMPTY_BAR);
_MX->setColumn(_limitRight + _nextPos, EMPTY_BAR);
_nextPos++;
if (bLightBar && (_nextPos <= (_limitLeft-_limitRight)/2))
{
_MX->setColumn(_limitLeft - _nextPos, LIGHT_BAR);
_MX->setColumn(_limitRight + _nextPos,LIGHT_BAR);
}
}
break;
default:
PRINT_STATE("O OPEN");
_fsmState = END;
}
}
}

View File

@@ -0,0 +1,66 @@
/*
MD_Parola - Library for modular scrolling text and Effects
See header file for comments
Copyright (C) 2013 Marco Colli. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <MD_Parola.h>
#include <MD_Parola_lib.h>
/**
* \file
* \brief Implements static print effect
*/
void MD_PZone::commonPrint(void)
{
int16_t nextPos;
PRINTS("\ncommonPrint");
zoneClear();
nextPos = _limitLeft;
_charCols = getFirstChar();
_countCols = 0;
while (nextPos >= _limitRight)
{
if (_countCols == _charCols)
{
_charCols = getNextChar();
_countCols = 0;
}
// now put something on the display
_MX->setColumn(nextPos--, DATA_BAR(_cBuf[_countCols++]));
}
}
void MD_PZone::effectPrint(bool bIn)
// Just print the message in the justification selected
{
if (bIn) // incoming
{
commonPrint();
_fsmState = PAUSE;
}
else //exiting
{
zoneClear();
_fsmState = END;
}
}

View File

@@ -0,0 +1,102 @@
/*
MD_Parola - Library for modular scrolling text and Effects
See header file for comments
Copyright (C) 2013 Marco Colli. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <MD_Parola.h>
#include <MD_Parola_lib.h>
/**
* \file
* \brief Implements random effect
*/
#define RAND_CYCLE 11 // random effect repeats every RANDOM_CYCLE columns
void MD_PZone::effectRandom(bool bIn)
// Text enters as random dots
{
static uint8_t pix[RAND_CYCLE]; // pixel data (one byte per column) to mask the display
uint8_t c, r; // the row and column coordinates being considered
switch (_fsmState)
{
case INITIALISE: // Entry bIn == true
case PAUSE: // Exit bIn == false
PRINT_STATE("IO RAND");
for (uint8_t i = 0; i < RAND_CYCLE; i++)
pix[i] = 0;
_fsmState = PUT_CHAR;
// fall through to next state
case GET_FIRST_CHAR:
case GET_NEXT_CHAR:
case PUT_CHAR:
PRINT_STATE("IO RAND");
if (bIn) FSMPRINTS(" in"); else FSMPRINTS(" out");
// Work out and set the next random pixel in the column mask.
// Use a loop counter to make sure we just don't loop forever.
_nextPos = 0;
do
{
c = random(RAND_CYCLE);
r = random(ROW_SIZE);
_nextPos++;
} while (pix[c] & (1 << r) && _nextPos < 5000);
// FSMPRINT("\n [r,c]=", r); FSMPRINT(",", c); FSMPRINT(" counter ", _nextPos);
pix[c] |= (1 << r); // set the r,c location in the mask
// set up a new display
commonPrint();
// now mask each column by the pixel mask - this repeats every RAND_CYCLE columns, but the
// characters don't occupy every pixel so the effect looks 'random' across the whole display.
_nextPos = 0;
for (uint8_t c = ZONE_START_COL(_zoneStart); c <= ZONE_END_COL(_zoneEnd); c++)
{
uint8_t col = _MX->getColumn(c);
col &= (bIn ? pix[_nextPos] : ~pix[_nextPos]); // set or reset the bit (depends on bIn)
_MX->setColumn(c, col);
_nextPos++;
if (_nextPos == RAND_CYCLE)
_nextPos = 0;
}
// check if we have finished. This is when all the columns have pixels all on (0xff)
{
bool bEnd = true;
for (uint8_t i = 0; bEnd && i < COL_SIZE; i++)
bEnd = (pix[i] == 0xff);
if (bEnd) _fsmState = (bIn ? PAUSE : END);
}
break;
default:
PRINT_STATE("IO RAND");
_fsmState = (bIn ? PAUSE : END);
}
}

View File

@@ -0,0 +1,209 @@
/*
MD_Parola - Library for modular scrolling text and Effects
See header file for comments
Copyright (C) 2013 Marco Colli. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <MD_Parola.h>
#include <MD_Parola_lib.h>
/**
* \file
* \brief Implements scan effect
*/
void MD_PZone::effectHScan(bool bIn, bool bBlank)
// Scan the message end to end.
// if bBlank is true, a blank column scans the text. If false, a non-blank scans the text.
// Print up the whole message and then remove the parts we
// don't need in order to do the animation.
{
if (bIn) // incoming
{
switch (_fsmState)
{
case INITIALISE:
PRINT_STATE("I SCANH");
setInitialEffectConditions();
_fsmState = PUT_CHAR;
// fall through to next state
case GET_FIRST_CHAR:
case GET_NEXT_CHAR:
case PUT_CHAR:
case PAUSE:
PRINT_STATE("I SCANH");
commonPrint();
// check if we have finished
if (_nextPos == _endPos)
{
_fsmState = PAUSE;
break;
}
// blank out the part of the display we don't need
FSMPRINT("Scan col ", _nextPos);
for (int16_t i=_startPos; i != _endPos+_posOffset; i += _posOffset)
{
if ((!bBlank && (i != _nextPos)) || (bBlank && (i == _nextPos)))
_MX->setColumn(i, EMPTY_BAR);
}
_nextPos += _posOffset; // for the next time around
break;
default:
PRINT_STATE("I SCANH");
_fsmState = PAUSE;
}
}
else // exiting
{
switch (_fsmState)
{
case PAUSE:
case INITIALISE:
PRINT_STATE("O SCANH");
setInitialEffectConditions();
_fsmState = PUT_CHAR;
// fall through to next state
case GET_FIRST_CHAR:
case GET_NEXT_CHAR:
case PUT_CHAR:
PRINT_STATE("O SCANH");
commonPrint();
// blank out the part of the display we don't need
FSMPRINT(" Scan col ", _nextPos);
for (int16_t i=_startPos; i != _endPos+_posOffset; i += _posOffset)
{
if ((!bBlank && (i != _nextPos)) || (bBlank && (i == _nextPos)))
_MX->setColumn(i, EMPTY_BAR);
}
// check if we have finished
if (_nextPos < _endPos) _fsmState = END;
_nextPos += _posOffset; // for the next time around
break;
default:
PRINT_STATE("O SCANH");
_fsmState = END;
break;
}
}
}
void MD_PZone::effectVScan(bool bIn, bool bBlank)
// Scan the message over with a new one
// if bBlank is true, a blank column scans the text. If false, a non-blank scans the text.
// Print up the whole message and then remove the parts we
// don't need in order to do the animation.
{
uint8_t maskCol = 0;
if (bIn) // incoming
{
switch (_fsmState)
{
case INITIALISE:
PRINT_STATE("I SCANV");
setInitialEffectConditions();
_nextPos = 0; // this is the bit number
_fsmState = PUT_CHAR;
// fall through to next state
case GET_FIRST_CHAR:
case GET_NEXT_CHAR:
case PUT_CHAR:
case PAUSE:
PRINT_STATE("I SCANV");
commonPrint();
// check if we have finished
if (_nextPos == 8) // bits numbered 0 to 7
{
_fsmState = PAUSE;
break;
}
// blank out the part of the display we don't need
FSMPRINT("Keep bit ", _nextPos);
maskCol = (1 << _nextPos);
for (int16_t i=_startPos; i != _endPos+_posOffset; i += _posOffset)
{
uint8_t c = DATA_BAR(_MX->getColumn(i) & (bBlank ? ~maskCol : maskCol));
_MX->setColumn(i, DATA_BAR(c));
}
_nextPos++; // for the next time around
break;
default:
PRINT_STATE("I SCANV");
_fsmState = PAUSE;
}
}
else // exiting
{
switch (_fsmState)
{
case PAUSE:
case INITIALISE:
PRINT_STATE("O SCANV");
setInitialEffectConditions();
_nextPos = 7; // the bit number
_fsmState = PUT_CHAR;
// fall through to next state
case GET_FIRST_CHAR:
case GET_NEXT_CHAR:
case PUT_CHAR:
PRINT_STATE("O SCANV");
commonPrint();
// blank out the part of the display we don't need
FSMPRINT(" Keep bit ", _nextPos);
if (_nextPos >= 0)
maskCol = 1 << _nextPos;
for (int16_t i=_startPos; i != _endPos+_posOffset; i += _posOffset)
{
uint8_t c = DATA_BAR(_MX->getColumn(i) & (bBlank ? ~maskCol : maskCol));
_MX->setColumn(i, DATA_BAR(c));
}
// check if we have finished
if (_nextPos < 0)
_fsmState = END;
_nextPos--; // for the next time around
break;
default:
PRINT_STATE("O SCANV");
_fsmState = END;
break;
}
}
}

View File

@@ -0,0 +1,147 @@
/*
MD_Parola - Library for modular scrolling text and Effects
See header file for comments
Copyright (C) 2013 Marco Colli. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <MD_Parola.h>
#include <MD_Parola_lib.h>
/**
* \file
* \brief Implements slice effect
*/
void MD_PZone::effectSlice(bool bIn)
{
if (bIn)
{
switch(_fsmState)
{
case INITIALISE:
case GET_FIRST_CHAR:
PRINT_STATE("I SLICE");
if ((_charCols = getFirstChar()) == 0)
{
_fsmState = END;
break;
}
zoneClear();
_countCols = 0;
_nextPos = ZONE_START_COL(_zoneStart);
_endPos = _limitLeft;
FSMPRINT(" - Start ", _nextPos);
FSMPRINT(", End ", _endPos);
_fsmState = PUT_CHAR;
break;
case GET_NEXT_CHAR: // Load the next character from the font table
PRINT_STATE("I SLICE");
// have we reached the end of the characters string?
if ((_charCols = getNextChar()) == 0)
{
_fsmState = PAUSE;
break;
}
_countCols = 0;
_fsmState = PUT_CHAR;
// !! fall through to next state to start displaying
case PUT_CHAR: // display the next part of the character
PRINT_STATE("I SLICE");
FSMPRINT(" - Next ", _endPos);
FSMPRINT(", anim ", _nextPos);
// if the text is too long for the zone, stop when we are at the last column of the zone
if (_nextPos == _endPos)
{
_MX->setColumn(_nextPos, DATA_BAR(_cBuf[_countCols]));
_fsmState = PAUSE;
break;
}
if (_cBuf[_countCols] == 0) // empty column ?
{
_nextPos = _endPos; // pretend we just animated it!
}
else // something to animate
{
// clear the column and animate the next one
if (_nextPos != _endPos) _MX->setColumn(_nextPos, EMPTY_BAR);
_nextPos++;
_MX->setColumn(_nextPos, DATA_BAR(_cBuf[_countCols]));
}
// set up for the next time
if (_nextPos == _endPos)
{
_nextPos = ZONE_START_COL(_zoneStart);
_countCols++;
_endPos--;
}
if (_countCols == _charCols) _fsmState = GET_NEXT_CHAR;
break;
default:
_fsmState = PAUSE;
}
}
else // exiting
{
switch(_fsmState)
{
case PAUSE:
PRINT_STATE("O SLICE");
_nextPos = _endPos = _limitLeft;
_fsmState = PUT_CHAR;
// fall through
case GET_FIRST_CHAR:
case GET_NEXT_CHAR:
case PUT_CHAR:
PRINT_STATE("O SLICE");
FSMPRINT(" - Next ", _endPos);
FSMPRINT(", anim ", _nextPos);
while(_MX->getColumn(_nextPos) == EMPTY_BAR && _endPos >= _limitRight)
_nextPos = _endPos--; // pretend we just animated it!
if (_endPos+1 < _limitRight)
_fsmState = END; //reached the end
else
{
// Move the column over to the left and blank out previous position
if (_nextPos < ZONE_END_COL(_zoneEnd))
_MX->setColumn(_nextPos+1, _MX->getColumn(_nextPos));
_MX->setColumn(_nextPos, EMPTY_BAR);
_nextPos++;
// set up for the next time
if (_nextPos == ZONE_END_COL(_zoneEnd)+1)
_nextPos = _endPos--;
}
break;
default:
_fsmState = END;
}
}
}

View File

@@ -0,0 +1,157 @@
/*
MD_Parola - Library for modular scrolling text and Effects
See header file for comments
Copyright (C) 2018 Marco Colli. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <MD_Parola.h>
#include <MD_Parola_lib.h>
/**
* \file
* \brief Implements various sprite effects
*/
#if ENA_SPRITE
void MD_PZone::effectSprite(bool bIn, uint8_t id)
// Animated Pacman sprite leads or eats up the message.
// Print up the whole message and then remove the parts we
// don't need in order to do the animation.
{
if (bIn) // incoming - sprite moves left to right in the zone
{
switch (_fsmState)
{
case INITIALISE:
PRINT_STATE("I SPRITE");
setInitialEffectConditions();
if (_startPos < _endPos)
{
int16_t t = _startPos;
_startPos = _endPos;
_endPos = t;
}
if (_spriteInData == nullptr)
{
_fsmState = END;
break;
}
_posOffset = 0; // current animation frame for the sprite
_nextPos = ZONE_END_COL(_zoneEnd) + 1;
_fsmState = PUT_CHAR;
// fall through to next state
case GET_FIRST_CHAR:
case GET_NEXT_CHAR:
case PUT_CHAR:
case PAUSE:
PRINT_STATE("I SPRITE");
commonPrint();
// move reference column and draw new graphic
_nextPos--;
for (uint8_t i = 0; i < _spriteInWidth; i++)
{
if ((_nextPos + i) <= ZONE_END_COL(_zoneEnd) && (_nextPos + i) >= ZONE_START_COL(_zoneStart))
_MX->setColumn(_nextPos + i, DATA_BAR(pgm_read_byte(_spriteInData + (_posOffset * _spriteInWidth) + i)));
}
// blank out the part of the display we don't need
// this is the part to the right of the sprite
for (int16_t i = _nextPos - 1; i >= _endPos; i--)
_MX->setColumn(i, EMPTY_BAR);
// advance the animation frame
_posOffset++;
if (_posOffset >= _spriteInFrames)
_posOffset = 0;
// check if we have finished
if (_nextPos == ZONE_START_COL(_zoneStart) - _spriteInWidth - 1)
_fsmState = PAUSE;
break;
default:
PRINT_STATE("I SPRITE");
_fsmState = PAUSE;
}
}
else // exiting - sprite moves left to right in the zone
{
switch (_fsmState)
{
case PAUSE:
case INITIALISE:
PRINT_STATE("O SPRITE");
setInitialEffectConditions();
if (_startPos < _endPos)
{
int16_t t = _startPos;
_startPos = _endPos;
_endPos = t;
}
if (_spriteOutData == nullptr)
{
_fsmState = END;
break;
}
_nextPos = ZONE_START_COL(_zoneStart) - 1;
_posOffset = 0;
_fsmState = PUT_CHAR;
// fall through to next state
case GET_FIRST_CHAR:
case GET_NEXT_CHAR:
case PUT_CHAR:
PRINT_STATE("O SPRITE");
commonPrint();
// move reference column and draw new graphic
_nextPos++;
for (uint8_t i = 0; i < _spriteOutWidth; i++)
{
if ((_nextPos - i) <= ZONE_END_COL(_zoneEnd) && (_nextPos - i) >= ZONE_START_COL(_zoneStart))
_MX->setColumn(_nextPos - i, DATA_BAR(pgm_read_byte(_spriteOutData + (_posOffset * _spriteOutWidth) + i)));
}
// blank out the part of the display we don't need
// this is the part to the right of the sprite
for (int16_t i = _nextPos - _spriteOutWidth; i >= _endPos; i--)
_MX->setColumn(i, EMPTY_BAR);
// advance the animation frame
_posOffset++;
if (_posOffset >= _spriteOutFrames)
_posOffset = 0;
// check if we have finished
if (_nextPos == ZONE_END_COL(_zoneEnd) + _spriteOutWidth + 1)
_fsmState = END;
break;
default:
PRINT_STATE("O SPRITE");
_fsmState = END;
break;
}
}
}
#endif

View File

@@ -0,0 +1,101 @@
/*
MD_Parola - Library for modular scrolling text and Effects
See header file for comments
Copyright (C) 2013 Marco Colli. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <MD_Parola.h>
#include <MD_Parola_lib.h>
/**
* \file
* \brief Implements vertical scroll effect
*/
void MD_PZone::effectVScroll(bool bUp, bool bIn)
// Scroll the display horizontally up of down, depending on the selected effect
{
if (bIn) // incoming
{
switch (_fsmState)
{
case INITIALISE:
PRINT_STATE("I VSCROLL");
_nextPos = 0;
_MX->control(_zoneStart, _zoneEnd, MD_MAX72XX::WRAPAROUND, MD_MAX72XX::OFF);
_fsmState = PUT_CHAR;
// fall through to next state
case GET_FIRST_CHAR:
case GET_NEXT_CHAR:
case PUT_CHAR:
case PAUSE:
PRINT_STATE("I VSCROLL");
zoneClear();
commonPrint();
for (uint8_t i = _nextPos; i < 7; i++)
// scroll the whole display so that the message appears to be animated
// Note: Directions are reversed because we start with the message in the
// middle position thru commonPrint() and to see it animated move DOWN we
// need to scroll it UP, and vice versa.
_MX->transform(_zoneStart, _zoneEnd, bUp ? MD_MAX72XX::TSD : MD_MAX72XX::TSU);
// check if we have finished
if (_nextPos == 7) _fsmState = PAUSE;
_nextPos++;
break;
default:
PRINT_STATE("I VSCROLL");
_fsmState = PAUSE;
}
}
else // exiting
{
switch (_fsmState)
{
case PAUSE:
case INITIALISE:
PRINT_STATE("O VSCROLL");
_nextPos = 0;
_fsmState = PUT_CHAR;
// fall through to next state
case GET_FIRST_CHAR:
case GET_NEXT_CHAR:
case PUT_CHAR:
PRINT_STATE("O VSCROLL");
_MX->transform(_zoneStart, _zoneEnd, bUp ? MD_MAX72XX::TSU : MD_MAX72XX::TSD);
// check if we have finished
if (_nextPos == 7) _fsmState = END;
_nextPos++;
break;
default:
PRINT_STATE("O VSCROLL");
_fsmState = END;
break;
}
}
}

View File

@@ -0,0 +1,113 @@
/*
MD_Parola - Library for modular scrolling text and Effects
See header file for comments
Copyright (C) 2013 Marco Colli. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <MD_Parola.h>
#include <MD_Parola_lib.h>
/**
* \file
* \brief Implements wipe effect
*/
void MD_PZone::effectWipe(bool bLightBar, bool bIn)
// Wipe the message over with a new one
// Print up the whole message and then remove the parts we
// don't need in order to do the animation.
{
if (bIn) // incoming
{
switch (_fsmState)
{
case INITIALISE:
PRINT_STATE("I WIPE");
setInitialEffectConditions();
_fsmState = PUT_CHAR;
// fall through to next state
case GET_FIRST_CHAR:
case GET_NEXT_CHAR:
case PUT_CHAR:
case PAUSE:
PRINT_STATE("I WIPE");
if (_fsmState == PAUSE)
_fsmState = PUT_CHAR;
commonPrint();
// blank out the part of the display we don't need
FSMPRINT(" - Clear ", _nextPos);
FSMPRINT(" to ", _endPos);
FSMPRINT(" step ", _posOffset);
for (int16_t i=_nextPos; i != _endPos+_posOffset; i += _posOffset)
_MX->setColumn(i, EMPTY_BAR);
if (bLightBar && (_nextPos != _endPos+_posOffset)) _MX->setColumn(_nextPos, LIGHT_BAR);
// check if we have finished
if (_nextPos == _endPos+_posOffset) _fsmState = PAUSE;
_nextPos += _posOffset; // for the next time around
break;
default:
PRINT_STATE("I WIPE");
_fsmState = PAUSE;
}
}
else // exiting
{
switch (_fsmState)
{
case PAUSE:
case INITIALISE:
PRINT_STATE("O WIPE");
setInitialEffectConditions();
_fsmState = PUT_CHAR;
// fall through to next state
case GET_FIRST_CHAR:
case GET_NEXT_CHAR:
case PUT_CHAR:
PRINT_STATE("O WIPE");
commonPrint();
// blank out the part of the display we don't need
FSMPRINT(" - Clear ", _nextPos);
FSMPRINT(" to ", _endPos);
FSMPRINT(" step ", _posOffset);
for (int16_t i = _startPos; i != _nextPos + _posOffset; i += _posOffset)
_MX->setColumn(i, EMPTY_BAR);
if (bLightBar && (_nextPos != _endPos+_posOffset)) _MX->setColumn(_nextPos, LIGHT_BAR);
// check if we have finished
if (_nextPos == _endPos + _posOffset) _fsmState = END;
_nextPos += _posOffset; // for the next time around
break;
default:
PRINT_STATE("O WIPE");
_fsmState = END;
break;
}
}
}

View File

@@ -0,0 +1,50 @@
#ifndef MD_PAROLALIB_H
#define MD_PAROLALIB_H
/**
* \file
* \brief Contains internal library definitions
*/
#define DEBUG_PAROLA 0 ///< Set to 1 to enable General debug output
#define DEBUG_PAROLA_FSM 0 ///< Set to 1 to enable Finite State Machine debug output
#define TIME_PROFILING 0 ///< Set to 1 to enable Time Profile debug output
#if DEBUG_PAROLA
#define PRINT(s, v) { Serial.print(F(s)); Serial.print(v); } ///< (GENERAL) Print a string followed by a value (decimal)
#define PRINTX(s, v) { Serial.print(F(s)); Serial.print(v, HEX); } ///< (GENERAL) Print a string followed by a value (hex)
#define PRINTS(s) Serial.print(F(s)) ///< (GENERAL) Print a string
#else
#define PRINT(s, v) ///< (GENERAL) Print a string followed by a value (decimal)
#define PRINTX(s, v) ///< (GENERAL) Print a string followed by a value (hex)
#define PRINTS(s) ///< (GENERAL) Print a string
#endif
#if DEBUG_PAROLA_FSM
#define FSMPRINT(s, v) { Serial.print(F(s)); Serial.print(v); } ///< (FSM) Print a string followed by a value (decimal)
#define FSMPRINTX(s, v) { Serial.print(F(s)); Serial.print(v, HEX); } ///< (FSM) Print a string followed by a value (hex)
#define FSMPRINTS(s) Serial.print(F(s)) ///< (FSM) Print a string
#define PRINT_STATE(f) { Serial.print(F("\n")); Serial.print(F(f)); Serial.print(F(" fsm ")); Serial.print(state2string(_fsmState)); } ///< (FSM) Print the current FSM state information
#else
#define FSMPRINT(s, v) ///< (FSM) Print a string followed by a value (decimal)
#define FSMPRINTX(s, v) ///< (FSM) Print a string followed by a value (hex)
#define FSMPRINTS(s) ///< (FSM) Print a string
#define PRINT_STATE(f) ///< (FSM) Print the current FSM state information
#endif
// General macros and defines
#define LIGHT_BAR (_inverted ? 0 : 0xFF) ///< Turn display column to all LEDs on
#define EMPTY_BAR (_inverted ? 0xFF : 0) ///< Turn display column to all LEDs off
#define DATA_BAR(d) (_inverted ? ~d : d) ///< Turn display column to specified data
// Zone effects masks
#define ZE_SET(b, mask) ((b & ~mask) | mask) ///< clear the bit then put it back in
#define ZE_RESET(b, mask) (b & ~mask) ///< clear the bit
#define ZE_TEST(b, mask) ((b & mask) != 0) ///< mask off the bit
#define ZE_FLIP_UD_MASK 0x01 ///< mask bit 0
#define ZE_FLIP_LR_MASK 0x02 ///< mask bit 1
#define SFX(s) ((_moveIn && _effectIn == (s)) || (!_moveIn && _effectOut == (s))) ///< Effect is selected if it is the effect for the current motion
#endif