Parola for Arduino  1.0
Text effects for Parola modular hardware
MD_Parola.h
1 /**
2 \mainpage Library for scrolling text effects using Parola hardware
3 The Parola Library
4 ------------------
5 The Parola library is implemented to work with the Parola hardware. It
6 depends on the MD_MAX72xx library for hardware control.
7 
8 This software library implements functions to simplify the implementation
9 of text special effects on the Parola display.
10 - Left, right or center text justification in the display field.
11 - Text scrolling, text entering and exit effects.
12 - Control display parameters and animation speed.
13 
14 The latest copy of the Parola Software and hardware files can be found
15 at the [Parola website] (http://code.google.com/p/parola-for-arduino).
16 
17 ![The final product with 8 modules connected together] (Working_Display.jpg "Working System")
18 
19 System Components
20 -----------------
21 - \subpage pageHardware
22 - \subpage pageSoftware
23 - \subpage pageConnection
24 
25 Revision History
26 ----------------
27 June 2013 - version 1.0
28 - New library
29 
30 Copyright
31 ---------
32 Copyright (C) 2013 Marco Colli. All rights reserved.
33 
34 This library is free software; you can redistribute it and/or
35 modify it under the terms of the GNU Lesser General Public
36 License as published by the Free Software Foundation; either
37 version 2.1 of the License, or (at your option) any later version.
38 
39 This library is distributed in the hope that it will be useful,
40 but WITHOUT ANY WARRANTY; without even the implied warranty of
41 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
42 Lesser General Public License for more details.
43 
44 You should have received a copy of the GNU Lesser General Public
45 License along with this library; if not, write to the Free Software
46 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
47 
48 \page pageSoftware Parola Software
49 The Parola Library
50 ------------------
51 The Parola library is implemented using the MD_MAX72xx library for hardware
52 control. The library implements functions to simplify the implementation
53 of text special effects on the LED matrix.
54 - Text left, right or center justification in the display
55 - Text scrolling, appearance and disappearance effects
56 - Control display parameters and animation speed
57 
58 ### External Dependencies
59 - Parola uses the MD_MAX72xx library for hardware level control primitives.
60 The latest copy of this library can be found
61 [here] (http://code.google.com/p/arduino-code-repository).
62 
63 Implementing New Text Effects
64 -----------------------------
65 Each of the selected text effects is implemented as a function. This makes it easy to add new
66 effects:
67 - Choose a name for the effect and add it to the textEffect_t enumerated type.
68 - Clone an existing method and modify it according to the guidelines below.
69 - Add the function prototype for the new effect to the class definition
70 (at the bottom of the MD_Parola.h file).
71 - Modify the displayAnimate() method in MD_Parola.cpp to invoke the new method.
72 
73 ###New Text Effects
74 The effects functions are implemented as finite state machines that are called with the
75 frequency set by the setSpeed() method. The class variable _fsmState holds the state from
76 the last invocation of an effect method.
77 
78 An effect method can work in one of 2 ways:
79 - *Additive*: where the animation frames are incrementally built up to the initial display.
80 With this method, the function will need to use the getFirstChar() and getNextChar() methods
81 to build up the displayed text, column by column.
82 - *Subtractive*: where the final displayed text is placed in the buffer using the commonPrint()
83 method and the elements that are not visible at that stage of the animation are removed.
84 
85 Which algorithm is used depends on the type animation and what is convenient for the coder.
86 Examples of both are found in the supplied library text effects.
87 
88 Each effect method is implemented in 2 parts. One part implements the text move IN to the display
89 (method parameter bIn is true) and the other when the text is moving OUT of the display (bIn false).
90 Because the IN and OUT effects can be different for a display cycle, the method must not assume
91 that the first part was ever called. The first phase should always end with the text in its
92 display position (depending on the alignment specified) and the second phase should assume the text
93 is in that position when called. Text position parameters are held in the class variable _limitLeft,
94 _limitRight,
95 
96 The first phase starts with _fsmState set to INITIALISE and ends when the state is set to PAUSE
97 in the effect method. The second phase starts with a PAUSE state and ends when the state is set to
98 END by the method. Aside from the INITIALISE state (set by the displayReset() method), all other
99 state changes are under the control of the effect functions.
100 
101 Coding Tips
102 -----------
103 + The MD_MAX72XX library sets the origin for the LED matrix at the top right of the display. This
104 makes the text leftmost column a higher column number that the far right column. Sometimes this
105 is not intuitive when coding and is worth remembering. Rows are numbered from top to bottom.
106 
107 + Ensure that a new effect is tested in combination with other effects to make sure that transitions
108 are smooth and the IN and OUT effects combine weel. Common errors are misaligned entry compared to
109 exit, with causes a small jump in the text position when the effects are combined.
110 
111 + Display update times grow with the number of modules there are in a display, so some timing
112 paramaters will need to adapt. In most cases the animations will simply slow down.
113 As an example, a 6 module chain updates in approximately 14ms, while a 12 module display
114 takes around 25ms.
115 Most of the time taken is to physically update the display, as animating frames takes about
116 1-2ms to update in the MD_MAX72XX display buffers.
117 
118 \page pageHardware Parola Hardware
119 Design
120 ------
121 The aim was to create a 'lego-like' approach to LED matrix display, using standard 8x8 on
122 LED matrices. The software supports this flexibility through a scalable approach that
123 only requires the definition of the number of modules to adapt existing software to
124 a new configuration.
125 
126 ![Completed Parola module with and without the LED matrix] (PCB_Actual.jpg "Parola Modules")
127 
128 Circuit Schematic
129 -----------------
130 The schematic is the basic application circuit that is found on the MAX7219 datasheet,
131 adapted to the LED matrix. Each Parola Module consists of an 8x8 LED Common Anode matrix
132 controlled by a MAX7219 LED controller and a few passive components. These controllers
133 can be daisy chained, making them ideal for the purpose.
134 
135 ![Parola Circuit Schematic] (Circuit_Schematic.jpg "Parola Schematic")
136 
137 PCB Design
138 ----------
139 The PCD design was executed using the autorouting facility in Eagle CAD, and the PCB was
140 manufactured by SeedStudio. The Eagle CAD files for the layout and the Gerber files
141 suitable for SeedStudio are found on the [Parola website] (http://code.google.com/p/parola-for-arduino).
142 The final design includes edge connections that allow many modules to be connected
143 together into an extended display one LED module high.
144 
145 ![PCB layout ready for manufacture] (PCB_Layout.jpg "PCB Design")
146 
147 \page pageConnection System Connections
148 Connecting Parola to the Arduino
149 --------------------------------
150 The modules are connected through a 4-wire serial interface (SPI), and devices are cascaded,
151 with communications passed through the first device in the chain to all others. The Arduino
152 should be connected to the IN side (shown in the figure below) of the first module in the chain.
153 
154 ![Module Input Header] (Connector.jpg "Connection In")
155 
156 The Arduino interface is implemented with 3 digital outputs that are passed through to
157 the class constructor. The digital outputs define the SPI interface as follows:
158 - DIN - the Data IN signal shifts data into the display module. Data is loaded into
159 the device's internal 16-bit shift register on CLK's rising edge.
160 - CLK - the CLocK signal that is used to time the data for the device.
161 - LD - the interface is active when LoaD signal is LOW. Serial data are loaded into the
162 device shift register while LOAD is LOW and latched in on the riding edge.
163 
164 Note that the LD signal is used to select the entire device chain. This allows separate LD
165 outputs to control multiple Parola displays sharing the same DIN and CLK signals. The
166 software needs to instantiate a separate object for each display.
167 
168 The remaining interface pins are for +5V and GND. The power supply must be able to supply
169 enough current for the number of connected Parola modules. The central position of the GND
170 connector provides some protection for accidentally reversing the connector.
171 
172 Connecting Parola Modules
173 -------------------------
174 Separate Parola modules are connected by the plugging them together edge to edge, with the
175 OUT side of one module plugged to the IN side of the next, as shown in the figure below.
176 
177 ![Connecting Parola modules] (Modules_conn.jpg "Modules connected")
178 */
179 #ifndef _MD_PAROLA_H
180 #define _MD_PAROLA_H
181 
182 #include <Arduino.h>
183 #include <MD_MAX72xx.h>
184 
185 // Miscellaneous defines
186 #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
187 
188 /**
189  * Core object for the Parola library
190  */
191 class MD_Parola
192 {
193  public:
194  /**
195  * Text alignment specification.
196  *
197  * Used to define the display text aligmnent and to specify direction for
198  * scrolling and animations. In the situation where LEFT AND RIGHT are the onty sensible
199  * options (eg, text scrolling direction), CENTER will behave the same as LEFT.
200  */
202  {
203  LEFT, ///< The leftmost column for the first character will be on the left side of the display
204  CENTER, ///< The text will be placed with equal number of blank display columns either side
205  RIGHT ///< The rightmost column of the last character will be on the right side of the display
206  };
207 
208  /**
209  * Special effect specification.
210  *
211  * Used to define the effects to be used for the entry and exit of text in the display area.
212  */
214  {
215  NO_EFFECT, ///< Used as a place filler, executes no operation
216  PRINT, ///< Text just appears (printed)
217  SLICE, ///< Text enters and exits a slice (column) at a time
218  WIPE, ///< Text appears/disappears one column at a time, looks like it is wiped on and off
219  WIPE_CURSOR, ///< WIPE with a light bar ahead of the change
220  OPENING, ///< Appear and disappear from the center of the display, towards the ends
221  OPENING_CURSOR, ///< OPENING with light bars ahead of the change
222  CLOSING, ///< Appear and disappear from the ends of the display, tords the middle
223  CLOSING_CURSOR, ///< CLOSING with light bars ahead of the change
224  BLINDS, ///< Text is replaced behind vertical blinds
225  DISSOLVE, ///< Text dissolves from one display to another
226  SCROLL_UP, ///< Text scrolls up through the display
227  SCROLL_DOWN, ///< Text scrolls down through the display
228  SCROLL_LEFT, ///< Text scrolls right to left on the display
229  SCROLL_RIGHT, ///< Text scrolls left to right on the display
230  };
231 
232  /**
233  * Class Constructor.
234  *
235  * Instantiate a new instance of the class. The parameters passed are used to
236  * connect the software to the hardware using the MD_MAX72XX class.
237  *
238  * See documentation for the MD_MAX72XX library for detailed explanation of parameters.
239  *
240  * \param dataPin output on the Arduino where data gets shifted out.
241  * \param clkPin output for the clock signal.
242  * \param csPin output for selecting the device.
243  * \param numDevices number of devices connected. Default is 1 if not supplied.
244  */
245  MD_Parola(uint8_t dataPin, uint8_t clkPin, uint8_t csPin, uint8_t numDevices=1);
246 
247  /**
248  * Class Destructor.
249  *
250  * Release allocated memory and does the necessary to clean up once the object is
251  * no longer required.
252  */
253  ~MD_Parola(void);
254 
255  //--------------------------------------------------------------
256  /** \name Methods for core object control.
257  * @{
258  */
259  /**
260  * Animate the display.
261  *
262  * Animate the display using the currently specifed text and animation parameters.
263  * This method needs to be invoked as often as possible to ensure smooth animation.
264  * The animation is goiverened by a time tick that is set by the setSpeed() method
265  * and it will pause between entry and exit using the time set by the setPause() method.
266  *
267  * The calling program should monitor the return value for a true in order to either
268  * reset the animation or supply another string for display.
269  *
270  * \return bool true if the current animation has competed, false otherwise.
271  */
272  bool displayAnimate(void);
273 
274  /**
275  * Clear the display.
276  *
277  * Clear all the data from the current display.
278  *
279  * \return No return value.
280  */
281  inline void displayClear() { _D.clear(); };
282 
283  /**
284  * Reset the current animation to restart.
285  *
286  * This method is used to reset an animation back to the start of the current cycle.
287  * It is normally invoked after all the parameters for a display are set and the
288  * animation needs to be started (or restarted).
289  *
290  * \return No return value.
291  */
292  void displayReset(void);
293 
294  /**
295  * Easy start for a scrolling text display.
296  *
297  * This method is a convenient way to set up a scrolling display. All the data
298  * necessary for setup is passed through as parameters and the display animation
299  * is started.
300  *
301  * \param pText parameter suitable for the setTextBuffer() method.
302  * \param align parameter suitable for the the setTextAlignment() method.
303  * \param effect parameter suitable for the the setTextEffect() method.
304  * \param speed parameter suitable for the setSpeed() method.
305  * \return No return value.
306  */
307  void displayScroll(char *pText, textPosition_t align, textEffect_t effect, uint16_t speed);
308 
309  /**
310  * Suspend or resume display updates.
311  *
312  * Stopthe current animation at the point it is at. When pausing it leaves the
313  * display showing the current text. Resuming will restart the animation where
314  * it left off. To reset the animation back to the beginning, use the
315  * displayReset() method.
316  *
317  * \param b boolean value to suspend(true) or resume (false).
318  * \return No return value.
319  */
320  inline void displaySuspend(bool b) { _suspend = b; };
321 
322  /**
323  * Easy start for a non-scrolling text display.
324  *
325  * This method is a convenient way to set up a static text display. All the data
326  * necessary for setup is passed through as parameters and the display animation
327  * is started.
328  *
329  * \param pText parameter suitable for the setTextBuffer() method.
330  * \param align parameter suitable for the the setTextAlignment() method.
331  * \param speed parameter suitable for the setSpeed() method.
332  * \param pause parameter suitable for the setPause() method.
333  * \param effectIn parameter suitable for the setTextEffect() method.
334  * \param effectOut parameter suitable for the setTextEffect() method.
335  * \return No return value.
336  */
337  void displayText(char *pText, textPosition_t align, uint16_t speed, uint16_t pause, textEffect_t effectIn, textEffect_t effectOut = NO_EFFECT);
338 
339  /** @} */
340  //--------------------------------------------------------------
341  /** \name Support methods for visually adjusting the display.
342  * @{
343  */
344 
345  /**
346  * Get the inter-character spacing in columns.
347  *
348  * \return the current setting for the space between characters in columns.
349  */
350  inline uint8_t getCharSpacing(void) { return _charSpacing; };
351 
352  /**
353  * Get the current pause time.
354  *
355  * See the setPause() method.
356  *
357  * \return the pause value in milliseconds.
358  */
359  inline uint16_t getPause(void) { return _pauseTime; };
360 
361  /**
362  * Get the current animation speed.
363  *
364  * See the setSpeed() method
365  *
366  * \return the speed value.
367  */
368  inline uint16_t getSpeed(void) { return _tickTime; };
369 
370  /**
371  * Get the current text alignment specification.
372  *
373  * \return the current text alignment setting.
374  */
375  inline textPosition_t getTextAlignment(void) { return _textAlignment; };
376 
377  /**
378  * Set the inter-character spacing in columns.
379  *
380  * Set the number of blank columns between characters when they are displayed.
381  *
382  * \param cs space between characters in columns.
383  * \return No return value.
384  */
385  inline void setCharSpacing(uint8_t cs) { _charSpacing = cs; };
386 
387  /**
388  * Set the display brightness.
389  *
390  * Set the intensity (brightness) of the display.
391  *
392  * \param intensity The intensity to set the display (0-15).
393  * \return No return value.
394  */
395  inline void setIntensity(uint8_t intensity) { _D.control(MD_MAX72XX::INTENSITY, intensity); };
396 
397  /**
398  * Set the pause between ENTER and EXIT animations.
399  *
400  * Between each entry and exit, the libray will pause by the number of milliseconds
401  * specified to allow the viewer to read the message. For continuous scrolling displays
402  * this should be set to the same value as the display speed.
403  *
404  * \param pause the time, in milliseconds, between animations.
405  * \return No return value.
406  */
407  inline void setPause(uint16_t pause) { _pauseTime = pause; /*(pause > _tickTime ? pause : _tickTime);*/ };
408 
409  /**
410  * Set the animation frame speed.
411  *
412  * The speed of the display is the 'tick' time between animation frames. The lower this time
413  * the faster the animation; set it to zero to run as fast as possible.
414  *
415  * \param speed the time, in milliseconds, between animation frames.
416  * \return No return value.
417  */
418  inline void setSpeed(uint16_t speed) { _tickTime = speed; /*_pauseTime = (_pauseTime > _tickTime ? _pauseTime : _tickTime); */ };
419 
420  /**
421  * Set the text alignment.
422  *
423  * Text alignment is specified as one of the values in textPosition_t.
424  *
425  * \param ta the required text alignment.
426  * \return No return value.
427  */
428  inline void setTextAlignment(textPosition_t ta) { _textAlignment = ta; };
429 
430  /**
431  * Set the pointer to the text buffer.
432  *
433  * Sets the text buffer to be a pointer to user data. The library does not allocate
434  * any memory for the text message, rather it is the calling program that supplies
435  * a pointer to a buffer. This reduces memory requirements and offers the flexibility
436  * to keep a single buffer or rotate buffers with different messages, all under calling
437  * program control, with no livbrary limit to the size or numbers of buffers. The text
438  * placed in the buffer must be properly terminated by the NUL ('\0') character or
439  * processing will overrun the end of the message.
440  *
441  * \param pb pointer to the text buffer to be used.
442  * \return No return value.
443  */
444  inline void setTextBuffer(char *pb) { _pText = pb; };
445 
446  /**
447  * Set the entry and exit text effects.
448  *
449  * The 'in' and 'out' text effects are specified using the textEffect_t enumerated
450  * type. If no effect is required, NO_EFFECT should be specified. NO_EFFECT
451  * is most useful when no exit effect is required (e.g., when DISSOLVE is used) and
452  * the entry effect is sufficient.
453  *
454  * \param effectIn the entry effect, one of the textEffect_t enumerated values.
455  * \param effectOut the exit effect, one of the textEffect_t enumerated values.
456  * \return No return value.
457  */
458  inline void setTextEffect(textEffect_t effectIn, textEffect_t effectOut) { _effectIn = effectIn, _effectOut = effectOut; };
459 
460  /** @} */
461 
462  private:
463  /***
464  * Finite State machine states enumerated type.
465  */
466  enum fsmState_t
467  {
468  INITIALISE, ///< Initialise all variables
469  GET_FIRST_CHAR, ///< Get the first character
470  GET_NEXT_CHAR, ///< Get the next character
471  PUT_CHAR, ///< Placing a character
472  PUT_FILLER, ///< Placing filler (blank) columns
473  PAUSE, ///< Pausing between anmations
474  END ///< Display cycle has completed
475  };
476 
477  // The display hardware controlled by this library
478  MD_MAX72XX _D;
479 
480  // Time and speed controlling data and methods
481  bool _suspend; // don't do anything
482  uint32_t _lastRunTime; // the millis() value for when the animation was last run
483  uint16_t _tickTime; // the time between animations in milliseconds
484  uint16_t _pauseTime; // time to pause the animation between 'in' and 'out'
485 
486  // Display control data and methods
487  fsmState_t _fsmState; // fsm state for all FSMs used to display text
488  uint16_t _textLen; // length of current text in columns
489  int16_t _limitLeft; // leftmost limit for the current display effect
490  int16_t _limitRight; // rightmost limit for the current display effect
491  bool _limitOverflow; // true if the text will overflow the display
492  textPosition_t _textAlignment; // current text alignment
493  textEffect_t _effectIn; // the effect for text entering the display
494  textEffect_t _effectOut; // the effect for text exiting the display
495  bool _moveIn; // animation is movein IN when true, OUT when false
496  void setInitialConditions(void); // set up initial conditions for an effect
497  uint16_t getTextWidth(char *p); // width of text in columns
498  bool calcTextLimits(char *p); // calculate the right and left limits for the text
499 
500  // Character buffer handling data and methods
501  char *_pText; // pointer to text buffer from user call
502  char *_pCurChar; // the current character being processed in the text
503  bool _endOfText; // true when the end of the text string has been reached.
504  void moveTextPointer(void); // move the text pointer depending on direction of buffer scan
505  uint8_t getFirstChar(void); // put the first Text char into the char buffer
506  uint8_t getNextChar(void); // put the next Text char into the char buffer
507 
508  // Font character handling data and methods
509  uint8_t _cBuf[15]; // buffer for loading character font
510  uint8_t _charSpacing; // spacing in columns between characters
511  uint8_t _charCols; // number of columns for this character
512  int16_t _countCols; // count of number of columns already shown
513  uint8_t makeChar(char c); // load a character bitmap and add in trailing _charSpacing blanks
514  uint8_t reverseBuf(uint8_t *p, uint8_t size); // reverse the elements of the buffer
515 
516  // Effect functions
517  void commonPrint(void);
518  void effectPrint(bool bIn);
519  void effectSlice(bool bIn);
520  void effectWipe(bool bLightBar, bool bIn);
521  void effectOpen(bool bLightBar, bool bIn);
522  void effectClose(bool bLightBar, bool bIn);
523  void effectBlinds(bool bIn);
524  void effectDissolve(bool bIn);
525  void effectVScroll(textEffect_t effectSelect, bool bIn);
526  void effectHScroll(textEffect_t effectSelect, bool bIn);
527 };
528 
529 #endif