RSeries astromech firmware
LogicEngineController.h
Go to the documentation of this file.
1 #ifndef LOGICENGINECONTROLLER_H
2 #define LOGICENGINECONTROLLER_H
3 
4 #include "ReelTwo.h"
5 #ifndef LENGINE_DELAY_PIN
6  #if defined(REELTWO_TEENSY)
7  #define LENGINE_DELAY_PIN A1 /* analog pin to read keyPause value */
8  #define LENGINE_FADE_PIN A2 /* analog pin to read tweenPause value */
9  #define LENGINE_BRI_PIN A3 /* analog pin to read tweenPause value */
10  #define LENGINE_HUE_PIN A6 /* analog pin to read tweenPause value */
11  #define LENGINE_PAL_PIN 9 /* pin to switch palettes in ADJ mode */
12  #define LENGINE_FJUMP_PIN 0 /* front jumper */
13  #define LENGINE_RJUMP_PIN 1 /* rear jumper */
14  #elif defined(REELTWO_ZERO)
15  #define LENGINE_DELAY_PIN A0 /* analog pin to read keyPause value */
16  #define LENGINE_FADE_PIN A1 /* analog pin to read tweenPause value */
17  #define LENGINE_BRI_PIN A2 /* analog pin to read tweenPause value */
18  #define LENGINE_HUE_PIN A3 /* analog pin to read tweenPause value */
19  #define LENGINE_PAL_PIN 9 /* pin to switch palettes in ADJ mode */
20  #define LENGINE_FJUMP_PIN 2 /* front jumper */
21  #define LENGINE_RJUMP_PIN 4 /* rear jumper */
22  #elif defined(REELTWO_AVR_MEGA)
23  #define LENGINE_DELAY_PIN A0 /* analog pin to read keyPause value */
24  #define LENGINE_FADE_PIN A1 /* analog pin to read tweenPause value */
25  #define LENGINE_BRI_PIN A2 /* analog pin to read Brightness value */
26  #define LENGINE_HUE_PIN A3 /* analog pin to read Color/Hue shift value */
27  #define LENGINE_PAL_PIN 9 /* pin to switch palettes in ADJ mode */
28  #define LENGINE_FJUMP_PIN 2 /* front jumper */
29  #define LENGINE_RJUMP_PIN 4 /* rear jumper */
30  #elif defined(REELTWO_AVR)
31  #define LENGINE_DELAY_PIN A0 /* analog pin to read keyPause value */
32  #define LENGINE_FADE_PIN A1 /* analog pin to read tweenPause value */
33  #define LENGINE_BRI_PIN A2 /* analog pin to read Brightness value */
34  #define LENGINE_HUE_PIN A3 /* analog pin to read Color/Hue shift value */
35  #define LENGINE_PAL_PIN 9 /* pin to switch palettes in ADJ mode */
36  #define LENGINE_FJUMP_PIN 2 /* front jumper */
37  #define LENGINE_RJUMP_PIN 4 /* rear jumper */
38  #endif
39 #endif
40 
41 #include "dome/LogicEngine.h"
42 #include "core/AnalogMonitor.h"
43 #include "core/PersistentStorage.h"
44 
45 #if defined(ESP32)
47 #else
48 
57 template <byte kDelayPin = LENGINE_DELAY_PIN, byte kFadePin = LENGINE_FADE_PIN,
58  byte kBriPin = LENGINE_BRI_PIN, byte kHuePin = LENGINE_HUE_PIN, byte kPalPin = LENGINE_PAL_PIN,
59  byte kFrontJumperPin = LENGINE_FJUMP_PIN, byte kRearJumperPin = LENGINE_RJUMP_PIN>
61 {
62 public:
69  {
70  fLogic[0] = &FLD;
71  fLogic[1] = &RLD;
72  fSettings[0] = FLD.getSettings();
73  fSettings[1] = RLD.getSettings();
74  fFactorySettings[0] = fSettings[0];
75  fFactorySettings[1] = fSettings[1];
76  if (fFLDSettingsStorage.isValid())
77  FLD.changeDefaultSettings(fFLDSettingsStorage.get(fSettings[0]));
78  if (fRLDSettingsStorage.isValid())
79  RLD.changeDefaultSettings(fRLDSettingsStorage.get(fSettings[1]));
80 
81  // ensure button pin is an input
82  pinMode(kDelayPin, INPUT);
83  pinMode(kFadePin, INPUT);
84  pinMode(kBriPin, INPUT);
85  pinMode(kHuePin, INPUT);
86 
87  //jumper is used to set front or rear adjustment mode (pull low to adjust)
88  pinMode(kFrontJumperPin, INPUT_PULLUP); //use internal pullup resistors of Teensy
89  pinMode(kRearJumperPin, INPUT_PULLUP);
90  pinMode(kPalPin, INPUT_PULLUP);
91  }
92 
101  {
102  fLogic[0] = &LD;
103  fLogic[1] = NULL;
104  fSettings[0] = LD.getSettings();
105  fFactorySettings[0] = fSettings[0];
106  if (fFLDSettingsStorage.isValid())
107  LD.changeDefaultSettings(fFLDSettingsStorage.get(fSettings[0]));
108  //jumper is used to set front or rear adjustment mode (pull low to adjust)
109  pinMode(kFrontJumperPin, INPUT_PULLUP); //use internal pullup resistors of Teensy
110  pinMode(kRearJumperPin, INPUT_PULLUP);
111  pinMode(kPalPin, INPUT_PULLUP);
112  }
113 
117  virtual void animate() override
118  {
119  checkAdjSwitch(); //checks the switch and sets adjMode and flipFlopMillis
120  //setStatusLED(); //blinks the status LED back and forth
121  if (fAdjMode != 0)
122  {
123  fAdjLoops++;
124  compareTrimpots(fAdjMode);
125  }
126 
127  int palBut = checkPaletteButton();
128  if (palBut >= 400)
129  {
130  for (int i = 0; i < SizeOfArray(fLogic); i++)
131  {
132  LogicEngineRenderer* logic = fLogic[i];
133  if (logic != NULL)
134  {
135  logic->changeDefaultSettings(fFactorySettings[i]);
136  logic->changeSettings(fFactorySettings[i]);
137  logic->calculateAllColors();
138  if (i == 0)
139  fFLDSettingsStorage.put(fFactorySettings[i]);
140  else if (i == 1)
141  fRLDSettingsStorage.put(fFactorySettings[i]);
142  }
143  }
144  }
145  else if (fAdjMode != 0 && palBut >= 3)
146  {
147  //change up the color palette used for this logic display
148  if (fAdjMode == 1 && fLogic[0] != NULL)
149  fLogic[0]->changePalette();
150  else if (fAdjMode == 2 && fLogic[1] != NULL)
151  fLogic[1]->changePalette();
152  }
153  }
154 
155 private:
156  byte fAdjMode = 0; // 0 for no adjustments, 1 for front, 2 for rear. if adjMode>0, then trimpots will be enabled
157  byte fPrevAdjMode = 0;
158  byte fStartAdjMode = 0;
159  byte fPrevBrightness = 0;
160  byte fPrevPalNum = 0;
161  unsigned fPalPinLoops;
162  bool fPalPinStatus = 1;
163  bool fPrevPalPinStatus = 1;
164  unsigned fAdjLoops;
165  int fStartTrimpots[4]; //will hold trimpot values when adjustments start being made
166  bool fTrimEnabled[4]; //during adjustment, if trimpot has moved beyond specified threshold it will be enabled here
167  int fLoopTrimpots[4]; //will hold trimpot values when adjustments start being made
168  bool fAdjEnabled[4]; //tells us if a trimpot has been adjusted beyond adj_threshold
169  byte fAdjThreshold = 5;
170  LogicEngineSettings fSettings[2];
171  LogicEngineSettings fFactorySettings[2];
172  LogicEngineRenderer* fLogic[2];
173 
174  PERSIST(LogicEngineSettings) fFLDSettingsStorage;
175  PERSIST(LogicEngineSettings) fRLDSettingsStorage;
176 
177  enum
178  {
179  kMAX_FADE = 15,
180  kMAX_DELAY = 500,
181  kMIN_DELAY = 10,
182  kMIN_BRI = 10,
183 
184  kMAX_ADJLOOP = 90000,
185  kMIN_ADJLOOP = 500,
186  };
187 
188  void checkTrimpots(bool startTrim = false)
189  {
190  //check the current trimpot values and put them into startTrimpots[] or loopTrimpots[]
191  int* trimData = (startTrim) ? fStartTrimpots : fLoopTrimpots;
192 
193  trimData[0] = map(analogRead(kDelayPin), 0, 1023, kMIN_DELAY, kMAX_DELAY);
194  trimData[1] = map(analogRead(kFadePin), 0, 1023, 0, kMAX_FADE);
195  trimData[2] = map(analogRead(kBriPin), 0, 1023, kMIN_BRI, LogicEngineDefaults::MAX_BRIGHTNESS);
196  trimData[3] = map(analogRead(kHuePin), 0, 1023, 0, 255);
197  }
198 
199  void compareTrimpots(byte adjMode = 0)
200  {
201  boolean update = false;
202  checkTrimpots();
203  for (byte x = 0; x < 4; x++)
204  {
205  if (x > 1 && fAdjEnabled[x] == 0 &&
206  ((fStartTrimpots[x] - fLoopTrimpots[x] > fAdjThreshold) || (fLoopTrimpots[x] - fStartTrimpots[x] > fAdjThreshold)))
207  {
208  //compare Brightness and Hue using adjThreshold, as changes there can be a lot of work
209  fAdjEnabled[x] = 1;
210  }
211  else if (fAdjEnabled[x] == 0 && fStartTrimpots[x] != fLoopTrimpots[x])
212  {
213  fAdjEnabled[x] = 1;
214  }
215  else if (fAdjEnabled[x] == 1)
216  {
217  if ((x == 1 && fLoopTrimpots[x] != fStartTrimpots[x]) ||
218  (fLoopTrimpots[x] - fStartTrimpots[x] >= 2 || fStartTrimpots[x] - fLoopTrimpots[x] >= 2))
219  {
220  //adjustment is enabled for this pot, if settings have changed see if we need to recalc colors and all that jazz
221  if (fAdjMode == 1 || fAdjMode == 2)
222  {
223  LogicEngineRenderer* logic = fLogic[fAdjMode-1];
224  LogicEngineSettings* settings = &fSettings[fAdjMode-1];
225  *settings = logic->getSettings();
226  if (x == 0)
227  {
228  settings->fDelay = fLoopTrimpots[x];
229  }
230  else if (x == 1)
231  {
232  settings->fFade = fLoopTrimpots[x];
233  }
234  else if (x == 2)
235  {
236  settings->fBri = fLoopTrimpots[x];
237  }
238  else if (x == 3)
239  {
240  settings->fHue = fLoopTrimpots[x];
241  }
242  update = true;
243  }
244  }
245  //save the values for the next loop
246  fStartTrimpots[x] = fLoopTrimpots[x];
247  }
248  }
249  if (update && (fAdjMode == 1 || fAdjMode == 2))
250  {
251  LogicEngineRenderer* logic = fLogic[fAdjMode-1];
252  LogicEngineSettings* settings = &fSettings[fAdjMode-1];
253  if (logic != NULL)
254  {
255  logic->changeSettings(*settings);
256  logic->calculateAllColors();
257  }
258  }
259  }
260 
261  void checkAdjSwitch()
262  {
263  if (digitalRead(kFrontJumperPin) == 0 && fPrevAdjMode != 1 && fStartAdjMode == 0)
264  {
265  fAdjMode = 1;
266  checkTrimpots(true); //put initial trimpot values into startTrimpots[]
267  fAdjLoops = 0;
268 // flipFlopLoops = fastBlink;
269  }
270  else if (digitalRead(kRearJumperPin) == 0 && fPrevAdjMode != 2 && fStartAdjMode == 0)
271  {
272  fAdjMode = 2;
273  checkTrimpots(true); //put initial trimpot values into startTrimpots[]
274  fAdjLoops = 0;
275 // flipFlopLoops = fastBlink;
276  }
277  else if ((fPrevAdjMode != 0 && digitalRead(kRearJumperPin) == 1 &&
278  digitalRead(kFrontJumperPin) == 1 && fStartAdjMode == 0) || (fAdjLoops > kMAX_ADJLOOP))
279  {
280  if (fAdjLoops > kMAX_ADJLOOP)
281  {
282  DEBUG_PRINTLN("MAXED OUT");
283  }
284  //if we were in previous adjMode for way too long, save settings here SAVE STUFF HERE and go back to regular mode!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
285  if (fAdjLoops > kMIN_ADJLOOP)
286  {
287  if (fAdjMode == 1)
288  {
289  fFLDSettingsStorage.put(fSettings[0]);
290  fLogic[0]->changeDefaultSettings(fSettings[0]);
291  }
292  else if (fAdjMode == 2)
293  {
294  fRLDSettingsStorage.put(fSettings[1]);
295  fLogic[1]->changeDefaultSettings(fSettings[1]);
296  }
297  if (fAdjLoops > kMAX_ADJLOOP)
298  {
299  fStartAdjMode = fAdjMode;
300  fAdjLoops = 0;
301  }
302  fAdjMode = 0;
303  for (byte x = 0; x < 4; x++)
304  fAdjEnabled[x] = 0;
305  // flipFlopLoops = slowBlink;
306  }
307  }
308  else if (digitalRead(kRearJumperPin) == 1 && digitalRead(kFrontJumperPin) == 1 && fStartAdjMode != 0)
309  {
310  //adjMode didn't start off centered, which could have messed us up.
311  //now it is centered though, so let's get back to our normal state.
312  fStartAdjMode = 0;
313  }
314  if (fAdjMode != fPrevAdjMode)
315  {
316  // statusBlink(2, 250, 1, 0, 2); //blink purple 2 times
317  }
318  fPrevAdjMode = fAdjMode;
319  }
320 
321  int checkPaletteButton()
322  {
323  if (digitalRead(kPalPin) == 0)
324  {
325  //button is held
326  fPalPinLoops++;
327  if (fPalPinStatus == 1 && fPrevPalPinStatus == 1)
328  {
329  //we just started holding the button
330  fPalPinStatus = 0;
331  fPalPinLoops = 0;
332  }
333  }
334  else if (digitalRead(kPalPin) == 1 && fPalPinStatus == 0 && fPrevPalPinStatus == 0)
335  {
336  //button has just been released
337  fPalPinLoops++;
338  fPalPinStatus = 1;
339  return fPalPinLoops;
340  }
341  fPrevPalPinStatus = fPalPinStatus;
342  return 0;
343  }
344 };
345 
346 #if defined(REELTWO_TEENSY)
347 typedef LogicEngineController<> LogicEngineControllerTeensy;
348 typedef LogicEngineControllerTeensy LogicEngineControllerDefault;
349 #elif defined(REELTWO_ZERO)
350 typedef LogicEngineController<> LogicEngineControllerReactorZeroRedPCB;
352 typedef LogicEngineControllerReactorZeroRedPCB LogicEngineControllerReactorZero;
353 typedef LogicEngineControllerReactorZeroRedPCB LogicEngineControllerDefault;
354 #elif defined(REELTWO_AVR_MEGA)
355 typedef LogicEngineController<> LogicEngineControllerAVR;
356 typedef LogicEngineControllerAVR LogicEngineControllerDefault;
357 #elif defined(REELTWO_AVR)
358 typedef LogicEngineController<> LogicEngineControllerAVR;
359 typedef LogicEngineControllerAVR LogicEngineControllerDefault;
360 #endif
361 
362 #endif
363 
364 #endif
LogicEngineSettings::fBri
byte fBri
Definition: LogicEngine.h:200
LogicEngineSettings::fDelay
byte fDelay
Definition: LogicEngine.h:198
LogicEngineSettings
Current settings for LogicEngine hardware.
Definition: LogicEngine.h:176
LogicEngineDefaults::MAX_BRIGHTNESS
static constexpr byte MAX_BRIGHTNESS
Definition: LogicEngine.h:107
LogicEngineRenderer
Base class renderer for both front and rear RSeries logics.
Definition: LogicEngine.h:597
LogicEngineRenderer::changePalette
void changePalette()
Definition: LogicEngine.h:963
ReelTwo.h
AnimatedEvent
Base class for all animated devices. AnimatedEvent::animate() is called for each device once through ...
Definition: AnimatedEvent.h:18
LogicEngineController32.h
DEBUG_PRINTLN
#define DEBUG_PRINTLN(s)
Definition: ReelTwo.h:188
AnalogMonitor.h
LogicEngineRenderer::changeSettings
void changeSettings(LogicEngineSettings &newSettings)
Definition: LogicEngine.h:1408
LogicEngineRenderer::changeDefaultSettings
virtual void changeDefaultSettings(LogicEngineSettings &settings)=0
PersistentStorage.h
LogicEngineSettings::fHue
byte fHue
Definition: LogicEngine.h:197
LogicEngineController
Settings adjust for LogicEngine logics.
Definition: LogicEngineController.h:60
LogicEngineController::animate
virtual void animate() override
Check the adjustment switch and read trimpots and adjust settings.
Definition: LogicEngineController.h:117
LogicEngineRenderer::getSettings
LogicEngineSettings getSettings()
Definition: LogicEngine.h:1403
LogicEngine.h
LogicEngineController::LogicEngineController
LogicEngineController(LogicEngineRenderer &LD)
Constructor.
Definition: LogicEngineController.h:99
LogicEngineControllerDefault
LogicEngineController LogicEngineControllerDefault
Definition: LogicEngineController32.h:376
LogicEngineRenderer::calculateAllColors
void calculateAllColors(byte colorPalNum, byte brightVal)
Definition: LogicEngine.h:1238
LogicEngineController::LogicEngineController
LogicEngineController(LogicEngineRenderer &FLD, LogicEngineRenderer &RLD)
Constructor.
Definition: LogicEngineController.h:66
LogicEngineSettings::fFade
byte fFade
Definition: LogicEngine.h:196
SizeOfArray
#define SizeOfArray(arr)
Definition: ReelTwo.h:213