Coding
Product
Prototype
Visual

Weaving Memories

Weaving Memories - is an encrypted communication system displayed into a laser-cut felt carpet as a physical object.
Project purpose
University
Time
(weeks)
1
Delivery date
February 2022
Authors
Yllka Shehu, Matteo Subet
Role
Developer & Product Designer
Activities
During this intensive workshop I worked on developing a tool that would allow the user to create their own encrypted message and then easily decrypt it. With my colleague, we decided to make it possible to export the output obtained by the user immediately after the encryption phase of the message as a pdf file. This allowed us to easily create a product containing all the stages of our work.
No items found.

/ Abstract
Weaving Memories - is an encrypted communication system displayed into a laser-cut felt carpet as a physical object. The encryption contains a poem represented by four symbols in 15 canvases of different grids and colors.

/ Interface and Interaction Modality
Weaving memories is both a digital and physical project encoded and decoded in Processing, and transformed into a tangible carpet.
The sketch in Processing consists of two screens, the encoding and decoding, where users can easily interact by following the instructions. To encode a message the user types in and the message appears in four different characters. Whereas, to decode it the user needs to use the keys 1-4 for each character, and every after three characters a letter will be shown.

/ User Experience
From the viewpoint of functions the project is simple and clear as it is followed by instructions throughout the whole process. Users can type in their encoded message in different grids and have them saved as pdf files. They can generate digital or physical projects, and customize it according to their needs.

/ Research and Development Context
Woven Memories was inspired by one of the oldest forms of communication of Andean people, and by the core memory used in the early days of computing.
The main forms of expression and communication for the Andean were the textiles, like carpets, where every detail conveyed a meaning, from the woven symbols to the colors and spin of the yarn. Another way was through knotted strings known as khipu, which recorded information in a kind of three-dimensional binary code, similar to today’s computers. We also found knots as a way of sending a message in the handmade Persian carpets, called Pattern Signing - where the patterns are sung to other co-weavers.
The “core rope memory” which was the dominant memory technology in the 60s, was also physically weaved into a high-density storage.

/ References
“Pixel Quipu” - Dave’s blog
“The Woven Sounds” - Mehdi Aminian

/ Source code (Processing)

weaving_memories_v05.pde

// Weaving memories Ver 05
// Coded w <3 by Yllka Shehu & Matteo Subet

PGraphics canvas;
PGraphics pdf;
PFont font;

int rP = 1;
int cP = 1;
String msg = "";
String msgL = "";
String txt = "";
int intersections = 6; //Has to be a multiple of 3
int gW;
int gH;
int gX;
int gY;
int lSpaces;
int mode = 0;
boolean gridCreated = false;
int paragraph;
int fontSize;
String keyCmd = "";
float cursorCmd = 2;
int xP;
int yP;
boolean enterPressed = false;
String errorConsole = "No errors...";
String decodingTxt = "";
String decodingTxtL = "";
String decodingTxtD = "";
int stringCounter = 0;
String[] splitDecTxt = {};
String decodedTxt = "";
String fileNr = "";

void setup() {
  noCursor();
  //size(800, 400);
  fullScreen();
  background(0);
  //font = loadFont("AkzidenzGrotesk-Bold-48.vlw");
  //font = loadFont("Menlo-Regular-48.vlw");
  //font = loadFont("AndaleMono-48.vlw");
  font = loadFont("PTMono-Regular-48.vlw");
  //font = loadFont("SourceCodeProRoman-Regular-48.vlw");
  //paragraph = 15;
  paragraph = int(width/90);
  //fontSize = 12;
  fontSize = int(width/100);
  textFont(font, fontSize);
  
  double w = intersections*Math.ceil(width/intersections);
  Double newW = Double.valueOf(w);
  int intW = newW.intValue();
  
  gW = intW/3;
  println(gW);
  gH = gW;
  gX = ((width/2) + gW/10);
  gY = (height-gH)/2;
  lSpaces = gW /(intersections + 1);
  pdf = createGraphics(gW, gH);
  xP = width/80;
  yP = height/30;
}

void draw() {
  if (mode == 0) {
    background(0);
    introScreen();
  }

  if (mode == 1) {
    encoderScreen();
    if (gridCreated == false) {
      fileNr += System.currentTimeMillis();
      pdf = createGraphics(gW, gH, PDF, "out/" + "Knot_memory_msg_n" + fileNr + ".pdf");
      canvas = createGraphics(gW, gH);
      gridVisual(canvas);
      gridVisual(pdf);
      image(canvas, gX, gY);
      myKeys();
      errorConsole = "No errors...";
      gridCreated = true;
    }
  }

  if (mode == 2) {
    if (gridCreated == false) {
      background(0);
      gridVisualDisplay();
      errorConsole = "No errors...";
      gridCreated = true;
    }
    decoderScreen();
    myKeys();
  }
}

decodingKeys.pde

// Knot memory Ver 05 - decodingKeys
// Coded w <3 by Yllka Shehu & Matteo Subet

import java.util.Map;

void decodingKeys() {
  myKeys();
  for (int i=0; i<splitDecTxt.length; i++) {
    for (Map.Entry me : keys.entrySet()) {
      if (decodingTxtL.length() % 3 == 0) {
        String d = splitDecTxt[i];
        String gV = me.getValue().toString();
        String[] m = match(d, gV);
        if (m != null) {
          decodedTxt += me.getKey().toString();
        }
      }
    }
  }
}

void dKeyOne(int x, int y) {
  int w = width/180;
  push();
  stroke(255);
  line(x - w, y - w, w + x, w + y);
  pop();
}

void dKeyTwo(int x, int y) {
  int w = width/180;
  push();
  stroke(255);
  line(x + w, y - w, - w + x, w + y);
  pop();
}

