import processing.serial.*;

/*
Code based on Tom Igoe’s Serial Graphing Sketch
 >> http://wiki.processing.org/w/Tom_Igoe_Interview
 Reads X analog inputs and visualizes them by drawing a grid
 using grayscale shading of each square to represent sensor value.
 >> http://howtogetwhatyouwant.at/
 Working with a matrix
 */


String myString = null;
String inString = null;
int lf = 10;    // Linefeed in ASCII

Serial myPort; // The serial port
int rows = 2;
int cols = 3;
int maxNumberOfSensors = rows*cols;
float[] sensorValue = new float[maxNumberOfSensors]; // global variable for storing mapped sensor values,
float[] previousValue = new float[maxNumberOfSensors]; // array of previous values
int[] mins = new int[maxNumberOfSensors];
int[] maxs = new int[maxNumberOfSensors];
float[] Ns = new float[maxNumberOfSensors];

float ellipseSize = 0;

void setup () {
  size(1200, 800); // set up the window to whatever size you want
  ellipseSize = float(width)/float(cols);

  //println(Serial.list()); // List all the available serial ports
  String portName = Serial.list()[0]; // set the number of your serial port!
  myPort = new Serial(this, portName, 9600);
  myPort.clear();
  myPort.bufferUntil('\n'); // don’t generate a serialEvent() until you get a newline (\n) byte
  background(0, 0, 255); // set inital background
  smooth(); // turn on antialiasing
  
  for(int i = 0; i < maxNumberOfSensors; i++) {
    mins[i] = 1023;
    maxs[i] = 0;
    Ns[i] = random(3, 20);
  }
}

void draw () {
  background(255);
  for (int i = 0; i < maxNumberOfSensors; i++) {
    float X = (i % cols) * ellipseSize;
    float Y = (i / cols) * ellipseSize;
    
    //stroke(sensorValue[i]-28, sensorValue[i]-28, sensorValue[i]-28); //Define first colour of the ellipse
    push();
    translate(X, Y);
    float N = Ns[i];
    float d = ellipseSize/N * (sensorValue[i]/255.)/2.;
    for(int y = 0; y < N; y ++) {
      for(int x = 0; x < N; x ++) {
        push();
        translate(ellipseSize/N*float(x) + ellipseSize/2./N, ellipseSize/N*float(y) + ellipseSize/2./N);
        //strokeWeight(1);
        //rect(-ellipseSize/N/2.,-ellipseSize/N/2., ellipseSize/N, ellipseSize/N);
        
        strokeWeight(map(d, 0, ellipseSize/N, 0, 30));
        line(-d, -d, d, d);
        line(d, -d, -d, d);
        pop();
      }
    }
    pop();
  }
}

void serialEvent (Serial myPort) {
  inString = myPort.readStringUntil(lf); // get the ASCII string
  //println("test");
  if (inString != null) { // if it’s not empty
    inString = trim(inString); // trim off any whitespace
    int incomingValues[] = int(split(inString, "\t")); // convert to an array of ints

    if (incomingValues.length <= maxNumberOfSensors && incomingValues.length > 0) {
      for (int i = 0; i < incomingValues.length; i++) {
        // map the incoming values (0 to 1023) to an appropriate gray-scale range (0-255):
        if(incomingValues[i] > maxs[i]) maxs[i] = incomingValues[i];
        if(incomingValues[i] < mins[i]) mins[i] = incomingValues[i];
        
        sensorValue[i] = map(incomingValues[i], mins[i], maxs[i], 0, 255); // stretch 5×5, because sensor value = 255 at rest (without pressure)
        //incomingValue decreases with pressure because it is the resistance
        sensorValue[i] = constrain(incomingValues[i], 0, 255); // stretch 5×5
        println(sensorValue[i]); // print value to see
      }
    }
  }
}
