 const int minutesLen = maxRadius - 13;
 const int hoursLen = maxRadius - 22;
 void clockScene(bool changed) {
-		if (changed) {
-				TV.draw_circle(WIDTH / 2, HEIGHT / 2, maxRadius, 1, 0);
-
-				currentAngle = random(60) * angleDiff;
-				hourAngle = random(60) * angleDiff;
-				minuteAngle = random(60) * angleDiff;
-		}
-
-		drawLineAngle(WIDTH / 2, HEIGHT / 2, currentAngle, secondsLen, 0);
-		drawLineAngle(WIDTH / 2, HEIGHT / 2, minuteAngle, minutesLen, 0);
-
-		currentAngle -= angleDiff;
-		minuteAngle -= angleDiff / 60.0;
-		// Dont bother updating hours
-
-		drawLineAngle(WIDTH / 2, HEIGHT / 2, currentAngle, secondsLen, 1);	
-		drawLineAngle(WIDTH / 2, HEIGHT / 2, hourAngle, hoursLen, 1);
-		drawLineAngle(WIDTH / 2, HEIGHT / 2, minuteAngle, minutesLen, 1);
-
-		checkSceneEnded(15);
+    if (changed) {
+        TV.draw_circle(WIDTH / 2, HEIGHT / 2, maxRadius, 1, 0);
+
+        currentAngle = random(60) * angleDiff;
+        hourAngle = random(60) * angleDiff;
+        minuteAngle = random(60) * angleDiff;
+    }
+
+    drawLineAngle(WIDTH / 2, HEIGHT / 2, currentAngle, secondsLen, 0);
+    drawLineAngle(WIDTH / 2, HEIGHT / 2, minuteAngle, minutesLen, 0);
+
+    currentAngle -= angleDiff;
+    minuteAngle -= angleDiff / 60.0;
+    // Dont bother updating hours
+
+    drawLineAngle(WIDTH / 2, HEIGHT / 2, currentAngle, secondsLen, 1);  
+    drawLineAngle(WIDTH / 2, HEIGHT / 2, hourAngle, hoursLen, 1);
+    drawLineAngle(WIDTH / 2, HEIGHT / 2, minuteAngle, minutesLen, 1);
+
+    checkSceneEnded(15);
 }
 
 double chartRayLen = 0;
 void chartScene(bool changed) {
-		const int chartRadius = (HEIGHT / 2) - 6;
-		if (changed) {
-				chartRayLen = 0;
-				TV.draw_circle(WIDTH / 2, HEIGHT / 2, chartRadius, 1, 0);
-				TV.draw_circle(WIDTH / 2, HEIGHT / 2, chartRadius - 7, 1, 0);
-				TV.draw_circle(WIDTH / 2, HEIGHT / 2, 12, 1, 0);
-
-				for (int i = 0; i < 12; i++) {
-						drawLineAngle(WIDTH / 2, HEIGHT / 2, i * (360.0 / 12), chartRadius, 1);
-				}
-
-				TV.delay(2000);
-		}
-
-		int rays = random(2, 7);
-		double offset = random(180);
-		for (int i = 0; i < rays; i++) {
-				drawLineAngle(WIDTH / 2, HEIGHT / 2, (i * (360.0 / rays)) + offset, chartRayLen + (chartRadius / 2), 1);
-		}
-
-		TV.delay(50);
-		chartRayLen += 0.2;
-
-		checkSceneEnded(20);
+    const int chartRadius = (HEIGHT / 2) - 6;
+    if (changed) {
+        chartRayLen = 0;
+        TV.draw_circle(WIDTH / 2, HEIGHT / 2, chartRadius, 1, 0);
+        TV.draw_circle(WIDTH / 2, HEIGHT / 2, chartRadius - 7, 1, 0);
+        TV.draw_circle(WIDTH / 2, HEIGHT / 2, 12, 1, 0);
+
+        for (int i = 0; i < 12; i++) {
+            drawLineAngle(WIDTH / 2, HEIGHT / 2, i * (360.0 / 12), chartRadius, 1);
+        }
+
+        TV.delay(2000);
+    }
+
+    int rays = random(2, 7);
+    double offset = random(180);
+    for (int i = 0; i < rays; i++) {
+        drawLineAngle(WIDTH / 2, HEIGHT / 2, (i * (360.0 / rays)) + offset, chartRayLen + (chartRadius / 2), 1);
+    }
+
+    TV.delay(50);
+    chartRayLen += 0.2;
+
+    checkSceneEnded(20);
 }
 
 void loop() {
-		bool changed = false;
-		if (currentScene != lastScene) {
-				TV.clear_screen();
-				TV.set_cursor(0, 0);
-
-				digitalWrite(LED_PIN, HIGH);
-				TV.delay(100);
-				digitalWrite(LED_PIN, LOW);
-
-				startTime = TV.millis();
-				changed = true;
-		}
-
-		lastScene = currentScene;
-
-		switch (currentScene) {
-				case SYMBOL_TAURUS:
-						tauroSymbolScene();
-						break;
-				case SYMBOLS_FAST:
-						fastSymbolsScene();
-						break;
-				case PLANETS_SYMBOLS_FAST:
-						planetSymbolsFastScene();
-						break;
-				case WORDS_FAST:
-						fastWordsScene();
-						break;
-				case WORDS_FAST_INLINE:
-						wordsFastInlineScene();
-						break;
-				case STARS:
-						starsScene();
-						break;
-				case NOISE:
-						noiseScene();
-						break;
-				case SYMBOL_FADE:
-						symbolFadeScene(changed);
-						break;
-				case SYMBOL_CHECKERBOARD:
-						symbolCheckerboardScene(changed);
-						break;
-				case SYMBOL_GLITCH_SIZE:
-						symbolGlitchSizeScene();
-						break;
-				case CONSTELLATIONS:
-						constellationsScene();
-						break;
-				case COMMANDS:
-						commandsScene();
-						break;
-				case SYMBOL_GLITCH_LOAD:
-						symbolGlitchLoadScene(changed);
-						break;
-				case WORD_CURSOR:
-						wordCursorScene(changed);
-						break;
-				case WORMHOLE:
-						wormholeScene(changed);
-						break;
-				case SYMBOLS_SNAKE:
-						symbolsSnakeScene(changed);
-						break;
-				case SCROLL_STARS:
-						scrollStarsScene(changed);
-						break;
-				case EYES:
-						eyesScene(changed);
-						break;
-				case CHANNEL:
-						channelScene(changed);
-						break;
-				case VHS:
-						vhsScene(changed);
-						break;
-				case SYMBOL_SHIFT:
-						symbolShiftScene(changed);
-						break;
-				case BLINDS:
-						blindsScene(changed);
-						break;
-				case FADE_IN:
-						fadeInScene(changed);
-						break;
-				// case WHITE_BEAR:
-				// 		whiteBearScene(changed);
-				// 		break;
-				case PARTY_WORDS:
-						partyWordsScene();
-						break;
-				case FILL_LINES:
-						fillLinesScene(changed);
-						break;
-				case CIRCLES:
-						circlesScene(changed);
-						break;
-				case L_SYSTEM:
-						lSystemScene();
-						break;
-				case CLOCK:
-						clockScene(changed);
-						break;
-				case CHART:
-						chartScene(changed);
-						break;
-        		case HEX_SCENE:
-            			hexScene(changed);
-            			break;
-				case PYRAMID:
-						pyramidScene(changed);
-						break;
-				default:
-						TV.print("Invalid scene. ");
-						TV.delay(1000);
-						break;
-		}
-}
+    bool changed = false;
+    if (currentScene != lastScene) {
+        TV.clear_screen();
+        TV.set_cursor(0, 0);
+
+        digitalWrite(LED_PIN, HIGH);
+        TV.delay(100);
+        digitalWrite(LED_PIN, LOW);
+
+        startTime = TV.millis();
+        changed = true;
+    }
+
+    lastScene = currentScene;
+
+    switch (currentScene) {
+        case SYMBOL_TAURUS:
+            tauroSymbolScene();
+            break;
+        case SYMBOLS_FAST:
+            fastSymbolsScene();
+            break;
+        case PLANETS_SYMBOLS_FAST:
+            planetSymbolsFastScene();
+            break;
+        case WORDS_FAST:
+            fastWordsScene();
+            break;
+        case WORDS_FAST_INLINE:
+            wordsFastInlineScene();
+            break;
+        case STARS:
+            starsScene();
+            break;
+        case NOISE:
+            noiseScene();
+            break;
+        case SYMBOL_FADE:
+            symbolFadeScene(changed);
+            break;
+        case SYMBOL_CHECKERBOARD:
+            symbolCheckerboardScene(changed);
+            break;
+        case SYMBOL_GLITCH_SIZE:
+            symbolGlitchSizeScene();
+            break;
+        case CONSTELLATIONS:
+            constellationsScene();
+            break;
+        case COMMANDS:
+            commandsScene();
+            break;
+        case SYMBOL_GLITCH_LOAD:
+            symbolGlitchLoadScene(changed);
+            break;
+        case WORD_CURSOR:
+            wordCursorScene(changed);
+            break;
+        case WORMHOLE:
+            wormholeScene(changed);
+            break;
+        case SYMBOLS_SNAKE:
+            symbolsSnakeScene(changed);
+            break;
+        case SCROLL_STARS:
+            scrollStarsScene(changed);
+            break;
+        case EYES:
+            eyesScene(changed);
+            break;
+        case CHANNEL:
+            channelScene(changed);
+            break;
+        case VHS:
+            vhsScene(changed);
+            break;
+        case SYMBOL_SHIFT:
+            symbolShiftScene(changed);
+            break;
+        case BLINDS:
+            blindsScene(changed);
+            break;
+        case FADE_IN:
+            fadeInScene(changed);
+            break;
+        case PARTY_WORDS:
+            partyWordsScene();
+            break;
+        case FILL_LINES:
+            fillLinesScene(changed);
+            break;
+        case CIRCLES:
+            circlesScene(changed);
+            break;
+        case L_SYSTEM:
+            lSystemScene();
+            break;
+        case CLOCK:
+            clockScene(changed);
+            break;
+        case CHART:
+            chartScene(changed);
+            break;
+        case HEX_SCENE:
+            hexScene(changed);
+            break;
+        case PYRAMID:
+            pyramidScene(changed);
+            break;
+        default:
+            TV.print("Invalid scene. ");
+            blinkForever();
+            break;
+    }
+}

