/* Project: 3x3x3 Mono LED Cube (r3).
 * File: MVEdgeTumble.cpp
 * Description:
 *     Movie -- mv_EdgeTumble
 *         LEDs are lit along one edge, and then it "tumbles" from
 *         edge to edge randomly. The LED in the center is faded
 *         in and out.
 *
 * Copyright (C) 2014 Marc Symonds
 * All rights reserved.
 *
 * This software may be used and redistributed, with or without
 * modification, as long as it is understood that this software
 * is provided as-is without any explicit or implied warranties
 * of merchantablity or fitness of purpose.
 */

#include "Arduino.h"
#include "Movies.h"
#include "DisplayFrame.h"

const byte TUMBLESPEED = 25;
const byte TUMBLEDELAY = 150;
const byte FLASHERSPEED = 50;

int getN(byte, byte);

int m[7][2][2] = { 
    {{1, 0}, {2, 0}},
    {{1, 0}, {2, 1}},
    {{1, 1}, {2, 1}},
    {{1, 1}, {2, 2}},
    {{1, 1}, {1, 2}},
    {{0, 1}, {1, 2}},
    {{0, 1}, {0, 2}}
};

unsigned long ft = 0;
boolean flashUp = true;
boolean flashOn = true;

void delayAndFlash(int d)
{
  unsigned long t, ct;
  byte a;
  
  t = millis() + d;
  
  do
  {
    ct = millis();
    
    if (ct > ft)
    {
      a = displayFrame[13];
      if (flashUp)
      {
        if (flashOn)
          if (++a >= MAXBRIGHTNESSLEVEL)
            flashUp = false;
      }
      else
      {
        if (--a < 1)
          flashUp = true;
      }
      displayFrame[13] = a;
      
      ft = ct + FLASHERSPEED;
    }
  } while (ct < t);
}

void mv_EdgeTumble()
{
  unsigned long ts;
  byte a, b, f, l;
  int nx, ny, nz;
  int px, py, pz;
  byte fn, fd;
  Point p[3], v;
  
  ft = millis() + 1000;
  flashUp = (displayFrame[13] < MAXBRIGHTNESSLEVEL);
  flashOn = true;
    
  ts = millis() + (DEF_MOVIE_TIME * 2);
  l = 7;
  
  // Random start point.
  
  a = random(0, 8);
  p[0].Set((a & 1) * 2, (a & 2), (a & 4) / 2);
  
  // Random starting direction.
  
  nx = 0;
  ny = 0;
  nz = 0;
  switch(random(0, 3))
  {
    case 0:
      nx = (p[0].x == 0) ? 1 : -1;
      break;
      
    case 1:
      ny = (p[0].y == 0) ? 1 : -1;
      break;
      
    case 2:
      nz = (p[0].z == 0) ? 1 : -1;
      break;
  }
  
  // Draw initial line.
  
  for (a = 1 ; a < 3 ; a++)
    p[a].Set(p[0].x+(nx*a), p[0].y+(ny*a), p[0].z+(nz*a));
    
  displayFrame[p[0].Pos()] = 7;
  displayFrame[p[1].Pos()] = 7;
  displayFrame[p[2].Pos()] = 7;
  
  while (l > 0)
  {
    if (millis() > ts)
    {
      --l;
      flashOn = false;
    }

    px = 0;
    py = 0;
    pz = 0;

    fn = 1;
    fd = 1;
        
    switch(random(0, 2))
    {
      case 0:
        px = (p[0].x == 0) ? 1 : -1;

        if (nx != 0 || nz != 0)
          pz = (p[0].z == 0) ? 1 : -1;

        if (ny != 0)
          py = (p[0].y == 0) ? 1 : -1;
          
        if (ny != 0 || nz != 0)
        {
          fn = 5;
          fd=255;
        }
        break;
        
      case 1:
        py = (p[0].y == 0) ? 1 : -1;

        if (nx != 0)
          px = (p[0].x == 0) ? 1 : -1;
        
        if (ny != 0 || nz != 0)
          pz = (p[0].z == 0) ? 1 : -1;
          
        if (nz != 0)
        {
          fn = 5;
          fd=255;
        }
        break;
    }
       
    displayFrame[p[0].Pos()] = l;
    
    for (f = 0 ; f < 6 ; f++, fn += fd)
    {
      for (a = 1, b = 0 ; a < 3 ; a++, b++)
      {
        displayFrame[p[a].Pos()] = 0;
        
        if (px == 0)
        {
          p[a].y = p[0].y + (m[fn][b][0] * py);
          p[a].z = p[0].z + (m[fn][b][1] * pz);
        }
        else if (py == 0)
        {
          p[a].x = p[0].x + (m[fn][b][0] * px);
          p[a].z = p[0].z + (m[fn][b][1] * pz);
        }
        else
        {
          p[a].x = p[0].x + (m[fn][b][0] * px);
          p[a].y = p[0].y + (m[fn][b][1] * py);
        }
        
        displayFrame[p[a].Pos()] = l;
      }      
            
      delayAndFlash(TUMBLESPEED);
    }
   
    v = p[0];
    p[0] = p[2];
    p[2] = v; 

    nx = getN(p[0].x, p[2].x);
    ny = getN(p[0].y, p[2].y);
    nz = getN(p[0].z, p[2].z);
    
    delayAndFlash(TUMBLEDELAY);
  }
  
  df_fadeOut();
}

int getN(byte n1, byte n2)
{
  if (n1 == n2)
    return 0;
  else if (n1 < n2)
    return 1;
  else
    return -1;
}

Leave a Reply

Your e-mail address will not be published. Required fields are marked *

Comments Protected by WP-SpamShield Spam Blocker