-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathMD_RobotEyes.h
211 lines (187 loc) · 7.34 KB
/
MD_RobotEyes.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
// Implements a class to draw and animate a pair of 'emotive' eyes for a robot
//
#pragma once
#include "MD_MAX72xx.h"
// Misc defines
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) ///< number of elements in an array
#define EYE_COL_SIZE 8 ///< number of columns in one eye
// Module offsets from first module specified
#define LEFT_MODULE_OFFSET 1 ///< offset from the base LED module for the left eye
#define RIGHT_MODULE_OFFSET 0 ///< offset from the base LED module for the right eye
// Array references for eyeData array below
#define LEFT_EYE_INDEX 1 ///< array reference in the eye data for the left eye
#define RIGHT_EYE_INDEX 0 ///< array reference in the eye data for the right eye
// Basic unit of time a frame is displayed
#define FRAME_TIME 100 ///< minimum animation time
/**
* Robot Eyes Class.
* This class manages the displayed of animated eyes using LED matrices using the functions
* provided by the MD_MAX72xx library.
*/
class MD_RobotEyes
{
public:
/**
* Emotions enumerated type.
*
* This enumerated type defines the emotion animations
* availabel in the class for the eyes display
*/
//
typedef enum
{
E_NONE, ///< placeholder for no emotions, not user selectable
E_NEUTRAL, ///< eyes in neutral position (no animation)
E_BLINK, ///< both eyes blink
E_WINK, ///< one eye blink
E_LOOK_L, ///< both eyes look left
E_LOOK_R, ///< both eyes look right
E_LOOK_U, ///< both eyes look up
E_LOOK_D, ///< both eyes look down
E_ANGRY, ///< eyes look angry (symmetrical)
E_SAD, ///< eyes look sad (symmetrical)
E_EVIL, ///< eyes look evil (symmetrical)
E_EVIL2, ///< eyes look evil (asymmetrical)
E_SQUINT, ///< both eye squint
E_DEAD, ///< eyes indicate dead (different)
E_SCAN_UD, ///< both eyes scanning Up/Down
E_SCAN_LR, ///< both eyes scanning Left/Right
} emotion_t;
/**
* Class Constructor.
*
* Instantiate a new instance of the class.
*/
MD_RobotEyes(void);
/**
* Class Destructor.
*
* Released any allocated memory and does the necessary to clean
* up once the object is no longer required.
*/
~MD_RobotEyes(void) { };
/**
* Initialize the object.
*
* Initialise the object data. This needs to be called during setup() to initialise new
* data for the class that cannot be done during the object creation.
*
* Outside of the class, the MD_MAX72xx library should be initialised and the pointer
* to the MD_MAX72xx object passed to the parameter. Also, as the eyes could be in the
* middle of a string of LED modules, the first 'eye' module can be specified.
*
* /param M pointer to the MD_MAX72xx library object.
* /param moduleStart the first 'eye' LED module. Defaults to 0 if not specified.
*/
void begin(MD_MAX72XX *M, uint8_t moduleStart = 0);
/**
* Set the animation type and parameters.
*
* Set the next animations to the specified. Additionally, set whether the animation should
* auto reverse the action (eg, blink down then back up again) and whether the animation
* should be run in reverse.
*
* Animations are generally symmetric, so only half the anmation needs to be specified.
* If an animated expression needs to be held, the animation should be run without auto
* reverse, which holds the animation at the end point, and then later run the animation
* in reverse from the last position to return to the idle state.
*
* \param e the type of emotion to be displayed, one of the emotion_T enumerated values.
* \param r if true, run auto reverse.
* \param b if true, start the animation from the end of the sequence.
*/
inline void setAnimation(emotion_t e, bool r, bool b = false) { _nextEmotion = e; _autoReverse = r; _animReverse = b; };
/**
* Set the blink time.
*
* When no animation is running and AutoBlink is set, the eyes will occasionally blink.
* Set the minimum time period between blinks. A blink will occur a random time after this.
*
* \param t the minimum time between blinkins actions in milliseconds.
*/
inline void setBlinkTime(uint16_t t) { _timeBlinkMinimum = t; };
/**
* Set or reset auto blink mode.
*
* When no animation is running and AutoBlink is set, the eyes will loccasionally blink.
*
* \param b set auto blink if true, reset auto blink if false.
*/
inline void setAutoBlink(bool b) { _autoBlink = b; };
/**
* Display a text message.
*
* At the end of the cuurent animation, the text will be scrolled across the 'eyes'
* and then the eyes are returned to the neutral expression
*
* \param p a pointer to a char aarray containing a nul terminated string.
The string must remain in scope while the message is being dispayed.
*/
inline bool setText(char *pText) { if (_pText != nullptr) return(false); else _pText = pText; return(true); };
/**
* Animate the display.
*
* This method needs to be invoked as often as possible to ensure smooth animation.
*
* The calling program should monitor the return value for 'true' in order to know when
* the animation has concluded. A 'true' return value means that the animation is complete.
*
* \return bool true if the animation has completed, false otherwise.
*/
bool runAnimation(void);
protected:
// Animations FSM state
typedef enum
{
S_IDLE,
S_RESTART,
S_ANIMATE,
S_PAUSE,
S_TEXT,
} animState_t;
// Define an animation frame
typedef struct animFrame_t
{
uint8_t eyeData[2]; // [LEFT_MODULE_OFFSET] and [RIGHT_MODULE_OFFSET] eye character from font data
uint16_t timeFrame; // time for this frame in milliseconds
};
// Define an entry in the animation sequence lookup table
typedef struct
{
emotion_t e;
animFrame_t *seq;
uint8_t size;
} animTable_t;
// Display parameters
MD_MAX72XX *_M;
uint16_t _sd; // start module for the display
// Animation parameters
uint32_t _timeStartPause;
uint32_t _timeLastAnimation;
uint16_t _timeBlinkMinimum;
animState_t _animState;
bool _autoBlink;
uint16_t _scrollDelay;
// Animation control data
animTable_t _animEntry; // record with animation sequence parameters
int8_t _animIndex; // current index in the animation sequence
bool _animReverse; // true = reverse sequence, false = normal sequence
bool _autoReverse; // true = always play the reverse, false = slected direction only
emotion_t _nextEmotion; // the next emotion to display
char * _pText; // pointer to text data in user code. Not null means there is text to print
// Methods
void loadEye(uint8_t module, uint8_t ch);
void drawEyes(uint8_t L, uint8_t R);
uint8_t loadSequence(emotion_t e); // return the size of the sequence
void loadFrame(animFrame_t* pBuf);
void showText(bool bInit = false);
void dumpSequence(const animFrame_t* pBuf, uint8_t numElements); // debugging routine only
// Static data tables
static const animFrame_t seqBlink[], seqWink[];
static const animFrame_t seqLeft[], seqRight[], seqUp[], seqDown[];
static const animFrame_t seqAngry[], seqSad[], seqEvil[], seqEvil2[];
static const animFrame_t seqSquint[], seqDead[];
static const animFrame_t seqScanUpDown[], seqScanLeftRight[];
// Lookup table to find animation
static const animTable_t lookupTable[];
};