int treeXOffset = 0;

void lSystemRecursive(int x, int y, double angle, int len) {
		if (len < 1) {
				return;
		}

		drawLineAngle(x, y, angle, len, 1);
		int endX, endY;
		toCartesian(x, y, angle, len, &endX, &endY);

		double startAngle = angle + ((branchAngle * (branches - 1)) / 2.0) + angleOffset;
		for (int i = 0; i < branches; i++) {
				double a = startAngle - (i * branchAngle);
				if (random(rouletteDenominator) != 0) {
						lSystemRecursive(endX, endY, a, len / 2);
				}
		}
}

void drawLSystem() {
		startLen = random(30, 50);
		branches = random(3, 5);
		branchAngle = random(25, 40);
		angleOffset = -10 + random(20);
		rouletteDenominator = random(3, 5);
		treeXOffset = -20 + random(40);
		lSystemRecursive(treeXOffset + (WIDTH / 2), HEIGHT - 1, 90.0 + angleOffset, startLen);
} 

void lSystemScene() {
		drawLSystem();
		TV.delay(200);
		TV.clear_screen();

		checkSceneEnded(20);
}

double currentAngle, hourAngle, minuteAngle;

int snakeY = HEIGHT / 2;
unsigned long lastReset = 0;
void symbolsSnakeScene(bool changed) {
    if (changed) {
        lastSnakeBmp = getRandomSymbol();

        TV.bitmap(BMP_X, BMP_Y, lastSnakeBmp);
        
        lastReset = TV.millis();
        snakeX = WIDTH / 2;
        snakeY = HEIGHT / 2;
    }

    if (TV.millis() - lastReset > 2000) {
        TV.clear_screen();
        TV.bitmap(BMP_X, BMP_Y, lastSnakeBmp);
        lastReset = TV.millis();
        snakeX = WIDTH / 2;
        snakeY = HEIGHT / 2;
        orientation = random((int)TOTAL_ORIENTATION);
    }

    unsigned char currentColor = TV.get_pixel(snakeX, snakeY);
    TV.set_pixel(snakeX, snakeY, !currentColor);

    switch (orientation) {
        case Tau_NE:
            snakeY--;
            snakeX++;
        break;
        case Tau_SE:
            snakeY++;
            snakeX++;
        break;
        case Tau_SW:
            snakeX--;
            snakeY++;
        break;
        case Tau_NW:
            snakeX--;
            snakeY--;
        break;
    }

    if (snakeX < 0) {
        snakeX = WIDTH;
    } else if (snakeX > WIDTH) {
        snakeX = 0;
    }

    if (snakeY < 0) {
        snakeY = HEIGHT;
    } else if (snakeY > HEIGHT) {
        snakeY = 0;
    }

    unsigned char newColor = TV.get_pixel(snakeX, snakeY);

    if (newColor != currentColor) {
        orientation = orientation + 1;
        orientation = orientation % TOTAL_ORIENTATION;
    }

    checkSceneEnded(20);
}