void dKeyThree(int x, int y) {
  int w = width/180;
  push();
  stroke(255);
  line(x - w, y - w, w + x, w + y);
  line(x + w, y - w, - w + x, w + y);
  pop();
}
void dKeyFour(int x, int y) {
  int w = width/480;
  push();
  fill(76);
  noStroke();
  circle(x, y, w);
  pop();
}

gridVisual.pde

// Knot memory Ver 05 - gridVisual
// Coded w <3 by Yllka Shehu & Matteo Subet

void gridVisual(PGraphics target) {
  background(0);
  target.beginDraw();
  target.background(0);
  target.stroke(76);
  target.strokeWeight(2);
  for (int lX=1; lX<=intersections; lX++) {
    target.line((lSpaces * lX), 0, (lSpaces * lX), gH);
  }
  for (int lY=1; lY<=intersections; lY++) {
    target.line(0, (lSpaces * lY), gW, (lSpaces * lY));
  }
  target.endDraw();
}

void gridVisualDisplay() {
  stroke(76);
  strokeWeight(2);
  for (int lX=1; lX<=intersections; lX++) {
    line((gX + (lSpaces * lX)), gY, (gX + (lSpaces * lX)), gY+gH);
  }
  for (int lY=1; lY<=intersections; lY++) {
    line(gX, (gY + (lSpaces * lY)), gX + gW, (gY + (lSpaces * lY)));
  }
}

keys.pde

// Knot memory Ver 05 - keys
// Coded w <3 by Yllka Shehu & Matteo Subet
//Creating the hash map
HashMap<String, String> keys = new HashMap<String, String>();
//Creating the vocabulary with 3 variables per bit
void myKeys() {
  keys.put("A", "000");
  keys.put("B", "001");
  keys.put("C", "002");
  keys.put("D", "003");
  keys.put("E", "010");
  keys.put("F", "011");
  keys.put("G", "012");
  keys.put("H", "013");
  keys.put("I", "020");
  keys.put("J", "021");
  keys.put("K", "022");
  keys.put("L", "023");
  keys.put("M", "030");
  keys.put("N", "031");
  keys.put("O", "032");
  keys.put("P", "033");
  keys.put("Q", "100");
  keys.put("R", "101");
  keys.put("S", "102");
  keys.put("T", "103");
  keys.put("U", "110");
  keys.put("V", "111");
  keys.put("W", "112");
  keys.put("X", "113");
  keys.put("Y", "120");
  keys.put("Z", "121");
  keys.put("a", "122");
  keys.put("b", "123");
  keys.put("c", "130");
  keys.put("d", "131");
  keys.put("e", "132");
  keys.put("f", "133");
  keys.put("g", "200");
  keys.put("h", "201");
  keys.put("i", "202");
  keys.put("j", "203");
  keys.put("k", "210");
  keys.put("l", "211");
  keys.put("m", "212");
  keys.put("n", "213");
  keys.put("o", "220");
  keys.put("p", "221");
  keys.put("q", "222");
  keys.put("r", "223");
  keys.put("s", "230");
  keys.put("t", "231");
  keys.put("u", "232");
  keys.put("v", "233");
  keys.put("w", "300");
  keys.put("x", "301");
  keys.put("y", "302");
  keys.put("z", "303");
  keys.put("0", "310");
  keys.put("1", "311");
  keys.put("2", "312");
  keys.put("3", "313");
  keys.put("4", "320");
  keys.put("5", "321");
  keys.put("6", "322");
  keys.put("7", "323");
  keys.put("8", "330");
  keys.put("9", "331");
  keys.put(".", "332");
  keys.put(" ", "333");
}
void keyZero(int x, int y) {
  int w = width/180;
  canvas.beginDraw();
  pdf.beginDraw();
  canvas.push();
  pdf.push();
  canvas.stroke(255);
  pdf.stroke(255);
  canvas.line(x - w, y - w, w + x, w + y);
  pdf.line(x - w, y - w, w + x, w + y);
  canvas.pop();
  pdf.pop();
  canvas.endDraw();
  pdf.endDraw();
  image(canvas, gX, gY);
}

void keyOne(int x, int y) {
  int w = width/180;
  canvas.beginDraw();
  pdf.beginDraw();
  canvas.push();
  pdf.push();
  canvas.stroke(255);
  pdf.stroke(255);
  canvas.line(x + w, y - w, - w + x, w + y);
  pdf.line(x + w, y - w, - w + x, w + y);
  canvas.pop();
  pdf.pop();
  canvas.endDraw();
  pdf.endDraw();
  image(canvas, gX, gY);
}

void keyTwo(int x, int y) {
  int w = width/180;
  canvas.beginDraw();
  pdf.beginDraw();
  canvas.push();
  pdf.push();
  canvas.stroke(255);
  pdf.stroke(255);
  canvas.line(x - w, y - w, w + x, w + y);
  pdf.line(x - w, y - w, w + x, w + y);
  canvas.line(x + w, y - w, - w + x, w + y);
  pdf.line(x + w, y - w, - w + x, w + y);
  canvas.pop();
  pdf.pop();
  canvas.endDraw();
  pdf.endDraw();
  image(canvas, gX, gY);
}
void keyThree(int x, int y) {
  int w = width/480;
  canvas.beginDraw();
  pdf.beginDraw();
  canvas.push();
  pdf.push();
  canvas.fill(76);
  pdf.fill(76);
  canvas.noStroke();
  pdf.noStroke();
  canvas.circle(x, y, w);
  pdf.circle(x, y, w);
  canvas.pop();
  pdf.pop();
  canvas.endDraw();
  pdf.endDraw();
  image(canvas, gX, gY);
}

Code
License
CC BY-NC