Using shift registers for a 8 x 8 matrix

I have a silly / fun project I am working on which is to make a patch pin matrix with an Arduino, akin to an old analogue computer interface or the EMS Synthi A. I doubt I am the first to do this!

I am using a Due because I have one to hand, but it is totally overkill for the project in its current state (I’m wondering if I can use USB OTG to control some more contemporary synths at some point, but that is a while away), and yes I know it has more pins than you could shake a stick at, but I want to minimise the pin use with a pair of shift registers. The concept is the same as creating a matrix to read from a keypad.

I’m using a CMOS CD4094 as a serial in - parallel out interface and a CD4014 as a parallel in - serial out interface.

I use an array of 8-bit numbers called matrix[8] to store “patches” in the matrix. The CD4094 is meant to scroll through the rows of the matrix (outputs), a single bit is inserted into the first stage of the CD4094 register with a rising clock. Then the CD4014 is put into parallel mode with the parallel inputs linked to the columns of the matrix (inputs). If a patch is present in say X0, Y4 then stage 4 of the register should go high after a rising clock. The CD4014 is then switched to serial mode and clocked through, bitWrite() is used to activate a bit on the associated 8-bit number in the matrix array. The CD4094 is clocked so the active bit is shifted to the next stage and the process is repeated.

The CD4094 is working solidly and as I would expect. The CD4014 is about half way there, it always registers an active bit in the correct place, but sometimes an active bit appears on the stage before and sometimes after at the same time - I’m not particularly sure why this is, my guesses:

the CD4014 datasheet says the clock frequency should be at about 8Mhz, the Due is processing at 84MHz, is it just too fast? :stuck_out_tongue:

there is maybe some parasitic stuff going on between stages, maybe pull-down resistors would be a good idea?

In general, any tips on improving the code would be welcome - please feel free to try it out, I’d love to hear ideas on using a patchable matrix in projects as well :slight_smile: I want to turn it into a library eventually but need to learn how to do that, and I would also like to make a basic PCB for testing (right now I am using wire on breadboard, it’s not quite the same!)

n.b. sketch made in Platform.io so would need some minor tweaks to run in Arduino IDE - remove <Arduino.h> and make sure comments work correctly. You don’t need a Due for this sketch at all, any simple board will do!

/*
Virtual Patch Matrix version 3
This version adds two shift registers to reduce the number of digital pins
required for the patch matrix, a CD4094 and a CD4014. Built on the Arduino
Due.

Datasheets:
http://midondesign.com/Documents/4094BC.PDF
http://uk.farnell.com/texas-instruments/cd4014be/logic-static-shft-reg-8stg-16dip/dp/1740086

Design by Aidan Taylor, for fun!
Electric Noodle Box 2018
Version Date: 30/01/18
*/

#include <Arduino.h>

// CMOS IO
uint8_t clock94 = 2; // CD4094 Clock Pin
uint8_t data94 = 3; // CD4094 Data Pin
uint8_t test94 = 4; // optional to test the data out of the CD4094 (QS)
uint8_t clock14 = 5; // CD4014 Clock pin
uint8_t serial14 = 6; // CD4014 Q8 serial out pin
uint8_t mode14 = 7; // Switch 4014 to Serial mode to read register

// Test Parameters
bool print94; // used for testing the CD4094 Output
bool read14;

// Main Variables
uint8_t matrix[8];
uint8_t columns = 8;
uint8_t rows = 8;

void setup() {
    pinMode(clock94, OUTPUT);
    pinMode(data94, OUTPUT);
    pinMode(test94, INPUT);
    pinMode(clock14, OUTPUT);
    pinMode(serial14, INPUT);
    pinMode(mode14, OUTPUT);

    Serial.begin(115200);
}

void printBits(uint8_t myByte) {
 for(uint8_t mask = 0x80; mask; mask >>= 1) {
   if(mask  & myByte)
       Serial.print('1');
   else
       Serial.print('0');
 }
}