void scrollStarsScene(bool changed) {
    if (changed) {
        // Draw the earth
        TV.draw_circle(WIDTH / 2, HEIGHT / 2, HEIGHT / 2, WHITE, WHITE);
    }

    TV.shift(1, 1);

    // Place a new star on top line
    if (random(7) == 0) {
        TV.set_pixel(random(WIDTH), 0, 1);
    }

    TV.delay(100);

    if (checkSceneEnded(12)) {
        TV.delay(1000);
    }
}

void eyesScene(bool changed) {
    TV.bitmap(BMP_X, BMP_Y, open_eye);

    int irisRadius = 6;
    int irisOffset = -irisRadius + random(irisRadius * 2);
    TV.draw_circle((WIDTH / 2) + irisOffset, HEIGHT / 2, irisRadius, 1, 1);

    TV.delay(1200);

    TV.bitmap(BMP_X, BMP_Y, closed_eye);

    TV.delay(random(200, 600));

    checkSceneEnded(20);
}

void channelScene(bool changed) {
    if (changed) {
        char *s = "VIDEO 1";
        TV.set_cursor(WIDTH - (strlen(s) * FONT_W) - 2, FONT_H + 2);
        TV.print(s);
    }

    TV.delay(1);

    checkSceneEnded(8);
}

