Conway's game of life applied to the mbed and an RA8875 LCD.

Dependencies:   LifeRules mbed RA8875

Inspired by a forum discussion on the mbed site, this version was scaled to support up to a 480x272 display - in a monochrome mode, or at a lower resolution in color (the color shows simple animation for birthing and dying cells).

Leveraging the LifeRules class, the game can be easily adapted to other displays - whether monochrome or color.

By default, this version allocates memory from the Ethernet ram banks, so avoids the memory limitations of some designs.

It should be simple to adapt it to any display - color or b&w, high or low resolution.

Revision:
3:1139b132f983
Parent:
2:f4aece10ba62
Child:
4:6edc72b38ec2
--- a/main.cpp	Wed Apr 23 22:57:50 2014 +0000
+++ b/main.cpp	Thu Apr 24 11:19:56 2014 +0000
@@ -6,13 +6,15 @@
 #include "LifeRules.h"
 
 // Define the life-map size
-#define LIFE_W 300
-#define LIFE_H 200
-#define LIFE_C Life::color
+#define LIFE_W 150
+#define LIFE_H 100
+#define LIFE_C 2          /* 1 = monochrome, 2 = color */
+#define LIFE_Z 2          /* Zoom factor */
 
-// Define the screen size
-#define SCREEN_W 480
-#define SCREEN_H 272
+// Try to check if there is enough memory (for LPC1768)
+#if LIFE_W * LIFE_H * LIFE_C * 2 / 8 > 0x8000
+#error "Sorry, but there isn't this much memory on an LPC1768"
+#endif
 
 extern "C" void mbed_reset();
 
@@ -31,25 +33,45 @@
 #endif
 
 
-Life life(LIFE_W, LIFE_H, LIFE_C);
+#if LIFE_C == 2
+#define LIFE_CLR Life::color
+#else
+#define LIFE_CLR Life::monochrome
+#endif
+
+Life life(LIFE_W, LIFE_H, LIFE_CLR);
 
-// NOT USING p21, but the mbed lib v82 does not work if NC is part
-// of a constructor. See thread http://mbed.org/forum/bugs-suggestions/topic/4859/
+// NOT USING p21, but the mbed lib v82 will not work if NC is 
+// in the constructor. 
+// See thread http://mbed.org/forum/bugs-suggestions/topic/4859/
 RA8875 lcd(p5, p6, p7, p12, p21, "tft");
 
+// Define the screen size (may be fixed in the display driver)
+#define SCREEN_W 480
+#define SCREEN_H 272
+
 // Where on screen do we locate it?
-#define LIFE_OFFSET_X (SCREEN_W - LIFE_W)
-#define LIFE_OFFSET_Y (SCREEN_H - LIFE_H)
+#if LIFE_W * LIFE_Z < SCREEN_W
+#define H_OFFSET -1
+#else
+#define H_OFFSET 0
+#endif
 
-
+#if LIFE_H * LIFE_Z < SCREEN_H
+#define V_OFFSET -1
+#else
+#define V_OFFSET 0
+#endif
 
-unsigned char imgbuffer[3*LIFE_W];
+#define LIFE_OFFSET_X (SCREEN_W - (LIFE_W * LIFE_Z) + H_OFFSET)
+#define LIFE_OFFSET_Y (SCREEN_H - (LIFE_H * LIFE_Z) + V_OFFSET)
+
+unsigned char imgbuffer[3*LIFE_W]; // from forum thread...
 FILE *img;
 
 LocalFileSystem local("local"); //file system
 Serial pc(USBTX,USBRX); // for debugging
 
-
 int msDelay = 1000;     //delay between frames
 
 void CheckForUserInteraction(void);
@@ -63,28 +85,34 @@
 
 void ScreenUpdate()
 {
-    lcd.window(LIFE_OFFSET_X, LIFE_OFFSET_Y, LIFE_W, LIFE_H);
+    lcd.window(LIFE_OFFSET_X, LIFE_OFFSET_Y, LIFE_W * LIFE_Z, LIFE_H * LIFE_Z);
     lcd._StartGraphicsStream();
     for (int j = 0; j < LIFE_H; j++) {
-        for (int i = 0; i < LIFE_W; i++) {
-            Life::ValueOfLife lifeState = life.getbit(i,j);
-            switch (lifeState) {
-                case Life::dead:
-                    lcd._putp(Black);
-                    break;
-                case Life::dying:
-                    lcd._putp(RGB(64,0,0));
-                    break;
-                case Life::living:
-                    lcd._putp(Charcoal);
-                    break;
-                case Life::birthing:
-                    lcd._putp(Blue);
-                    break;
-                default:
-                    lcd._putp(Orange);
-                    ERR(" lifeState = %d\r\n", lifeState);
-                    break;
+        for (int Zx = 0; Zx < LIFE_Z; Zx++) {
+            for (int i = 0; i < LIFE_W; i++) {
+                Life::ValueOfLife lifeState = life.getbit(i,j);
+                color_t p;
+                switch (lifeState) {
+                    case Life::dead:
+                        p = Black;
+                        break;
+                    case Life::dying:
+                        p = RGB(64,0,0);
+                        break;
+                    case Life::living:
+                        p = Charcoal;
+                        break;
+                    case Life::birthing:
+                        p = Blue;
+                        break;
+                    default:
+                        p = Orange;
+                        ERR(" lifeState = %d\r\n", lifeState);
+                        break;
+                }
+                for (int Zy = 0; Zy < LIFE_Z; Zy++) {
+                    lcd._putp(p);
+                }
             }
         }
     }
@@ -113,7 +141,7 @@
              );
     
     // Frame the life map
-    lcd.rect(LIFE_OFFSET_X-1,LIFE_OFFSET_Y-1,LIFE_OFFSET_X+LIFE_W,LIFE_OFFSET_Y+LIFE_H,Red);
+    lcd.rect(LIFE_OFFSET_X-1,LIFE_OFFSET_Y-1,LIFE_OFFSET_X+LIFE_W*LIFE_Z,LIFE_OFFSET_Y+LIFE_H*LIFE_Z,Red);
     lcd.foreground(Blue);
     int choice = pc.getc();