void matrixRead() {
  // Step through each row and read each column to test for a patch
  for(uint8_t x = 0; x < rows; x++) {
    if(x == 0) {
      // Make the first bit active in the 4094 register
      digitalWrite(clock94, LOW);
      digitalWrite(data94, HIGH);
      digitalWrite(clock94, HIGH);
      digitalWrite(data94, LOW);
    }
    else {
      digitalWrite(clock94, LOW);
      digitalWrite(clock94, HIGH);
    }

    for(uint8_t y = 0; y < columns; y++) {
      if(y == 0) {
        digitalWrite(mode14, HIGH);
        digitalWrite(clock14, LOW);
        digitalWrite(clock14, HIGH);
        digitalWrite(mode14, LOW);
      }
      else {
        digitalWrite(clock14, LOW);
        digitalWrite(clock14, HIGH);
      }
      delay(1);
      read14 = digitalRead(serial14);
      if(read14) {
        bitWrite(matrix[x], y, 1);
        Serial.print("connection on row = ");
        Serial.print(x);
        Serial.print(" ");
        Serial.print("column = ");
        Serial.println(y);
      }
      else {
        bitWrite(matrix[x], y, 0);
      }
    }

    /*
    // Test the 4094 serial output on last register bit
    print94 = digitalRead(test94);
    Serial.print("row = ");
    Serial.print(x);
    Serial.print(" ");
    Serial.println(print94);
    */
  }
}

void loop() {
  matrixRead();
  for(uint8_t i = 0; i < 8; i++) {
    printBits(matrix[i]);
    Serial.println(" ");
  }

  delay(1000);
}

Ha! I cracked it, it was indeed a hardware issue - 10k pull-down resistors on each of the CD4014 parallel inputs fixed it - no noise now!

I did also put delays between the clock triggers, I will try taking those out now but the datasheet makes me think I should be wary

I tried figuring out how to use the shiftIn() function for the CD4014 but I was getting odd results - any tips here? looks like it could reduce a couple of lines at least!