int vhsTime = 0;
void vhsScene(bool changed) {
    char *stop = "STOP";
    char *play = "PLAY";
    const int timerWidth = 5;
    char *timer = "--:--";

    if (changed) {
        vhsTime = 0;
        TV.set_cursor(2, FONT_H + 2);
        TV.print(stop);

        TV.set_cursor(WIDTH - (timerWidth * FONT_W) - 2, FONT_H + 2);
        TV.print(timer);

        TV.delay(3500);
        TV.clear_screen();

        TV.set_cursor(2, FONT_H + 2);
        TV.print(play);

        return;
    }

    TV.set_cursor(WIDTH - (timerWidth * FONT_W) - 2, FONT_H + 2);
    TV.print("00:0");
    TV.print(vhsTime % 10);
    vhsTime++;

    TV.delay(1000);

    checkSceneEnded(9);
}

void shiftLine(int orientation, int direction, int index, int step) {
    if (orientation == 0) {
        // Shift column
        if (direction == 1) {
            for (int i = HEIGHT - 2; i >= 0; i--) {
                unsigned char pix = TV.get_pixel(index, i);
                TV.set_pixel(index, i + step, pix);
            }
        } else {
            for (int i = 1; i <= HEIGHT - 1; i++) {
                unsigned char pix = TV.get_pixel(index, i);
                TV.set_pixel(index, i - step, pix);
            }   
        }
    } else {
        // Shift row
        if (direction == 1) {
            for (int i = WIDTH - 2; i >= 0; i--) {
                unsigned char pix = TV.get_pixel(i, index);
                TV.set_pixel(i + step, index, pix);
            }
        } else {
            for (int i = 1; i <= WIDTH - 1; i++) {
                unsigned char pix = TV.get_pixel(i, index);
                TV.set_pixel(i - step, index, pix);
            }   
        }       
    }
}

#define STEP_COUNT 300
