Made MD* libraries (Parola, MAX72XX) project specific, to be able to use the newest software version from github.

This commit is contained in:
2019-02-01 15:21:58 +01:00
parent fe9f25c856
commit c7547144d2
761 changed files with 108577 additions and 2 deletions

View File

@@ -0,0 +1,53 @@
// Demonstrates reversed text (as if on front of an ambulance)
//
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#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(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(HARDWARE_TYPE, 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,150 @@
// Program to show full catalog of the MD_Parola animations
//
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 4
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// Hardware SPI connection
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
// Global data
struct sCatalog
{
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 catalog[] =
{
{ PA_PRINT, "PRINT", 1, 1 },
{ PA_SCROLL_UP, "SC_U", 5, 1 },
{ PA_SCROLL_DOWN, "SCR_D", 5, 1 },
{ PA_SCROLL_LEFT, "SCR_L", 5, 1 },
{ PA_SCROLL_RIGHT, "SCR_R", 5, 1 },
#if ENA_SPRITE
{ PA_SPRITE, "SPRIT", 5, 1 },
#endif
#if ENA_MISC
{ PA_SLICE, "SLICE", 1, 1 },
{ PA_MESH, "MESH", 20, 1 },
{ PA_FADE, "FADE", 20, 1 },
{ PA_DISSOLVE, "DSLVE", 7, 1 },
{ PA_BLINDS, "BLIND", 7, 1 },
{ PA_RANDOM, "RAND", 3, 1 },
#endif
#if ENA_WIPE
{ PA_WIPE, "WIPE", 5, 1 },
{ PA_WIPE_CURSOR, "WPE_C", 4, 1 },
#endif
#if ENA_SCAN
{ PA_SCAN_HORIZ, "SCNH", 4, 1 },
{ PA_SCAN_HORIZX, "SCNHX", 4, 1 },
{ PA_SCAN_VERT, "SCNV", 3, 1 },
{ PA_SCAN_VERTX, "SCNVX", 3, 1 },
#endif
#if ENA_OPNCLS
{ PA_OPENING, "OPEN", 3, 1 },
{ PA_OPENING_CURSOR, "OPN_C", 4, 1 },
{ PA_CLOSING, "CLOSE", 3, 1 },
{ PA_CLOSING_CURSOR, "CLS_C", 4, 1 },
#endif
#if ENA_SCR_DIA
{ PA_SCROLL_UP_LEFT, "SCR_UL", 7, 1 },
{ PA_SCROLL_UP_RIGHT, "SCR_UR", 7, 1 },
{ PA_SCROLL_DOWN_LEFT, "SCR_DL", 7, 1 },
{ PA_SCROLL_DOWN_RIGHT, "SCR_DR", 7, 1 },
#endif
#if ENA_GROW
{ PA_GROW_UP, "GRW_U", 7, 1 },
{ PA_GROW_DOWN, "GRW_D", 7, 1 },
#endif
};
// 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,
};
void setup(void)
{
P.begin();
#if ENA_SPRITE
P.setSpriteData(pacman1, W_PMAN1, F_PMAN1, pacman2, W_PMAN2, F_PMAN2);
#endif
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,617 @@
// 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
//
// * MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#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(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(HARDWARE_TYPE, 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,92 @@
// Program to exercise the MD_Parola library
//
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 8
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// HARDWARE SPI
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(HARDWARE_TYPE, 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,153 @@
// 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
//
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#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(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(HARDWARE_TYPE, 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,158 @@
// 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
// - MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
// 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.
//
// 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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#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(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
#define SPEED_TIME 75
#define PAUSE_TIME 0
#define MAX_MESG 6
// Hardware adaptation parameters for scrolling
bool invertUpperZone = false;
// 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)
{
invertUpperZone = (HARDWARE_TYPE == MD_MAX72XX::GENERIC_HW || HARDWARE_TYPE == MD_MAX72XX::PAROLA_HW);
// 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
if (invertUpperZone)
{
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);
}
#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,35 @@
// Data file for numerci scoreboard fonts
#ifndef FONTDATA_H
#define FONTDATA_H
MD_MAX72XX::fontType_t NumFontLower[] PROGMEM =
{
'F', 1, 48, 57, 8,
10, 0, 127, 255, 192, 192, 192, 192, 255, 127, 0, // 48 - '0'
10, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, // 49 - '1'
10, 0, 127, 255, 193, 193, 193, 193, 193, 128, 0, // 50 - '2'
10, 0, 128, 193, 193, 193, 193, 193, 255, 126, 0, // 51 - '3'
10, 0, 0, 1, 1, 1, 1, 1, 127, 255, 0, // 52 - '4'
10, 0, 128, 193, 193, 193, 193, 193, 255, 126, 0, // 53 - '5'
10, 0, 127, 255, 193, 193, 193, 193, 255, 127, 0, // 54 - '6'
10, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, // 55 - '7'
10, 0, 126, 255, 193, 193, 193, 193, 255, 126, 0, // 56 - '8'
10, 0, 128, 193, 193, 193, 193, 193, 255, 127, 0, // 57 - '9'
};
MD_MAX72XX::fontType_t NumFontUpper[] PROGMEM =
{
'F', 1, 48, 57, 8,
10, 0, 254, 255, 3, 3, 3, 3, 255, 254, 0, // 48 - '0'
10, 0, 0, 0, 0, 0, 0, 0, 254, 255, 0, // 49 - '1'
10, 0, 1, 131, 131, 131, 131, 131, 255, 254, 0, // 50 - '2'
10, 0, 1, 131, 131, 131, 131, 131, 255, 126, 0, // 51 - '3'
10, 0, 255, 254, 128, 128, 128, 128, 254, 255, 0, // 52 - '4'
10, 0, 254, 255, 131, 131, 131, 131, 131, 1, 0, // 53 -'5'
10, 0, 254, 255, 131, 131, 131, 131, 131, 1, 0, // 54 - '6'
10, 0, 1, 3, 3, 3, 3, 3, 255, 254, 0, // 55 - '7'
10, 0, 126, 255, 131, 131, 131, 131, 255, 126, 0, // 56 - '8'
10, 0, 254, 255, 131, 131, 131, 131, 255, 254, 0, // 57 - '9'
};
#endif

View File

@@ -0,0 +1,207 @@
// Demonstrates using double height to create a scoreboard using Parola.
//
// Each score has 2 zones, an upper and a lower zone to display the top and bottom
// sections of the double height score. The numeric font is a fixed font with
// just the numbers required to display scores.
//
// The upper and lower portions are '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.
//
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
// MD_UISwitch library can be found at https://github.com/MajicDesigns/MD_UISwitch
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <MD_UISwitch.h>
#include <SPI.h>
#include "Font_Data.h"
#define DEBUG 0
#if DEBUG
#define PRINT(s, v) { Serial.print(F(s)); Serial.print(v); } ///< Print a string followed by a value (decimal)
#define PRINTX(s, v) { Serial.print(F(s)); Serial.print(v, HEX); } ///< Print a string followed by a value (hex)
#define PRINTS(s) { Serial.print(F(s)); } ///< Print a string
#else
#define PRINT(s, v) ///< Print a string followed by a value (decimal)
#define PRINTX(s, v) ///< Print a string followed by a value (hex)
#define PRINTS(s) ///< Print a string
#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
const MD_MAX72XX::moduleType_t HARDWARE_TYPE = MD_MAX72XX::FC16_HW;
const uint8_t NUM_ZONES = 4;
const uint8_t ZONE_SIZE = 4;
const uint8_t MAX_DEVICES = (NUM_ZONES * ZONE_SIZE);
const uint8_t CLK_PIN = 13;
const uint8_t DATA_PIN = 11;
const uint8_t CS_PIN = 10;
// HARDWARE SPI
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
// Other global variables
bool invertUpperZone = false; // Hardware type adaptation
const uint8_t NUM_SCORES = 2; // Number of scores displayed
const uint8_t NUM_DIGITS = 3; // Maximum number of decimal digits in the score
uint16_t maxScore; // Maximum score displayed, calculated from number of digits
uint16_t score[NUM_SCORES] = { 0 }; // Running score registers
char mesg[NUM_SCORES][NUM_DIGITS+1]; // Persistent message buffer with the score to be displayed
const uint8_t SCORE_BASE_ZONE[NUM_SCORES] = { 0, 2 }; // Scores base zone number, add in UPPER and LOWER
const uint8_t ZONE_UPPER = 1;
const uint8_t ZONE_LOWER = 0;
// Hardware and objects for score inc/dec input switches
// if NUM_SCORES is changed the number of pins in the array will need to be adjusted
uint8_t pinInc[NUM_SCORES] = { 9, 7 }; // increment score pins
uint8_t pinDec[NUM_SCORES] = { 8, 6 }; // decrement score pins
MD_UISwitch_Digital scoreInc(pinInc, NUM_SCORES);
MD_UISwitch_Digital scoreDec(pinDec, NUM_SCORES);
void updateDisplay(uint8_t scoreIdx)
{
char *p = &mesg[scoreIdx][NUM_DIGITS];
uint16_t s = score[scoreIdx]; // temp score for arithmetic
*p-- = '\0'; // terminate the string, we work backwards through the buffer
for (uint8_t j = 0; j < NUM_DIGITS; j++)
{
*p-- = (s % 10) + '0'; // ascii digit for the lowest digit
s /= 10;
}
PRINT("\nMesg[", scoreIdx);
PRINT("]:'", mesg[scoreIdx]);
PRINTS("'");
P.displayZoneText(SCORE_BASE_ZONE[scoreIdx]+ZONE_LOWER, mesg[scoreIdx], PA_RIGHT, P.getSpeed(), 0, PA_PRINT, PA_NO_EFFECT);
P.displayZoneText(SCORE_BASE_ZONE[scoreIdx]+ZONE_UPPER, mesg[scoreIdx], PA_RIGHT, P.getSpeed(), 0, PA_PRINT, PA_NO_EFFECT);
P.synchZoneStart();
}
void setup(void)
{
#if DEBUG
Serial.begin(57600);
#endif
PRINTS("\n[Scoreboard Example]");
invertUpperZone = (HARDWARE_TYPE == MD_MAX72XX::GENERIC_HW || HARDWARE_TYPE == MD_MAX72XX::PAROLA_HW);
// initialise the inc/dec switches
scoreInc.begin();
scoreDec.begin();
scoreInc.enableDoublePress(false);
scoreDec.enableDoublePress(false);
scoreInc.enableLongPress(false);
scoreDec.enableLongPress(false);
//scoreInc.enableRepeat(false);
//scoreDec.enableRepeat(false);
// initialise the LED display
P.begin(NUM_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
for (uint8_t i = 0; i < NUM_SCORES; i++)
{
uint8_t z = (i * 2 * ZONE_SIZE);
P.setZone(SCORE_BASE_ZONE[i] + ZONE_LOWER, z, z + ZONE_SIZE - 1);
P.setZone(SCORE_BASE_ZONE[i] + ZONE_UPPER, z + ZONE_SIZE, z + (ZONE_SIZE * 2) - 1);
P.setFont(SCORE_BASE_ZONE[i] + ZONE_LOWER, NumFontLower);
P.setFont(SCORE_BASE_ZONE[i] + ZONE_UPPER, NumFontUpper);
if (invertUpperZone)
{
P.setZoneEffect(SCORE_BASE_ZONE[i] + ZONE_UPPER, true, PA_FLIP_UD);
P.setZoneEffect(SCORE_BASE_ZONE[i] + ZONE_UPPER, true, PA_FLIP_LR);
}
}
P.setCharSpacing(0); // spacing is built into the font definition
// work out the maximum score that can be displayed based on number of digits
maxScore = 0;
for (uint8_t i = 0; i < NUM_DIGITS; i++)
maxScore = (maxScore * 10) + 9; // 9999...
PRINT("\nMax score ", maxScore);
// initialise the displayed number
for (uint8_t i = 0; i < NUM_SCORES; i++)
updateDisplay(i);
}
void loop(void)
{
uint8_t pinIdx;
int8_t scoreIdx = -1;
// Handle the input switches to increment/decrement
if (scoreInc.read() != MD_UISwitch::KEY_NULL)
{
pinIdx = scoreInc.getKey();
for (uint8_t i = 0; i < NUM_SCORES; i++)
{
if (pinIdx == pinInc[i])
{
scoreIdx = i;
break;
}
}
PRINT("\nInc score[", scoreIdx);
if (scoreIdx != -1)
{
if (score[scoreIdx] < maxScore) score[scoreIdx]++;
PRINT("]=", score[scoreIdx]);
}
updateDisplay(scoreIdx);
}
else if (scoreDec.read() != MD_UISwitch::KEY_NULL)
{
pinIdx = scoreDec.getKey();
for (uint8_t i = 0; i < NUM_SCORES; i++)
{
if (pinIdx == pinDec[i])
{
scoreIdx = i;
break;
}
}
PRINT("\nDec score[", scoreIdx);
if (scoreIdx != -1)
{
if (score[scoreIdx] > 0) score[scoreIdx]--;
PRINT("]=", score[scoreIdx]);
}
updateDisplay(scoreIdx);
}
// Always run the display animation, we don't care when it completes
P.displayAnimate();
}

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,285 @@
// Demonstrates one double height display using Parola using a single font file
// definition 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.
//
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include "Font_Data.h"
// 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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_ZONES 2
#define ZONE_SIZE 6
#define MAX_DEVICES (MAX_ZONES * ZONE_SIZE)
bool invertUpperZone = false;
#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(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(HARDWARE_TYPE, 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];
};
catalogItem_t *catalog;
const PROGMEM catalogItem_t catalogInvert[] =
{
{ 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
};
const PROGMEM catalogItem_t catalogNoInvert[] =
{
{ 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
};
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;
invertUpperZone = (HARDWARE_TYPE == MD_MAX72XX::PAROLA_HW || HARDWARE_TYPE == MD_MAX72XX::GENERIC_HW);
catalog = (invertUpperZone ? catalogInvert : catalogNoInvert);
#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
if (invertUpperZone)
{
P.setZoneEffect(ZONE_UPPER, true, PA_FLIP_UD);
P.setZoneEffect(ZONE_UPPER, true, PA_FLIP_LR);
}
}
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,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
//
// 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.
//
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include "Font_Data.h"
#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 HARDWARE_TYPE MD_MAX72XX::FC16_HW
#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(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
// Hardware adaptation parameters for scrolling
bool invertUpperZone = false;
#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)
{
invertUpperZone = (HARDWARE_TYPE == MD_MAX72XX::GENERIC_HW || HARDWARE_TYPE == MD_MAX72XX::PAROLA_HW);
#if DEBUG
Serial.begin(57600);
Serial.println("[Double Height demo start]");
#endif
// 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
if (invertUpperZone)
{
P.setZoneEffect(ZONE_UPPER, true, PA_FLIP_UD);
P.setZoneEffect(ZONE_UPPER, true, PA_FLIP_LR);
}
}
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);
if (invertUpperZone)
{
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);
}
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);
if (invertUpperZone)
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);
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,163 @@
// 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.
//
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include "Font_Data_RUS.h" //English + Russian
#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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#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(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
bool invertUpperZone = false;
#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)
{
invertUpperZone = (HARDWARE_TYPE == MD_MAX72XX::GENERIC_HW || HARDWARE_TYPE == MD_MAX72XX::PAROLA_HW);
// 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
if (invertUpperZone)
{
P.setZoneEffect(ZONE_UPPER, true, PA_FLIP_UD);
P.setZoneEffect(ZONE_UPPER, true, PA_FLIP_LR);
}
#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);
if (invertUpperZone)
{
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);
}
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);
if (invertUpperZone)
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);
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,177 @@
// 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.
//
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include "Font_Data.h"
// 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
// Hardware adaptation parameters for scrolling
bool invertUpperZone = false;
textEffect_t scrollUpper, scrollLower;
// 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 HARDWARE_TYPE MD_MAX72XX::FC16_HW
#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(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(HARDWARE_TYPE, 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
// set up global parameters
invertUpperZone = (HARDWARE_TYPE == MD_MAX72XX::GENERIC_HW || HARDWARE_TYPE == MD_MAX72XX::PAROLA_HW);
if (invertUpperZone)
{
#if SCROLL_LEFT // invert and scroll left
scrollUpper = PA_SCROLL_RIGHT;
scrollLower = PA_SCROLL_LEFT;
#else // invert and scroll right
scrollUpper = PA_SCROLL_LEFT;
scrollLower = PA_SCROLL_RIGHT;
#endif
}
else // not invert
{
#if SCROLL_LEFT // not invert and scroll left
scrollUpper = PA_SCROLL_LEFT;
scrollLower = PA_SCROLL_LEFT;
#else // not invert and scroll right
scrollUpper = PA_SCROLL_RIGHT;
scrollLower = PA_SCROLL_RIGHT;
#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 (invertUpperZone)
{
P.setZoneEffect(ZONE_UPPER, true, PA_FLIP_UD);
P.setZoneEffect(ZONE_UPPER, true, PA_FLIP_LR);
}
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 (invertUpperZone)
{
P.displayZoneText(ZONE_UPPER, msgH, PA_CENTER, SCROLL_SPEED, PAUSE_TIME, scrollUpper, scrollLower);
P.displayZoneText(ZONE_LOWER, msgL[cycle], PA_CENTER, SCROLL_SPEED, PAUSE_TIME, scrollUpper, scrollLower);
}
else
{
P.displayZoneText(ZONE_LOWER, msgL[cycle], PA_LEFT, SCROLL_SPEED, PAUSE_TIME, scrollLower, scrollLower);
P.displayZoneText(ZONE_UPPER, msgH, PA_LEFT, SCROLL_SPEED, PAUSE_TIME, scrollUpper, scrollUpper);
}
// prepare for next pass
cycle = (cycle + 1) % ARRAY_SIZE(msgL);
// synchronize the start and run the display
P.synchZoneStart();
}
}