It's great that you have figured out how to use the registers and written code this way from scratch. It really helps you understand what's going on. But there is a much more efficient way, faster and with far less code. Use the SPI library. This means you will need to use specific pins on the Due (I don't know which pin numbers they are on Due, but they will be called SCK, MOSI and MISO). This way, you will be able to simultaneously read 8 columns from the cd4014 while writing the next bit pattern out to the cd4095. Just 8 calls to SPI.transfer() and the whole matrix is read.

PaulRB:
It's great that you have figured out how to use the registers and written code this way from scratch. It really helps you understand what's going on. But there is a much more efficient way, faster and with far less code. Use the SPI library. This means you will need to use specific pins on the Due (I don't know which pin numbers they are on Due, but they will be called SCK, MOSI and MISO). This way, you will be able to simultaneously read 8 columns from the cd4014 while writing the next bit pattern out to the cd4095. Just 8 calls to SPI.transfer() and the whole matrix is read.

thanks PaulRB I am looking into this now. SPI is on an ICSP like header on the Due

I had a stab at it but limited luck - I don’t think I am using the library correctly, or else I am missing something

I have an LED on an output of the CD4094 but it is staying on - I think the register bits are all high when it powers on, so it suggests I’m just not shifting it.

I connected MISO to Q8 on the 4014 and MOSI to DATA IN on the 4094 - both chips share SCK

I had to change the Serial/Parallel mode manually on the 4014 to ‘jam’ logic in to the parallel mode - I’m not quite sure how to do it in this case - should I break SPI.transfer() into two commands?

It’s evening now and my head is fried - I will sleep on it

/*
Virtual Patch Matrix version 4
This version adds two shift registers to reduce the number of digital pins
required for the patch matrix, a CD4094 and a CD4014. Built on the Arduino
Due.

Datasheets:
http://midondesign.com/Documents/4094BC.PDF
http://uk.farnell.com/texas-instruments/cd4014be/logic-static-shft-reg-8stg-16dip/dp/1740086

Design by Aidan Taylor, for fun!
Electric Noodle Box 2018
Version Date: 30/01/18
*/

#include <Arduino.h>
#include <SPI.h>

SPISettings mySettings(8000000, LSBFIRST, SPI_MODE0);

// CMOS IO
uint8_t data94 = 2;
uint8_t data14 = 3;
uint8_t mode14 = 4;

// Test Parameters

// Main Variables
uint8_t matrix[8];
uint8_t sendBits[8] = {1, 2, 4, 8, 16, 32, 64, 128};

void setup() {
  SPI.begin();

  Serial.begin(115200);
}

void printBits(uint8_t myByte) {
 for(uint8_t mask = 0x80; mask; mask >>= 1) {
   if(mask  & myByte)
       Serial.print('1');
   else
       Serial.print('0');
 }
}

void spiMatrixRead() {
  //SPI.transfer(sendBits[0]);
  SPI.beginTransaction(mySettings);
  for(uint8_t n = 0; n < 8; n++) {
    digitalWrite(mode14, HIGH);
    digitalWrite(mode14, LOW);
    matrix[n] = SPI.transfer(sendBits[n]);
  }
  SPI.endTransaction();
}

void loop() {
  spiMatrixRead();

  for(uint8_t i = 0; i < 8; i++) {
    printBits(matrix[i]);
    Serial.println(" ");
  }

  Serial.println(" ");
  delay(1000);
}
SPISettings mySettings(8000000, LSBFIRST, SPI_MODE0);

According to the data sheets, the max clock frequency of the 4094 is around 5MHz and the 4014 is about 3MHz, so it may be worth reducing that 8MHz down to perhaps 4 or 2MHz.

Which Arduino pin is connected to the strobe pin of the 4094? And which to the PE input of the 4014? Your code needs to trigger the PE of the 4014 input before doing the SPI.transfer() and trigger the strobe pin of the 4094 afterwards.

Also, you don’t need this array:

uint8_t sendBits[8] = {1, 2, 4, 8, 16, 32, 64, 128};

You can just send 1 << n instead of sendBits[n]

PaulRB:

SPISettings mySettings(8000000, LSBFIRST, SPI_MODE0);

According to the data sheets, the max clock frequency of the 4094 is around 5MHz and the 4014 is about 3MHz, so it may be worth reducing that 8MHz down to perhaps 4 or 2MHz.

Which Arduino pin is connected to the strobe pin of the 4094? And which to the PE input of the 4014? Your code needs to trigger the PE of the 4014 input before doing the SPI.transfer() and trigger the strobe pin of the 4094 afterwards.

Also, you don’t need this array:

uint8_t sendBits[8] = {1, 2, 4, 8, 16, 32, 64, 128};

You can just send 1 << n instead of sendBits[n]

Ah - I just have strobe connected to +V right now, mode14 is the CD4014 parallel enable - I was thinking it would be something like this as I was putting my head down last night, but I don’t quite get how SPI.transfer() orders things just yet. I’m pretty sure that I’m not sending anything at all from the Due at present though - I would expect the CD4094 to be shifting at very least - unless it is too fast of course. Thanks - yes that totally makes sense about the array as well!

In work now, thanks for the tips PaulRB - I will make the ammendments later

dataIn = SPI.transfer(dataOut);

What happens when the above runs is that the SCK pin sends out 8 clock pulses, which go to both the cd4094 and the cd4014. On each clock pulse, one bit of the variable dataOut gets sent to the MOSI pin and shifted into the cd4094. At the same time, one bit is shifted out of the cd4014, to the MISO pin and into the dataIn variable.

Before you call SPI.transfer(), you need to send a pulse (using digitalWrite()) to the cd4014 to get it to capture the signals on its 8 input pins, ready to be shifted out.

After you call SPI.transfer(), you need to send a pulse to the cd4094 (using digitalWrite()) to tell it to transfer the data that has just been shifted in to its 8 output pins. This will cause the cd4014 to read a selected column, next time it receives a pulse.

So you probably want to send the "1" to the cd4094 in setup(). Then, in loop(), you can have a for() loop that repeats 8 times, sending the "2", "4"... "128" and finally re-sending the "1" in readiness for the next scan of the matrix.

Hope that makes sense!

PaulRB:

dataIn = SPI.transfer(dataOut);

What happens when the above runs is that the SCK pin sends out 8 clock pulses, which go to both the cd4094 and the cd4014. On each clock pulse, one bit of the variable dataOut gets sent to the MOSI pin and shifted into the cd4094. At the same time, one bit is shifted out of the cd4014, to the MISO pin and into the dataIn variable.

Before you call SPI.transfer(), you need to send a pulse (using digitalWrite()) to the cd4014 to get it to capture the signals on its 8 input pins, ready to be shifted out.

After you call SPI.transfer(), you need to send a pulse to the cd4094 (using digitalWrite()) to tell it to transfer the data that has just been shifted in to its 8 output pins. This will cause the cd4014 to read a selected column, next time it receives a pulse.

So you probably want to send the "1" to the cd4094 in setup(). Then, in loop(), you can have a for() loop that repeats 8 times, sending the "2", "4"... "128" and finally re-sending the "1" in readiness for the next scan of the matrix.

Hope that makes sense!

That makes perfect sense! Thanks Paul. Heading home shortly so I will give it a whirl

Still not getting on with this :frowning: PaulRB’s last comment made sense but I might not be executing it correctly.

Am I right in thinking that on the CD4094, if the STROBE is LOW, the register can be shifted but the outputs don’t change? The datasheet says “When STROBE is HIGH, data propagates through
the latch to 3-STATE output gates”. And on the CD4014, when Parallel Enable is HIGH, you need to send a clock pulse to jam the bits in, but this won’t shift the register? I have this working without SPI but the screen is turning to alphabetti spaghetti now and I’m struggling!

Regardless, I tried attaching LEDs to each output of the 4094 - but it seems no matter how I send SPI.transfer() I don’t see any results - all outputs on the 4094 are in a HIGH state, matrix is full of 0’s. I feel like, even if I should be using MSBFIRST or a different SPIMODEx I would still see some kind of result - it would just not be the expected output - at the moment I’m getting a load of nothing.

Am I missing some library use? Do I need to tell the library which pins to use for SPI? They are listed here: http://forum.arduino.cc/index.php?topic=132130.0

I have this so far:

/*
Virtual Patch Matrix version 4
This version adds two shift registers to reduce the number of digital pins
required for the patch matrix, a CD4094 and a CD4014. Built on the Arduino
Due.

Datasheets:
http://midondesign.com/Documents/4094BC.PDF
http://www.ti.com/lit/ds/symlink/cd4014b.pdf

Design by Aidan Taylor, for fun!
Electric Noodle Box 2018
Version Date: 05/02/18
*/

#include <Arduino.h>
#include <SPI.h>

SPISettings mySettings(4000000, LSBFIRST, SPI_MODE0);

// CMOS IO
uint8_t data94 = 2;
uint8_t strobe94 = 5;
uint8_t mode14 = 4;

// SPI Digital Pins (Due only)
uint8_t sckPin = 76;

// Test Parameters

// Main Variables
uint8_t matrix[8];

void setup() {
  pinMode(sckPin, OUTPUT);

  SPI.begin();

  Serial.begin(115200);

  SPI.beginTransaction(mySettings);
  digitalWrite(strobe94, HIGH);
  SPI.transfer(1);
  SPI.endTransaction();
}

void printBits(uint8_t myByte) {
 for(uint8_t mask = 0x80; mask; mask >>= 1) {
   if(mask  & myByte)
       Serial.print('1');
   else
       Serial.print('0');
 }
}

void spiMatrixRead() {
  //SPI.transfer(sendBits[0]);
  SPI.beginTransaction(mySettings);
  for(uint8_t n = 0; n < 8; n++) {
    digitalWrite(mode14, HIGH);
    digitalWrite(sckPin, LOW);
    digitalWrite(sckPin, HIGH);
    digitalWrite(strobe94, LOW);
    digitalWrite(mode14, LOW);
    matrix[n] = SPI.transfer(1 << n);
    digitalWrite(strobe94, HIGH);

  }
  SPI.endTransaction();

  SPI.beginTransaction(mySettings);
  digitalWrite(strobe94, LOW);
  SPI.transfer(1);
  digitalWrite(strobe94, HIGH);
  SPI.endTransaction();

}

void loop() {
  spiMatrixRead();

  for(uint8_t i = 0; i < 8; i++) {
    printBits(matrix[i]);
    Serial.println(" ");
  }

  Serial.println(" ");
  delay(1000);
}

I’m not very familiar with cd4094. I use 74hc595 and they are a little different, I think.

The output of each stage of the shift register feeds a latch,
which latches data on the negative edge of the STROBE
input. When STROBE is HIGH, data propagates through
the latch to 3-STATE output gates. These gates are
enabled when OUTPUT ENABLE is taken HIGH.

I think this means you should keep the latch pin high most of the time. But after shifting new data in, take the latch pin low and then high again to latch the data.

You should remove this:

    digitalWrite(sckPin, LOW);
    digitalWrite(sckPin, HIGH);

Leave the clocking to the SPI library. Making the mode line high and then low again, as you are, should be enough to capture the 8 inputs.

    matrix[n] = SPI.transfer(1 << n);

Remember, you already sent "1’ in setup(). The line above will send “1” again on the first iteration of the for() loop. As I said before, in the loop, you want to send "2’, “4”, “8”… “128” and finally “1” on the last iteration .

PaulRB:
I'm not very familiar with cd4094. I use 74hc595 and they are a little different, I think.
I think this means you should keep the latch pin high most of the time. But after shifting new data in, take the latch pin low and then high again to latch the data.

Ok

PaulRB:
You should remove this:

    digitalWrite(sckPin, LOW);

digitalWrite(sckPin, HIGH);



Leave the clocking to the SPI library.

Ok, except I think the 4014 doesn't jam parallel data in without a HIGH clock pulse transistion, and I think I need to be in serial mode to get data back out the register - just switching the parallel enable won't do it alone, I think I proved that with my first sketch but I will go back over it

I think my next step might need to be getting a logic analyser on the SPI pins - I've been looking for an excuse to buy one! I might try a different MCU in the mean time

PaulRB:

    matrix[n] = SPI.transfer(1 << n);

Remember, you already sent "1’ in setup(). The line above will send “1” again on the first iteration of the for() loop. As I said before, in the loop, you want to send "2’, “4”, “8”… “128” and finally “1” on the last iteration .

oh - woops I did do that - that got mixed up somewhere, the lines after the for loop should reset the CD4049. Still I would expect to see some result even if the sequence was off!

Ok, except I think the 4014 doesn't jam parallel data in without a HIGH clock pulse transistion, and I think I need to be in serial mode to get data back out the register - just switching the parallel enable won't do it alone

You may be right. Reading the data sheet again, sounds like I was describing the cd4021 rather than the cd4014.

Let us know how you get on once you have the 4094 strobe signals right.

Looking with a scope today shows that SPI is behaving pretty much as expected, and with my coffee-aided morning eyes I have spotted a proper newb error in the code which I am almost ashamed to mention haha

I'll give you a chance to spot it but hopefully next post will have some real results!

Ok, I definitely have the CD4094 working right now - I did need to be in MSBFIRST although that really messes with my brain haha - it took me a while to figure what was going on but now with correct use of STROBE - the correct output bit on the register stays HIGH for the duration of the SPI.transfer(). Thanks PaulRB, your ordering was correct - I had to look at it on the scope to get it right, it would have taken me a lot longer without your pointers!!

On the downside, it looks like it might not be possible to use the CD4014 without some fudging at this point - the SPI library ref suggests that outside of SPI.beginTransaction() and SPI.endTransaction() you can use the digital pins for whatever. But when I try to set the clock pin HIGH to jam parallel input into the CD4014 - I can see on the scope that it only goes HIGH for a spec of time and then drops back to the SPI clock idle state which is low, this isn’t enough time for the CD4014 to register the change anyway.

I’m not sure if it is a good idea to tie a second pin to the same place to try and force the clock. But I think it might be possible with a second (or first rather) SPI.transfer() with parallel enabled and strobe disabled

Oh yes, it looks like I need to drop the SPI clock down to 2MHz as well, the 4094 wouldn’t work at 4MHz :confused:

/*
Virtual Patch Matrix version 4
This version adds two shift registers to reduce the number of digital pins
required for the patch matrix, a CD4094 and a CD4014. Built on the Arduino
Due.

Datasheets:
http://midondesign.com/Documents/4094BC.PDF
http://www.ti.com/lit/ds/symlink/cd4014b.pdf

Design by Aidan Taylor, for fun!
Electric Noodle Box 2018
Version Date: 05/02/18
*/

#include <Arduino.h>
#include <SPI.h>

SPISettings mySettings(2000000, MSBFIRST, SPI_MODE0);

// CMOS IO
uint8_t data94 = 2;
uint8_t strobe94 = 5;
uint8_t mode14 = 4;

// SPI Digital Pins (Due only)
uint8_t sckPin = 76;

// Test Parameters

// Main Variables
uint8_t matrix[8];

void setup() {
  pinMode(sckPin, OUTPUT);
  pinMode(strobe94, OUTPUT);
  pinMode(mode14, OUTPUT);

  SPI.begin();

  Serial.begin(115200);

  SPI.beginTransaction(mySettings);
  digitalWrite(strobe94, LOW);
  SPI.transfer(1);
  digitalWrite(strobe94, HIGH);
  SPI.endTransaction();
}

void printBits(uint8_t myByte) {
 for(uint8_t mask = 0x80; mask; mask >>= 1) {
   if(mask  & myByte)
       Serial.print('1');
   else
       Serial.print('0');
 }
}

void spiMatrixRead() {
  for(uint8_t n = 0; n < 8; n++) {
    SPI.beginTransaction(mySettings);
    digitalWrite(mode14, HIGH);
    digitalWrite(strobe94, LOW);
    digitalWrite(mode14, LOW);
    matrix[n] = SPI.transfer(2 << n);
    digitalWrite(strobe94, HIGH);
    SPI.endTransaction();
  }

  SPI.beginTransaction(mySettings);
  digitalWrite(strobe94, LOW);
  SPI.transfer(1);
  digitalWrite(strobe94, HIGH);
  SPI.endTransaction();
}

void loop() {
  spiMatrixRead();
  for(uint8_t i = 0; i < 8; i++) {
    printBits(matrix[i]);
    Serial.println(" ");
  }

  Serial.println(" ");
  //delay(1000);
}

This works, the CD4014 serial output is backwards in terms of the matrix - I could either give it it’s own SPI.beginTransaction() message and make the output LSBFIRST, or I could just wire the patch points that way :wink:

/*
Virtual Patch Matrix version 4
This version adds two shift registers to reduce the number of digital pins
required for the patch matrix, a CD4094 and a CD4014. Built on the Arduino
Due.

Datasheets:
http://midondesign.com/Documents/4094BC.PDF
http://www.ti.com/lit/ds/symlink/cd4014b.pdf

Design by Aidan Taylor, for fun!
Electric Noodle Box 2018
Version Date: 05/02/18
*/

#include <Arduino.h>
#include <SPI.h>

SPISettings mySettings(2000000, MSBFIRST, SPI_MODE0);

// CMOS IO
uint8_t strobe94 = 5;
uint8_t mode14 = 4;

// Test Parameters

// Main Variables
uint8_t matrix[8];

void setup() {
  pinMode(strobe94, OUTPUT);
  pinMode(mode14, OUTPUT);

  SPI.begin();

  Serial.begin(115200);

  SPI.beginTransaction(mySettings);
  digitalWrite(strobe94, LOW);
  SPI.transfer(1);
  digitalWrite(strobe94, HIGH);
  SPI.endTransaction();
}

void printBits(uint8_t myByte) {
 for(uint8_t mask = 0x80; mask; mask >>= 1) {
   if(mask  & myByte)
       Serial.print('1');
   else
       Serial.print('0');
 }
}

void spiMatrixRead() {
  for(uint8_t n = 0; n < 8; n++) {
    SPI.beginTransaction(mySettings);
    digitalWrite(mode14, HIGH);
    digitalWrite(strobe94, LOW);
    SPI.transfer(2 << n);
    digitalWrite(mode14, LOW);
    matrix[n] = SPI.transfer(2 << n);
    digitalWrite(strobe94, HIGH);
    SPI.endTransaction();
  }

  SPI.beginTransaction(mySettings);
  digitalWrite(strobe94, LOW);
  SPI.transfer(1);
  digitalWrite(strobe94, HIGH);
  SPI.endTransaction();
}

void loop() {
  spiMatrixRead();
  for(uint8_t i = 0; i < 8; i++) {
    printBits(matrix[i]);
    Serial.println(" ");
  }

  Serial.println(" ");
  delay(1000);
}

The spiMatrixRead() takes under 200µs to process

The big gaps are the digitalWrite() functions!! How annoying :stuck_out_tongue:

1st and 2nd loop, looking at P-O 1 on the CD4094 and SCK in each image

Cool. So how long did your original code tags to scan the matrix?

If you change

    matrix[n] = SPI.transfer(2 << n);

to

    matrix[n] = SPI.transfer(1 << ((n+1)&7);

you should not need that code to re-send the “1” after the for() loop.

I'll hook it up again and check - but not tonight!

By the way, my earlier mistake was totally forgetting pinMode() for STROBE and ENABLE :stuck_out_tongue: