Dilbert
Firmware for the Dilbert interactive badge.
 All Classes Files Functions Variables Enumerations Macros Pages
Conways.h
Go to the documentation of this file.
1 
3 #ifndef _CONWAYS_H_
4 #define _CONWAYS_H_
5 
6 #include <App.h>
7 
8 class Conways : public App
9 {
10  static const uint16_t GRID_X = 60, GRID_Y = 80, PIXEL_SCALE = 4, PATTERN_COUNT = 5;
11  unsigned long wait, next;
12  uint8_t currPattern;
13  uint8_t worldX, worldY;
14  bool getDots;
15  unsigned char frontGrid[(uint16_t)(((float)GRID_X / 8.0) + 1.0)][GRID_Y];
16  unsigned char backGrid[(uint16_t)(((float)GRID_X / 8.0) + 1.0)][GRID_Y];
17  unsigned char patterns[PATTERN_COUNT][8] = {
18  // blinker
19  {B00000000, B00000000, B00010000, B00010000, B00010000, B00000000, B00000000, B00000000},
20  // glider
21  {B00000000, B00000000, B00010000, B00001000, B00111000, B00000000, B00000000, B00000000},
22  // lwss
23  {B00000000, B00000000, B00111100, B01000100, B00000100, B01001000, B00000000, B00000000},
24  // mwss
25  {B00000000, B00000000, B01111100, B10000100, B00000100, B10001000, B00100000, B00000000},
26  // hwss
27  {B00000000, B00000000, B01111110, B10000010, B00000010, B10000100, B00110000, B00000000}};
28 
29  void setFGBit(uint16_t x, uint16_t y, uint8_t val)
30  {
31  uint16_t subX = (float)x / 8.0;
32  if (val)
33  {
34  frontGrid[subX][y] = frontGrid[subX][y] | (1 << (x % 8));
35  } // turn bit on
36  else
37  {
38  frontGrid[subX][y] = frontGrid[subX][y] & ~(1 << (x % 8));
39  } // turn bit off
40  }
41  unsigned char getFGBit(uint16_t x, uint16_t y)
42  {
43  return frontGrid[(uint16_t)((float)x / 8.0)][y] & (1 << (x % 8));
44  }
45  void setBGBit(uint16_t x, uint16_t y, uint16_t val)
46  {
47  uint16_t subX = (float)x / 8.0;
48  if (val)
49  {
50  backGrid[subX][y] = backGrid[subX][y] | (1 << (x % 8));
51  } // turn bit on
52  else
53  {
54  backGrid[subX][y] = backGrid[subX][y] & ~(1 << (x % 8));
55  } // turn bit off
56  }
57  unsigned char getBGBit(uint16_t x, uint16_t y)
58  {
59  return backGrid[(uint16_t)((float)x / 8.0)][y] & (1 << (x % 8));
60  }
61  unsigned char getPattBit(uint16_t pattern, uint16_t x, uint16_t y)
62  {
63  return patterns[pattern][y] & (1 << (x % 8));
64  }
65 
66  bool cgolGetDot(uint16_t x, uint16_t y)
67  {
68  uint8_t count = 0;
69  int16_t xleft = x - 1, xright = x + 1, ytop = y + 1, ybottom = y - 1;
70  if (xleft < 0)
71  xleft = GRID_X - 1;
72  if (xright == GRID_X)
73  xright = 0;
74  if (ytop == GRID_Y)
75  ytop = 0;
76  if (ybottom < 0)
77  ybottom = GRID_Y - 1;
78  if (getFGBit(xleft, ytop))
79  count++; // top left
80  if (getFGBit(x, ytop))
81  count++; // top middle
82  if (getFGBit(xright, ytop))
83  count++; // top right
84  if (getFGBit(xleft, y))
85  count++; // middle left
86  if (getFGBit(xright, y))
87  count++; // middle right
88  if (getFGBit(xleft, ybottom))
89  count++; // bottom left
90  if (getFGBit(x, ybottom))
91  count++; // bottom middle
92  if (getFGBit(xright, ybottom))
93  count++; // bottom right
94  if (getFGBit(x, y) && count < 2)
95  { // < 2 && alive, death
96  return false;
97  }
98  else if (getFGBit(x, y) && (count == 2 || count == 3))
99  { // ==2 || ==3 && alive, live
100  return true;
101  }
102  else if (getFGBit(x, y) && count > 3)
103  { // >3 && alive, death
104  return false;
105  }
106  else if (getFGBit(x, y) == false && count == 3)
107  { // ==3 && dead, birth
108  return true;
109  }
110  return false;
111  }
112 
113  void cgol()
114  {
115  for (uint16_t x = 0; x < GRID_X; x++)
116  {
117  for (uint16_t y = 0; y < GRID_Y; y++)
118  {
119  setBGBit(x, y, cgolGetDot(x, y));
120  }
121  }
122  /*
123  if(worldX<GRID_X && getDots){
124  if(worldY<GRID_Y){
125  setBGBit(worldX,worldY,cgolGetDot(worldX,worldY));
126  worldY++;
127  }else{
128  if(getDots){
129  worldY=0;
130  worldX++;
131  }
132  }
133  }else{
134  if(getDots){
135  worldX=0;
136  getDots=false;
137  }
138  }
139  */
140  for (uint16_t x = 0; x < GRID_X; x++)
141  {
142  for (uint16_t y = 0; y < GRID_Y; y++)
143  {
144  bool bit = getBGBit(x, y);
145  setFGBit(x, y, bit);
146  m_badge->display().fillRect(x * PIXEL_SCALE, y * PIXEL_SCALE, PIXEL_SCALE, PIXEL_SCALE,
147  bit ? ILI9341_WHITE : ILI9341_BLACK);
148  }
149  }
150  /*
151  if(worldX<GRID_X && !getDots){
152  if(worldY<GRID_Y){
153  bool bit=getBGBit(worldX,worldY);
154  setFGBit(worldX,worldY,bit);
155  m_badge->display().fillRect(worldX*PIXEL_SCALE,worldY*PIXEL_SCALE,PIXEL_SCALE,PIXEL_SCALE,bit?ILI9341_WHITE:ILI9341_BLACK);
156  worldY++;
157  }else{
158  if(!getDots){
159  worldY=0;
160  worldX++;
161  }
162  }
163  }else{
164  if(!getDots){
165  worldX=0;
166  getDots=true;
167  }
168  }
169  */
170  }
171 
172 public:
173  Conways()
174  : App("Conways")
175  , wait(500)
176  , next(millis())
177  , currPattern(0)
178  , worldX(0)
179  , worldY(0)
180  , getDots(true)
181  {
182  }
183 
184  ~Conways()
185  {
186  }
187 
191  void onEntry()
192  {
193  Serial.begin(9600);
194  App::onEntry();
195 
196  /* Clear the screen */
197  m_badge->display().fillScreen(ILI9341_BLACK);
198 
199  // random fill screen pixels
200  for (int x = 0; x < GRID_X; x++)
201  {
202  for (int y = 0; y < GRID_Y; y++)
203  {
204  bool bit = random(2);
205  setFGBit(x, y, bit);
206  m_badge->display().fillRect(x * PIXEL_SCALE, y * PIXEL_SCALE, PIXEL_SCALE, PIXEL_SCALE,
207  bit ? ILI9341_WHITE : ILI9341_BLACK);
208  }
209  }
210  }
211 
215  bool handleButton(IButton *button)
216  {
217  if (App::handleButton(button))
218  return true;
219 
220  if (button->isActive())
221  {
222  if (button->getID() == 1)
223  { // up (next pattern)
224  for (int x = 0; x < GRID_X; x++)
225  { // clear grid
226  for (int y = 0; y < GRID_Y; y++)
227  {
228  setFGBit(x, y, 0);
229  }
230  }
231  m_badge->display().fillScreen(ILI9341_BLACK); // clear screen
232  currPattern++;
233  currPattern = currPattern >= PATTERN_COUNT ? PATTERN_COUNT - 1 : currPattern;
234  uint16_t xOffset = (GRID_X / 2) - 4, yOffset = (GRID_Y / 2) - 4;
235  for (int x = 0; x < 8; x++)
236  { // set pattern
237  for (int y = 0; y < 8; y++)
238  {
239  bool bit = getPattBit(currPattern, 7 - x, y); // kludge! invert x?!
240  setFGBit(x + xOffset, y + yOffset, bit);
241  m_badge->display().fillRect((x + xOffset) * PIXEL_SCALE, (y + yOffset) * PIXEL_SCALE,
242  PIXEL_SCALE, PIXEL_SCALE,
243  bit ? ILI9341_WHITE : ILI9341_BLACK);
244  }
245  }
246  }
247  if (button->getID() == 2)
248  { // down (prev pattern)
249  for (int x = 0; x < GRID_X; x++)
250  { // clear grid
251  for (int y = 0; y < GRID_Y; y++)
252  {
253  setFGBit(x, y, 0);
254  }
255  }
256  m_badge->display().fillScreen(ILI9341_BLACK); // clear screen
257  currPattern--;
258  currPattern = currPattern < 0 ? 0 : currPattern;
259  uint16_t xOffset = (GRID_X / 2) - 4, yOffset = (GRID_Y / 2) - 4;
260  for (int x = 0; x < 8; x++)
261  { // set pattern
262  for (int y = 0; y < 8; y++)
263  {
264  bool bit = getPattBit(currPattern, 7 - x, y); // kludge! invert x?!
265  setFGBit(x + xOffset, y + yOffset, bit);
266  m_badge->display().fillRect((x + xOffset) * PIXEL_SCALE, (y + yOffset) * PIXEL_SCALE,
267  PIXEL_SCALE, PIXEL_SCALE,
268  bit ? ILI9341_WHITE : ILI9341_BLACK);
269  }
270  }
271  }
272  if (button->getID() == 0)
273  { // left: slower game speed
274  wait += 100;
275  wait = wait > 10000 ? 10000 : wait;
276  }
277  if (button->getID() == 3)
278  { // right: faster game speed
279  wait -= 100;
280  wait = wait < 100 ? 100 : wait;
281  }
282  if (button->getID() == 4)
283  { // a (random pattern)
284  // random fill screen pixels
285  for (int x = 0; x < GRID_X; x++)
286  {
287  for (int y = 0; y < GRID_Y; y++)
288  {
289  bool bit = random(2);
290  setFGBit(x, y, bit);
291  m_badge->display().fillRect(x * PIXEL_SCALE, y * PIXEL_SCALE, PIXEL_SCALE, PIXEL_SCALE,
292  bit ? ILI9341_WHITE : ILI9341_BLACK);
293  }
294  }
295  }
296  if (button->getID() == 5)
297  { // b
298  wait = 500;
299  }
300  }
301 
302  return true;
303  }
304 
308  void run()
309  {
310  /* Keep backlight on */
311  m_manager->feedBacklight(BACKLIGHT_STATE_DIM);
312 
313  if (next < millis())
314  {
315  next = millis() + wait;
316  cgol();
317  }
318  }
319 };
320 
321 #endif
Adafruit_ILI9341 & display()
Gets the TFT display driver.
Definition: Dilbert.h:44
AppManager * m_manager
Pointer to application manager.
Definition: App.h:130
virtual void onEntry()
Called when the application is entered.
Definition: App.h:70
void onEntry()
Definition: Conways.h:191
virtual bool handleButton(IButton *button)
Handle button presses.
Definition: App.h:121
Definition: Conways.h:8
App(char *name)
Creates a new instance of a badge application.
Definition: App.h:22
bool handleButton(IButton *button)
Definition: Conways.h:215
void run()
Definition: Conways.h:308
Dilbert * m_badge
Pointer to badge driver.
Definition: App.h:129
Used to encapsulate an individual application.
Definition: App.h:15
void feedBacklight(uint8_t status=BACKLIGHT_STATE_FULL)
Ensures that the backlight stays on, otherwise it is susceptible to the timeouts set in SystemConfigD...
Definition: AppManager.cpp:152