View File

@@ -0,0 +1,88 @@
// Program to exercise the MD_Parola library
//
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 8
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// HARDWARE SPI
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(HARDWARE_TYPE, 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,35 @@
// Program to demonstrate the MD_Parola library
//
// Simplest program that does something useful - Hello World!
//
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 4
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// Hardware SPI connection
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(HARDWARE_TYPE, 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,35 @@
// Program to demonstrate the MD_Parola library
//
// Simplest program that does something useful - Hello!
// Uses the Arduino Print Class extension
//
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 4
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// Hardware SPI connection
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
void setup(void)
{
P.begin();
P.print("Hello!");
}
void loop(void)
{
}

View File

@@ -0,0 +1,53 @@
// Program to demonstrate the MD_Parola library
//
// Uses the Arduino Print Class extension with various output types
//
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 4
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// Hardware SPI connection
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(HARDWARE_TYPE, 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,164 @@
// 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
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 8
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// HARDWARE SPI
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(HARDWARE_TYPE, 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,345 @@
// 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
//
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#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(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(HARDWARE_TYPE, 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,208 @@
// 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
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#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(HARDWARE_TYPE, 11, 13, 10, MAX_DEVICES), "abc", false },
{ MD_Parola(HARDWARE_TYPE, 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,441 @@
// 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
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 8
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// HARDWARE SPI
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(HARDWARE_TYPE, 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,145 @@
// 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
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 8
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// HARDWARE SPI
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(HARDWARE_TYPE, 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,168 @@
// 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
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 8
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// HARDWARE SPI
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(HARDWARE_TYPE, 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,323 @@
// 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
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 11
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// HARDWARE SPI
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(HARDWARE_TYPE, 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;
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;
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;
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, 0x7b, 0xf3, 0x7f, 0xfb, 0x73, 0xfe,
0x24, 0x66, 0xe7, 0xff, 0xff, 0xff, 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,
};
const uint8_t F_WAVE = 14;
const uint8_t W_WAVE = 14;
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;
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;
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;
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;
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 = 9;
const uint8_t PROGMEM arrow2[F_ARROW2 * W_ARROW2] = // arrow fading to outside
{
0x18, 0x3c, 0x7e, 0xe7, 0x00, 0x00, 0xc3, 0x00, 0x00,
0x18, 0x3c, 0x7e, 0xe7, 0xe7, 0x00, 0x00, 0x81, 0x00,
0x18, 0x3c, 0x7e, 0xe7, 0x00, 0xc3, 0x00, 0x00, 0x81,
};
const uint8_t F_SAILBOAT = 1;
const uint8_t W_SAILBOAT = 11;
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;
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;
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;
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;
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;
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,
};
const uint8_t F_CHEVRON = 1;
const uint8_t W_CHEVRON = 9;
const uint8_t PROGMEM chevron[F_CHEVRON * W_CHEVRON] = // chevron
{
0x18, 0x3c, 0x66, 0xc3, 0x99, 0x3c, 0x66, 0xc3, 0x81,
};
struct
{
const uint8_t *data;
uint8_t width;
uint8_t frames;
}
sprite[] =
{
{ rocket, W_ROCKET, F_ROCKET },
{ invader, W_INVADER, F_INVADER },
{ chevron, W_CHEVRON, F_CHEVRON },
{ 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,51 @@
// Program to exercise the MD_Parola library
//
// Demonstrates minimum required for sprite animated text.
//
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 11
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// HARDWARE SPI
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
// Global variables
char msg[] = "Parola Sprites";
// Sprite Definition
const uint8_t F_ROCKET = 2;
const uint8_t W_ROCKET = 11;
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,
};
void setup(void)
{
P.begin();
P.displayText(msg, PA_CENTER, P.getSpeed(), 1000, PA_SPRITE, PA_SPRITE);
P.setSpriteData(rocket, W_ROCKET, F_ROCKET, rocket, W_ROCKET, F_ROCKET);
}
void loop(void)
{
if (P.displayAnimate())
P.displayReset();
}

View File

@@ -0,0 +1,233 @@
// 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
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 11
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// HARDWARE SPI
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(HARDWARE_TYPE, 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
// Sprite Definition
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,
};
// 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_SPRITE,
#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.setSpriteData(rocket, W_ROCKET, F_ROCKET, rocket, W_ROCKET, F_ROCKET);
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,250 @@
// Program to exercise the MD_Parola library
//
// Demonstrates most of the functions of the Parola library Text and Graphics combined.
// Not all animations look good, so this can also be used to determine which animations
// will work for the required application.
//
// 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
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
// MD_MAXPanel library can be found at https://github.com/MajicDesigns/MD_MAXPanel
//
#include <MD_Parola.h>
#include <MD_MAXPanel.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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 11
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// HARDWARE SPI
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// SOFTWARE SPI
//MD_Parola P = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
// Create the graphics library object, passing through the Parola MD_MAX72XX graphic object
MD_MAXPanel MP = MD_MAXPanel(P.getGraphicObject(), MAX_DEVICES, 1);
// 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 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 Text & Graphics Test]");
#endif
// user interface switches
uiSwitches.begin();
// Parola and MAXPanel objects
P.begin();
P.displayText(msg[curString], PA_CENTER, P.getSpeed(), PAUSE_TIME, PA_PRINT, PA_PRINT);
curString = NEXT_STRING;
MP.begin();
}
void loop(void)
{
doUI();
if (P.displayAnimate())
{
P.setTextBuffer(msg[curString]);
P.displayReset();
curString = NEXT_STRING;
}
if (P.isAnimationAdvanced())
{
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);
// draw the rectangle, taking into account the change in coordinates system
// between Parola and MAXPanel
MP.update(false);
MP.drawRectangle(0, 0, MP.getXMax()-(startText+1), ROW_SIZE-1, !P.getInvert());
MP.drawRectangle(MP.getXMax()-(endText-1), 0, MP.getXMax(), ROW_SIZE-1, !P.getInvert());
MP.update(true);
}
}

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,177 @@
// 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.
//
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 8
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
// Hardware SPI connection
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(HARDWARE_TYPE, 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,185 @@
// 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
//
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#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(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(HARDWARE_TYPE, 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_SCAN_VERTX,
PA_SCROLL_UP_LEFT,
PA_SCROLL_UP,
PA_FADE,
PA_OPENING_CURSOR,
PA_GROW_UP,
PA_SCROLL_UP_RIGHT,
PA_BLINDS,
PA_SPRITE,
PA_CLOSING,
PA_GROW_DOWN,
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,
};
// 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,
};
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.setSpriteData(pacman1, W_PMAN1, F_PMAN1, pacman2, W_PMAN2, F_PMAN2);
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,108 @@
// 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.
//
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#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(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(HARDWARE_TYPE, 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,128 @@
// 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
//
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#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(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(HARDWARE_TYPE, 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,123 @@
// 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.
//
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#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(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(HARDWARE_TYPE, 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,79 @@
// Program to demonstrate the MD_Parola library
//
// Demonstrate use of effects on different zones to create an animated sign
//
// MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
#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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#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(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(HARDWARE_TYPE, 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,247 @@
// 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
// - MD_MAX72XX library can be found at https://github.com/MajicDesigns/MD_MAX72XX
//
// 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 HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#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(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// Arbitrary output pins
// MD_Parola P = MD_Parola(HARDWARE_TYPE, 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 char str[][4] PROGMEM =
{
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
*psz = '\0';
mon--;
if (mon < 12)
{
strncpy_P(psz, str[mon], len);
psz[len] = '\0';
}
return(psz);
}
char *dow2str(uint8_t code, char *psz, uint8_t len)
{
static const char str[][10] PROGMEM =
{
"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"
};
*psz = '\0';
code--;
if (code < 7)
{
strncpy_P(psz, str[code], 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);
}
}