Introduction: Make Your Own Enigma Replica

Picture of Make Your Own Enigma Replica

EDIT: This Instructable has won Second prize in the 2013 Radio Shack Microcontroller Contest. Thank You to all who voted!

EDIT2: An Open Enigma with fake Standup Nixie Tubes like the ones pictured in this Instructable will soon be available as a Special Kickstarter edition.

This is our very first Instructable and this step by step guide will show you how to build a fully functional electronic replica of the world famous German Enigma machine. This Arduino based Open Source project is able to encrypt & decrypt any Enigma M4 encoded message.

This first ever fully functional Open Source Enigma "exact " Replica was inspired by the Kid's Game to Arduino Enigma Machine by sketchsk3tch.

Using Multiplexing for the LEDs, this circuit with 115 light emitting diodes uses only 38 pins and the 36 push buttons use only 4 pins total thanks to properly placed resistors (and the P-Channel MOSFETs) in the keyboard loop. These 4 16-Segment displays & an LED for each keyboard button would add up quickly the total number of pins required and even the Arduino Mega would have ran out of pins without the 2 methods mentioned above....

In response to the overwhelming demand, we designed the PCB and made it available through www.stgeotronics.com. Skip to Step 10 & beyond for more info. We also offer it as a complete electronics kit & an assembled & tested complete product.

Step 1: Proof of Concept on Breadboard

Picture of Proof of Concept on Breadboard

Before going all out on the development of this electronic Enigma replica, we wanted to make sure we could properly drive the 16 Segment LEDs. If we can do that, than we will be able to do everything as the rest is only Math...

Step 2: Gather the Raw Materials...

Picture of Gather the Raw Materials...

You will need:
1 Arduino Mega
26 Alpha Buttons
26 1/4" Jacks Mono
10 1/4" Plugs Mono
36 Pushbuttons
1 On/Off/On Switch
4 16Segment Orange
4 Injection molded 2-Liter Soda Bottle preform (test tubes)
1 Case Plywood
1 Hinge & Hooks
1 Half-Mortise Lock
1 Perfboard
38 Resistors 470 Ohms
40 Resistors 1K Ohms
7 IRF9Z24N P-Channel MOSFET
1 Piece of Metal & Spray paint

Optional:
Battery Case
Rechargeable Batteries
Battery Charger/Connectors


If we were to do it again, we wouldn't use 1/4" Jacks & Plugs as these are pretty big and tend to overwhelm the whole Enigma. Banana plugs & jacks are smaller & closer to the original connectors used by the real German Enigmas.

Step 3: Lay the Components Down

Picture of Lay the Components Down

The Radio Shack 6" x 8" Micro Perboard is the perfect size to host all components as it provides just the right amount of space to fit everything on & will fit perfectly inside the Enigma box.

We started dividing the space on the Perfboard equally between the 3 regions, but realized soon that this would make the electonic Enigma longer than the real one, so we compressed everything down to the proper spacing.

Once satisfied with the positioning of each components, next step is soldering.

Step 4: Soldering, Soldering & a Little More Soldering

Picture of Soldering, Soldering & a Little More Soldering

OK, this proved to be the most solder I have used on a single project ever. With 18 pins per 16 Segment, times 4 plus 26 keyboard keys + 26 keyboard lamps + a few LEDs & 1 SPDT on/off/on switch, that was a lot of solder.

Our decision to raise the 16 Segment displays up to make them look like old-time Nixie tubes certainly added a lot of solder points!

Our Arduino Mega Pin assignment:

17 Segments:
Seg Pin Wire DuinoPin
a   2   blue  24
b   1   white 22
c   16  wh-bl 25
d   13  green 31
e   9   wh-br 38
f   8   brown 36
g   6   green 32
h   5   wh-or 30
k   4   orang 28
m   3   wh-bl 26
n   17  blue  23
p   15  orang 27
r   12  wh-gr 33
s   11  brown 35
t   7   wh-gr 34
u   14  wh-or 29
dp  10  wh-br 37
anode1 18 red 39
anode2 18 red 41
anode3 18 red 43
anode4 18 red 45

LEDs:
1  40
2  42
3  44
4  46
5  48

Lamps:
QAP 10
WSY 9
EDX 8
RFC 7
TGV 6
ZHB 5
UJN 4
IKM 3
OL  2
anode1 (First Row)  11
anode2 (Second Row) 12
anode3 (Third Row)  13


Function Keys:
A0

Keyboard:
First Row A1
Second Row A2
Third Row A3

Step 5: Make a Box and Cut & Drill the Top Plate.

Picture of Make a Box and Cut & Drill the Top Plate.

After obtaining the exact dimensions of the original M4 wooden box, we purchased a sheet of plywood & cut it in pieces so we could assemble our case.

We decided to cut a steel plate from an obsolete rack mounted server as it had just the right thickness of metal for our needs. After making a transparency that showed where every button/lamp was located & cutting it out, we were able to superimpose it on the metal piece and draw each required hole with a sharpie.

We then spray painted it textured black to look like the real Enigma.

Step 6: Integration Tests

Picture of Integration Tests

First is the permanent fitting of the metal plate on top of the perfboard making sure every button is working and every LED can shine.

Then is the fitting of this solid assembly into the wooden case ensuring we didn't introduce a short anywhere.

Step 7: Software - Ohhhh.... Ouch!

Picture of Software - Ohhhh.... Ouch!

During each hardware assembly phase, we had created small Arduino sketches that would test the specific individual section we were working on:

A code that tests that each keyboard button is read accurately.
A second code that tests each of the 10 function buttons.

An Enigma_POST (Power On Self Test) sketch that tests that each keyboard lamp can be lit precisely and move each LED through each mode, with some modifications to the original breadboard code to ensure each segment of the 4 16-Segment LEDs is working perfectly.

But, even with all these sample codes on hand that tested every piece of hardware on the machine, the task of reproducing the encrypting/decrypting functionality of a real M4 Enigma was a Mathematics tour-de-force!


All Arduino sketches will be available on our Github that we are currently setting up.

Here is the Enigma_POST sketch:

/* Enigma Development Code to Test each of the 4 Nixies, the 5 LEDs,
   then Turn On each Lamp in sequence.
   Written by Marc Tessier & James Sanderson 9/8/13
*/

// Define the 16-Segments Pins
int segment[17] = {24,22,25,31,38,36,32,30,28,26,23,27,33,35,34,29,37};
int anode[4] = {39,41,43,45};

// Define the 9 lamps Pins
int lamp[9] = {10,9,8,7,6,5,4,3,2};
int lanode[3] = {11,12,13};

//              LTP587P Segments: A,B,C,D,E,F,G,H,K,M,N,P,R,S,T,U,dp              
boolean segmentvals[39][17] = { { 0,0,0,0,1,1,0,0,1,1,1,0,1,1,1,0,1 },  // = A
                                { 0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,1 },  // = B
                                { 0,0,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1 },  // = C
                                { 0,0,0,0,0,0,1,1,1,0,1,1,1,0,1,1,1 },  // = D
                                { 0,0,1,1,0,0,0,0,1,1,1,0,1,1,1,0,1 },  // = E
                                { 0,0,1,1,1,1,0,0,1,1,1,0,1,1,1,0,1 },  // = F
                                { 0,0,1,0,0,0,0,0,1,1,1,0,1,1,1,1,1 },  // = G
                                { 1,1,0,0,1,1,0,0,1,1,1,0,1,1,1,0,1 },  // = H
                                { 0,0,1,1,0,0,1,1,1,0,1,1,1,0,1,1,1 },  // = I
                                { 1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1 },  // = J
                                { 1,1,1,1,1,1,0,0,1,1,0,1,0,1,1,0,1 },  // = K
                                { 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1 },  // = L
                                { 1,1,0,0,1,1,0,0,0,1,0,1,1,1,1,1,1 },  // = M
                                { 1,1,0,0,1,1,0,0,0,1,1,1,0,1,1,1,1 },  // = N
                                { 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1 },  // = O
                                { 0,0,0,1,1,1,0,0,1,1,1,0,1,1,1,0,1 },  // = P
                                { 0,0,0,0,0,0,0,0,1,1,1,1,0,1,1,1,1 },  // = Q
                                { 0,0,0,1,1,1,0,0,1,1,1,0,0,1,1,0,1 },  // = R
                                { 0,0,1,0,0,0,1,0,1,1,1,0,1,1,1,0,1 },  // = S
                                { 0,0,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1 },  // = T
                                { 1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1 },  // = U
                                { 1,1,1,1,1,1,0,0,1,1,0,1,1,1,0,1,1 },  // = V
                                { 1,1,0,0,1,1,0,0,1,1,1,1,0,1,0,1,1 },  // = W
                                { 1,1,1,1,1,1,1,1,0,1,0,1,0,1,0,1,1 },  // = X
                                { 1,1,1,1,1,1,1,1,0,1,0,1,1,0,1,1,1 },  // = Y
                                { 0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,1 },  // = Z
                                { 0,0,0,0,0,0,0,0,1,1,0,1,1,1,0,1,1 },  // = 0
                                { 1,1,0,0,1,1,1,1,1,1,0,1,1,1,1,1,1 },  // = 1
                                { 0,0,0,1,0,0,0,1,1,1,1,0,1,1,1,0,1 },  // = 2
                                { 0,0,0,0,0,0,1,1,1,1,1,0,1,1,1,1,1 },  // = 3
                                { 1,1,0,0,1,1,1,0,1,1,1,0,1,1,1,0,1 },  // = 4
                                { 0,0,1,0,0,0,1,0,1,1,1,0,1,1,1,0,1 },  // = 5
                                { 0,0,1,0,0,0,0,0,1,1,1,0,1,1,1,0,1 },  // = 6
                                { 0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1 },  // = 7
                                { 0,0,0,0,0,0,0,0,1,1,1,0,1,1,1,0,1 },  // = 8
                                { 0,0,0,0,0,0,1,0,1,1,1,0,1,1,1,0,1 },  // = 9
                                { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },  // = Space
                                { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },  // = Full Lit
                                { 1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1 }   // = SS
                              };
//              LTP587P Segments: A,B,C,D,E,F,G,H,K,M,N,P,R,S,T,U,dp
        
boolean lampvals[9][9] =   { { 0,1,1,1,1,1,1,1,1 },  // = Q or A or P
                             { 1,0,1,1,1,1,1,1,1 },  // = W or S or Y
                             { 1,1,0,1,1,1,1,1,1 },  // = E or D or X
                             { 1,1,1,0,1,1,1,1,1 },  // = R or F or C
                             { 1,1,1,1,0,1,1,1,1 },  // = T or G or V
                             { 1,1,1,1,1,0,1,1,1 },  // = Z or H or B
                             { 1,1,1,1,1,1,0,1,1 },  // = U or J or N
                             { 1,1,1,1,1,1,1,0,1 },  // = I or K or M
                             { 1,1,1,1,1,1,1,1,0 }   // = O or L
                            };

int value_row1 = 0;
int value_row2 = 0;
int value_row3 = 0;
char key = 91;

int led1 = 40;
int led2 = 42;
int led3 = 44;
int led4 = 46;
int led5 = 48;
int wait = 100;



void setup() {
  for (int index = 0 ; index <= 3; index++) {
    pinMode (anode[index], OUTPUT);
    digitalWrite (anode[index], 1);
  }
  for (int index = 0 ; index <= 16; index++) {
    pinMode (segment[index], OUTPUT);
    digitalWrite (segment[index], 1);
  } 
  // initialize the digital pins as an output.
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(led5, OUTPUT);
  for (int index = 0 ; index <= 2; index++) {
    pinMode (lanode[index], OUTPUT);
    digitalWrite (lanode[index], 1);
  }
  for (int index = 0 ; index <= 8; index++) {
    pinMode (lamp[index], OUTPUT);
    digitalWrite (lamp[index], 1);
  }
}

void loop() {
   sixteenSegWrite(0, 38);
   sixteenSegWrite(1, 38);
   sixteenSegWrite(2, 38);
   sixteenSegWrite(3, 38);
  
  digitalWrite(led1, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(200);               // wait for a second
  digitalWrite(led1, LOW);    // turn the LED off by making the voltage LOW
  delay(wait);               // wait for a second
  digitalWrite(led2, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(200);               // wait for a second
  digitalWrite(led2, LOW);    // turn the LED off by making the voltage LOW
  delay(wait);               // wait for a second
  digitalWrite(led3, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(200);               // wait for a second
  digitalWrite(led3, LOW);    // turn the LED off by making the voltage LOW
  delay(wait);               // wait for a second
  digitalWrite(led4, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(200);               // wait for a second
  digitalWrite(led4, LOW);    // turn the LED off by making the voltage LOW
  delay(wait);               // wait for a second
  digitalWrite(led5, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(200);               // wait for a second
  digitalWrite(led5, LOW);    // turn the LED off by making the voltage LOW
  delay(wait);               // wait for a second

for (int index = 0 ; index <= 2; index++) {
   digitalWrite (lanode[index], 0);
   for (int mychar = 0; mychar < 9; mychar++) {
      for (int sindex = 0; sindex < 9; sindex++) {
         digitalWrite(lamp[sindex], lampvals[mychar][sindex]);
         delay (30);
      }
  }
  digitalWrite (lanode[index], 1);
}
}

void sixteenSegWrite(int digit, int character) {
  digitalWrite(anode[digit],0);
  for (int index = 0; index < 17; index++) {
  digitalWrite(segment[index], segmentvals[character][index]);
  }
}

Step 8: More Software!

Picture of More Software!
So we first created a function for each mode the Enigma operates in:
In Mode 0, Default Mode, the Enigma is nothing but a simple typewriter with a Marquee that displays its Model Number.
Mode 1 allows the user to select the 3 (out of 8) Rotors he will use along with which one (of the 2) Reflector he wants to use.
In Mode 2, the user can select the Internal position of each Rotor.
Mode 3 is used to specify the starting (external) position of each Rotor.
In Mode 4, a user can enter up to 10 Swapped pairs of letters.
Mode 5 is Run mode and at that point, the Enigma will encrypt or decrypt any letter typed on the keyboard.

Here is the Complete sketch that runs the whole Enigma:

/* S&T GeoTronics Enigma Code. This Arduino Mega custom shield is programmed to replicate
   exactly the behavior of a true German M4 Enigma machine.
   It uses 4 16-Segment units, 5 LEDs, 26 Lamps setup as keyboard, 26 keyboard buttons
   & 10 Function keys. The 115 light emitting diodes are charlie-plexed to minimize the
   amount of pins needed down to 38 and all 36 pushbuttons keys are sharing a total of 4 pins.
   Designed, assembled & programmed by Marc Tessier & James Sanderson 9/20/13
*/
// Define the variables
unsigned long time = millis();
unsigned long otime = time;
int inpin[4] = {A0, A1, A2, A3};
int inval[4] = {0, 0, 0, 0};
int keyval = 100;
boolean windex = 0;
boolean windex1 = 0;
boolean windex2 = 0;
int lampval = 100;
int procesval = 0;
int procesvala = 0;
int mode = 0;
unsigned long mtime;
int mdex =0;

// Define each Nixie character
int dig1 = 37;
int dig2 = 37;
int dig3 = 37;
int dig4 = 37;

int data[36] = {36,36,36,36,18,39,19,36,6,4,14,19,17,14,13,8,2,18,36,4,13,8,6,12,0,36,12,0,17,10,36,30,36,36,36,36} ;

// Define the 16-Segments Pins as 2 Arrays
int segment[17] = {24,22,25,31,38,36,32,30,28,26,23,27,33,35,34,29,37}; //cathode array
int anode[4] = {39,41,43,45}; //annode array commin annode

// Define the 26 Lamps as a 2D Array
int lamparray[26] [2] = {{12,10},{13,5},{13,7},{12,8},{11,8},{12,7,},{12,6},{12,5},{11,3},{12,4},
                         {12,3},{13,2},{13,3},{13,4},{11,2},{13,10},{11,10},{11,7},{12,9},{11,6},
                         {11,4},{13,6},{11,9},{13,8},{13,9},{11,5}};

//  Define the 12 Lamp Pins for initialization
int lamppin[12] = {2,3,4,5,6,7,8,9,10,11,12,13}; //2 to 10 cathode, 11 to 13 common annode

// Define each LTP587P Segments: A,B,C,D,E,F,G,H,K,M,N,P,R,S,T,U,dp              
boolean segmentvals[40][17] = { { 0,0,0,0,1,1,0,0,1,1,1,0,1,1,1,0,1 },  // = A 0
                                { 0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,1 },  // = B 1
                                { 0,0,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1 },  // = C 2
                                { 0,0,0,0,0,0,1,1,1,0,1,1,1,0,1,1,1 },  // = D 3
                                { 0,0,1,1,0,0,0,0,1,1,1,0,1,1,1,0,1 },  // = E 4
                                { 0,0,1,1,1,1,0,0,1,1,1,0,1,1,1,0,1 },  // = F 5
                                { 0,0,1,0,0,0,0,0,1,1,1,0,1,1,1,1,1 },  // = G 6
                                { 1,1,0,0,1,1,0,0,1,1,1,0,1,1,1,0,1 },  // = H 7
                                { 0,0,1,1,0,0,1,1,1,0,1,1,1,0,1,1,1 },  // = I 8
                                { 1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1 },  // = J 9
                                { 1,1,1,1,1,1,0,0,1,1,0,1,0,1,1,0,1 },  // = K 10
                                { 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1 },  // = L 11
                                { 1,1,0,0,1,1,0,0,0,1,0,1,1,1,1,1,1 },  // = M 12
                                { 1,1,0,0,1,1,0,0,0,1,1,1,0,1,1,1,1 },  // = N 13
                                { 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1 },  // = O 14
                                { 0,0,0,1,1,1,0,0,1,1,1,0,1,1,1,0,1 },  // = P 15
                                { 0,0,0,0,0,0,0,0,1,1,1,1,0,1,1,1,1 },  // = Q 16
                                { 0,0,0,1,1,1,0,0,1,1,1,0,0,1,1,0,1 },  // = R 17
                                { 0,0,1,0,0,0,1,0,1,1,1,0,1,1,1,0,1 },  // = S 18
                                { 0,0,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1 },  // = T 19
                                { 1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1 },  // = U 20
                                { 1,1,1,1,1,1,0,0,1,1,0,1,1,1,0,1,1 },  // = V 21
                                { 1,1,0,0,1,1,0,0,1,1,1,1,0,1,0,1,1 },  // = W 22
                                { 1,1,1,1,1,1,1,1,0,1,0,1,0,1,0,1,1 },  // = X 23
                                { 1,1,1,1,1,1,1,1,0,1,0,1,1,0,1,1,1 },  // = Y 24
                                { 0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,1 },  // = Z 25
                                { 0,0,0,0,0,0,0,0,1,1,0,1,1,1,0,1,1 },  // = 0 26
                                { 1,1,0,0,1,1,1,1,1,1,0,1,1,1,1,1,1 },  // = 1 27
                                { 0,0,0,1,0,0,0,1,1,1,1,0,1,1,1,0,1 },  // = 2 28
                                { 0,0,0,0,0,0,1,1,1,1,1,0,1,1,1,1,1 },  // = 3 29
                                { 1,1,0,0,1,1,1,0,1,1,1,0,1,1,1,0,1 },  // = 4 30
                                { 0,0,1,0,0,0,1,0,1,1,1,0,1,1,1,0,1 },  // = 5 31
                                { 0,0,1,0,0,0,0,0,1,1,1,0,1,1,1,0,1 },  // = 6 32
                                { 0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1 },  // = 7 33
                                { 0,0,0,0,0,0,0,0,1,1,1,0,1,1,1,0,1 },  // = 8 34
                                { 0,0,0,0,0,0,1,0,1,1,1,0,1,1,1,0,1 },  // = 9 35
                                { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },  // = Space 36
                                { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },  // = Full Lit 37
                                { 1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1 },  // = SS 38
                                { 0,1,1,1,0,0,0,1,0,0,1,1,0,1,1,0,1} }; // = & 39
//              LTP587P Segments: A,B,C,D,E,F,G,H,K,M,N,P,R,S,T,U,dp

// Define the 5 Mode LEDs
int led1 = 40;
int led2 = 42;
int led3 = 44;
int led4 = 46;
int led5 = 48;

                                      //4,10,12, 5,11, 6, 3,16,21,25,13,19,14,22,24, 7,23,20,18,15, 0, 8, 1,17, 2, 9
//Define the rotor values                 A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q
static const int rotorvals[12][78] = { {  4,10,12, 5,11, 6, 3,16,21,25,13,19,14,22,24, 7,123,20,18,15, 0, 8, 1,17, 2, 9,
                                         4,10,12, 5,11, 6, 3,16,21,25,13,19,14,22,24, 7,123,20,18,15, 0, 8, 1,17, 2, 9,
                                         4,10,12, 5,11, 6, 3,16,21,25,13,19,14,22,24, 7,123,20,18,15, 0, 8, 1,17, 2, 9 },  // wheel 1

                                       {  0, 9, 3,10,118, 8,17,20,23, 1,11, 7,22,19,12, 2,16, 6,25,13,15,24, 5,21,14, 4,
                                          0, 9, 3,10,118, 8,17,20,23, 1,11, 7,22,19,12, 2,16, 6,25,13,15,24, 5,21,14, 4,
                                          0, 9, 3,10,118, 8,17,20,23, 1,11, 7,22,19,12, 2,16, 6,25,13,15,24, 5,21,14, 4 },  // wheel 2
                                        
                                       {  1, 3, 5, 7, 9,11, 2,15,17,19,23,21,25,13,24, 4, 8,22, 6, 0,10,112,20,18,16,14,
                                          1, 3, 5, 7, 9,11, 2,15,17,19,23,21,25,13,24, 4, 8,22, 6, 0,10,112,20,18,16,14,
                                          1, 3, 5, 7, 9,11, 2,15,17,19,23,21,25,13,24, 4, 8,22, 6, 0,10,112,20,18,16,14 },  // wheel 3
                                        
                                       {  4,18,14,21,15,25, 9, 0,24,116,20, 8,17, 7,23,11,13, 5,19, 6,10, 3, 2,12,22, 1,
                                          4,18,14,21,15,25, 9, 0,24,116,20, 8,17, 7,23,11,13, 5,19, 6,10, 3, 2,12,22, 1,
                                          4,18,14,21,15,25, 9, 0,24,116,20, 8,17, 7,23,11,13, 5,19, 6,10, 3, 2,12,22, 1 },  // wheel 4
                                          
                                       { 21,25, 1,17, 6, 8,19,24,20,15,18, 3,13, 7,11,23, 0,22,12, 9,16,14, 5, 4, 2,110,
                                         21,25, 1,17, 6, 8,19,24,20,15,18, 3,13, 7,11,23, 0,22,12, 9,16,14, 5, 4, 2,110,
                                         21,25, 1,17, 6, 8,19,24,20,15,18, 3,13, 7,11,23, 0,22,12, 9,16,14, 5, 4, 2,110  },  // wheel 5
                                        
                                       {  9,15, 6,21,14,20,12, 5,24,16, 1, 4,113, 7,25,17, 3,10, 0,18,23,11, 8, 2,19,122,
                                          9,15, 6,21,14,20,12, 5,24,16, 1, 4,113, 7,25,17, 3,10, 0,18,23,11, 8, 2,19,122,
                                          9,15, 6,21,14,20,12, 5,24,16, 1, 4,113, 7,25,17, 3,10, 0,18,23,11, 8, 2,19,122 },  // wheel 6
                                         
                                       { 13,25, 9, 7, 6,17, 2,23,12,24,18,22,101,14,20, 5, 0, 8,21,11,15, 4,10,16, 3,119,
                                         13,25, 9, 7, 6,17, 2,23,12,24,18,22,101,14,20, 5, 0, 8,21,11,15, 4,10,16, 3,119,
                                         13,25, 9, 7, 6,17, 2,23,12,24,18,22,101,14,20, 5, 0, 8,21,11,15, 4,10,16, 3,119 },  // wheel 7
                                        
                                       { 5,10,16, 7,19,11,23,14, 2, 1, 9,18,115, 3,25,17, 0,12, 4,22,13, 8,20,24, 6,121,
                                         5,10,16, 7,19,11,23,14, 2, 1, 9,18,115, 3,25,17, 0,12, 4,22,13, 8,20,24, 6,121,
                                         5,10,16, 7,19,11,23,14, 2, 1, 9,18,115, 3,25,17, 0,12, 4,22,13, 8,20,24, 6,121 },    // wheel 8
                                        
                                       { 11,4,24,9,21,2,13,8,23,22,15,1,16,12,3,17,19,0,10,25,6,5,20,7,14,18,
                                         11,4,24,9,21,2,13,8,23,22,15,1,16,12,3,17,19,0,10,25,6,5,20,7,14,18,
                                         11,4,24,9,21,2,13,8,23,22,15,1,16,12,3,17,19,0,10,25,6,5,20,7,14,18 },    // Beta
                                        
                                       { 5,18,14,10,0,13,20,4,17,7,12,1,19,8,24,2,22,11,16,15,25,23,21,6,9,3,
                                         5,18,14,10,0,13,20,4,17,7,12,1,19,8,24,2,22,11,16,15,25,23,21,6,9,3,
                                         5,18,14,10,0,13,20,4,17,7,12,1,19,8,24,2,22,11,16,15,25,23,21,6,9,3 },    // Gamma
                                        
                                       { 4,13,10,16,0,20,24,22,9,8,2,14,15,1,11,12,3,23,25,21,5,19,7,17,6,18,
                                         4,13,10,16,0,20,24,22,9,8,2,14,15,1,11,12,3,23,25,21,5,19,7,17,6,18,
                                         4,13,10,16,0,20,24,22,9,8,2,14,15,1,11,12,3,23,25,21,5,19,7,17,6,18},    // = UKW-B
                                        
                                       { 17,3,14,1,9,13,19,10,21,4,7,12,11,5,2,22,25,0,23,6,24,8,15,18,20,16,
                                         17,3,14,1,9,13,19,10,21,4,7,12,11,5,2,22,25,0,23,6,24,8,15,18,20,16,
                                         17,3,14,1,9,13,19,10,21,4,7,12,11,5,2,22,25,0,23,6,24,8,15,18,20,16 }    // = UKW-C
                                        };
                                       
                                   
static const int rotorvali[10][78] = { { 20,22,24, 6, 0, 3, 5,15,21,25, 1, 4, 2,10,12,19, 7,23,18,11,17, 8,13,16,14, 9,
                                         20,22,24, 6, 0, 3, 5,15,21,25, 1, 4, 2,10,12,19, 7,23,18,11,17, 8,13,16,14, 9,
                                         20,22,24, 6, 0, 3, 5,15,21,25, 1, 4, 2,10,12,19, 7,23,18,11,17, 8,13,16,14, 9  },  //wheel 1 i
//                                  
                                      {  0, 9,15, 2,25,22,17,11, 5, 1, 3,10,14,19,24,20,16, 6, 4,13, 7,23,12, 8,21,18,
                                         0, 9,15, 2,25,22,17,11, 5, 1, 3,10,14,19,24,20,16, 6, 4,13, 7,23,12, 8,21,18,
                                         0, 9,15, 2,25,22,17,11, 5, 1, 3,10,14,19,24,20,16, 6, 4,13, 7,23,12, 8,21,18  },  //wheel 2 i
                                       
                                      { 19, 0, 6, 1,15, 2,18, 3,16, 4,20, 5,21,13,25, 7,24, 8,23, 9,22,11,17,10,14,12,
                                        19, 0, 6, 1,15, 2,18, 3,16, 4,20, 5,21,13,25, 7,24, 8,23, 9,22,11,17,10,14,12,
                                        19, 0, 6, 1,15, 2,18, 3,16, 4,20, 5,21,13,25, 7,24, 8,23, 9,22,11,17,10,14,12 },  //wheel 3 i
                                       
                                       
                                       { 7,25,22,21, 0,17,19,13,11, 6,20,15,23,16, 2, 4, 9,12, 1,18,10, 3,24,14, 8, 5,
                                         7,25,22,21, 0,17,19,13,11, 6,20,15,23,16, 2, 4, 9,12, 1,18,10, 3,24,14, 8, 5,
                                         7,25,22,21, 0,17,19,13,11, 6,20,15,23,16, 2, 4, 9,12, 1,18,10, 3,24,14, 8, 5 },  //wheel 4 i
                                        
                                       { 16, 2,24,11,23,22, 4,13, 5,19,25,14,18,12,21, 9,20, 3,10, 6, 8, 0,17,15, 7, 1,
                                         16, 2,24,11,23,22, 4,13, 5,19,25,14,18,12,21, 9,20, 3,10, 6, 8, 0,17,15, 7, 1,
                                         16, 2,24,11,23,22, 4,13, 5,19,25,14,18,12,21, 9,20, 3,10, 6, 8, 0,17,15, 7, 1 },  //wheel 5 i
                                        
                                       { 18,10,23,16,11, 7, 2,13,22, 0,17,21,06,12, 4, 1, 9,15,19,24, 5, 3, 25,20, 8,14,
                                         18,10,23,16,11, 7, 2,13,22, 0,17,21,06,12, 4, 1, 9,15,19,24, 5, 3, 25,20, 8,14,
                                         18,10,23,16,11, 7, 2,13,22, 0,17,21,06,12, 4, 1, 9,15,19,24, 5, 3, 25,20, 8,14 },  //wheel 6 i
                                    
                                       { 16,12,6,24,21,15,4,3,17,2,22,19,8,0,13,20,23,5,10,25,14,18,11,7,9,1,
                                         16,12,6,24,21,15,4,3,17,2,22,19,8,0,13,20,23,5,10,25,14,18,11,7,9,1,
                                         16,12,6,24,21,15,4,3,17,2,22,19,8,0,13,20,23,5,10,25,14,18,11,7,9,1 },  //wheel 7 i
                                       
                                       { 16,9,8,13,18,0,24,3,21,10,1,5,17,20,7,12,2,15,11,4,22,25,19,6,23,14,
                                         16,9,8,13,18,0,24,3,21,10,1,5,17,20,7,12,2,15,11,4,22,25,19,6,23,14,
                                         16,9,8,13,18,0,24,3,21,10,1,5,17,20,7,12,2,15,11,4,22,25,19,6,23,14 },   //wheel 8 i
                                        
                                       { 17,11,5,14,1,21,20,23,7,3,18,0,13,6,24,10,12,15,25,16,22,4,9,8,2,19,
                                         17,11,5,14,1,21,20,23,7,3,18,0,13,6,24,10,12,15,25,16,22,4,9,8,2,19,
                                         17,11,5,14,1,21,20,23,7,3,18,0,13,6,24,10,12,15,25,16,22,4,9,8,2,19 },   //Beta i
                                        
                                       { 4,11,15,25,7,0,23,9,13,24,3,17,10,5,2,19,18,8,1,12,6,22,16,21,14,20,
                                         4,11,15,25,7,0,23,9,13,24,3,17,10,5,2,19,18,8,1,12,6,22,16,21,14,20,
                                         4,11,15,25,7,0,23,9,13,24,3,17,10,5,2,19,18,8,1,12,6,22,16,21,14,20 } }; //Gamma i
                                                                               
                                       
// Define a 2D Array for keeping the wheel locations & positions
int wheel[3][3] = {{26,0,0},{26,0,0},{26,0,0}};
int reflect[2] = {1,0};

// Define Array for plugbord values 25 x2 position 0 holds use position 1 holds value int plugu holds the total nomber of plugs used (10 max)
int plugval [2][26] = {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
                       {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25}};
int pluguse = 0; int paindex = 0; int pbindex = 1;


void setup() {
// Initialize all 38 LED pins as Output 
  for (int index = 0; index <= 11; index++) {
    pinMode(lamppin[index], OUTPUT);
    digitalWrite(lamppin[index],1);
  }
  for (int index = 0 ; index <= 3; index++) {
    pinMode (anode[index], OUTPUT);
    digitalWrite (anode[index], 1);
  }
  for (int index = 0 ; index <= 16; index++) {
    pinMode (segment[index], OUTPUT);
    digitalWrite (segment[index], 1);
  } 
  pinMode(led1,OUTPUT);
  pinMode(led2,OUTPUT);
  pinMode(led3,OUTPUT);
  pinMode(led4,OUTPUT);
  pinMode(led5,OUTPUT);
 
// Serial.begin(9600);
// Initialize all 4 pusbutton pins as Input   
  for (int index = 0; index <= 3; index++) {
    pinMode(inpin[index], INPUT);
  }

}

void loop() {
// Keyboard debounce & test for new key pressed 
  time = millis();
  if (time > otime + 500) {keyval = readkbde();}
  if((keyval == 45) && (windex ==1)) {modeselect();}
// The whole Enigma machine operation revolves around which Operating Mode is current 
  if(mode == 0) {mode0();}
  else if(mode == 1) {mode1();}
  else if(mode == 2) {mode2();}
  else if(mode == 3) {mode3();}
  else if(mode == 4) {mode4();}
  else if(mode == 5) {mode5();}
  else {    }

//Serial.println(keyval); // for debuging prints keybord value to serial monitor// for run or del

}

// This function takes care of figuring out which key has been pressed & returns a unique Integer
int readkbde() {
int kval = 100;
for (int index = 0; index <= 3; index++) { inval[index] = analogRead(inpin[index]);   } //Reads analog input values
if((inval[0] > 925) && (inval[1] > 828) && (inval[2] > 730) && (inval[3] > 828))  {kval = 100;} // no key press
else if((inval[0] < 924) && (inval[0] > 915)) {kval = 49;} //up arrow 4
else if((inval[0] < 914) && (inval[0] > 903)) {kval = 48;} //up arrow 3
else if((inval[0] < 902) && (inval[0] > 887)) {kval = 47;} //up arrow 2
else if((inval[0] < 886) && (inval[0] > 865)) {kval = 46;} //up arrow 1
else if((inval[0] < 864) && (inval[0] > 836)) {kval = 45;} //mode
else if((inval[0] < 834) && (inval[0] > 793)) {kval = 44;} //enter
else if((inval[0] < 792) && (inval[0] > 724)) {kval = 43;}
else if((inval[0] < 723) && (inval[0] > 594)) {kval = 42;}
else if((inval[0] < 593) && (inval[0] > 260)) {kval = 41;}
else if(inval[0] < 259 ) {kval = 40;}
else if((inval[1] < 827) && (inval[1] > 807)) {kval = 14;}
else if((inval[1] < 806) && (inval[1] > 781)) {kval = 8;}
else if((inval[1] < 780) && (inval[1] > 749)) {kval = 20;}
else if((inval[1] < 748) && (inval[1] > 706)) {kval = 25;}
else if((inval[1] < 705) && (inval[1] > 647)) {kval = 19;}
else if((inval[1] < 646) && (inval[1] > 555)) {kval = 17;}
else if((inval[1] < 554) && (inval[1] > 418)) {kval = 4;}
else if((inval[1] < 417) && (inval[1] > 169)) {kval = 22;}
else if(inval[1] < 168 ) {kval = 16;}
else if((inval[2] < 729) && (inval[2] > 699)) {kval = 10;}
else if((inval[2] < 698) && (inval[2] > 660)) {kval = 9;}
else if((inval[2] < 659) && (inval[2] > 611)) {kval = 7;}
else if((inval[2] < 610) && (inval[2] > 547)) {kval = 6;}
else if((inval[2] < 546) && (inval[2] > 455)) {kval = 5;}
else if((inval[2] < 454) && (inval[2] > 331)) {kval = 3;}
else if((inval[2] < 330) && (inval[2] > 127)) {kval = 18;}
else if(inval[2] < 126 ) {kval = 0;}
else if((inval[3] < 827) && (inval[3] > 807)) {kval = 11;}
else if((inval[3] < 806) && (inval[3] > 781)) {kval = 12;}
else if((inval[3] < 780) && (inval[3] > 749)) {kval = 13;}
else if((inval[3] < 748) && (inval[3] > 706)) {kval = 1;}
else if((inval[3] < 705) && (inval[3] > 647)) {kval = 21;}
else if((inval[3] < 646) && (inval[3] > 555)) {kval = 2;}
else if((inval[3] < 554) && (inval[3] > 418)) {kval = 23;}
else if((inval[3] < 417) && (inval[3] > 169)) {kval = 24;}
else if(inval[3] < 169 ) {kval = 15;}
else {kval = 100;}
if(kval < 99) {otime = millis();}              //Starts key debounce timer
if((kval >= 0) && (kval <= 99)) {windex = 1;}  //windex showing true (1) indicates the return of a fresh key stroke
return kval;
}

// Function to change operating Mode
void modeselect() {
  mode++;
  if(mode >=6) {mode = 0;}
  windex = 0;
}

// Default Mode: Enigma is a Typewriter
void mode0() {
  if((keyval >= 0) && (keyval <= 25)) {lampval = keyval;}
  lampita();
  marquee();
  lampitb();
  }

// Select the Rotors & the Reflector 
  void mode1() {
    int index;
    digitalWrite(led1, HIGH);
    if(windex == 1) {if((keyval == 43) || (keyval == 46)) {reflect[0]++; if (reflect[0] > 2) {reflect[0] = 1;}  windex = 0;}}
    if(windex == 1) {if(keyval == 47) { for(index = wheel[2][0];(index == wheel[1][0]) || (index == wheel[0][0]) || (index == wheel[2][0]);
                        index++) {if(index > 33) {index = 26;} }wheel[2][0] = index;  windex = 0;}}
    if(windex == 1) {if(keyval == 48) { for(index = wheel[1][0];(index == wheel[2][0]) || (index == wheel[0][0]) || (index == wheel[1][0]);
                        index++) {if(index > 33) {index = 26;} }wheel[1][0] = index;  windex = 0;}}
    if(windex == 1) {if(keyval == 49) { for(index = wheel[0][0];(index == wheel[2][0]) || (index == wheel[1][0]) || (index == wheel[0][0]);
                        index++) {if(index > 33) {index = 26;} }wheel[0][0] = index;  windex = 0;}}
    if(windex == 1) {if(keyval == 42) { for(index = wheel[2][0];(index == wheel[1][0]) || (index == wheel[0][0]) || (index == wheel[2][0]);
                        index--) {if(index < 28) {index = 35;} }wheel[2][0] = index;  windex = 0;}}
    if(windex == 1) {if(keyval == 41) { for(index = wheel[1][0];(index == wheel[2][0]) || (index == wheel[0][0]) || (index == wheel[1][0]);
                        index--) {if(index < 28) {index = 35;} }wheel[1][0] = index;  windex = 0;}}
    if(windex == 1) {if(keyval == 40) { for(index = wheel[0][0];(index == wheel[2][0]) || (index == wheel[1][0]) || (index == wheel[0][0]);
                        index--) {if(index < 28) {index = 35;} }wheel[0][0] = index;  windex = 0;}}
    dig2 = wheel[2][0];  dig3 = wheel[1][0]; dig4 = wheel[0][0]; dig1 = reflect[0];               
    nixisend();
    dig1 =37; dig2 = 37; dig3 = 37; dig4 = 37;
    digitalWrite(led1, LOW);
  }

// Position the Inner setting of each Rotor 
  void mode2() {
    digitalWrite(led2, HIGH);
    if(windex == 1){
      if(keyval == 47) {wheel[2][1]++; if(wheel[2][1] > 25) {wheel[2][1] = 0;}}
      if(keyval == 48) {wheel[1][1]++; if(wheel[1][1] > 25) {wheel[1][1] = 0;}}
      if(keyval == 49) {wheel[0][1]++; if(wheel[0][1] > 25) {wheel[0][1] = 0;}}
      if(keyval == 42) {wheel[2][1]--; if(wheel[2][1] < 0) {wheel[2][1] = 25;}}
      if(keyval == 41) {wheel[1][1]--; if(wheel[1][1] < 0) {wheel[1][1] = 25;}}
      if(keyval == 40) {wheel[0][1]--; if(wheel[0][1] < 0) {wheel[0][1] = 25;}}
      windex = 0; }
   
    dig2 = wheel[2][1];  dig3 = wheel[1][1]; dig4 = wheel[0][1]; dig1 = 0;
    nixisend();
    dig1 =37; dig2 = 37; dig3 = 37; dig4 = 37;
    digitalWrite(led2, LOW);
  }

// Position the Start character of each Wheel 
  void mode3() {
    digitalWrite(led3, HIGH);
    if(windex == 1){
      if(keyval == 46) {reflect[1]++; if(reflect[1] > 25) {reflect[1] = 0;}}
      if(keyval == 47) {wheel[2][2]++; if(wheel[2][2] > 25) {wheel[2][2] = 0;}}
      if(keyval == 48) {wheel[1][2]++; if(wheel[1][2] > 25) {wheel[1][2] = 0;}}
      if(keyval == 49) {wheel[0][2]++; if(wheel[0][2] > 25) {wheel[0][2] = 0;}}
      if(keyval == 43) {reflect[1]--; if(reflect[1] < 0) {reflect[1] = 25;}}
      if(keyval == 42) {wheel[2][2]--; if(wheel[2][2] < 0) {wheel[2][2] = 25;}}
      if(keyval == 41) {wheel[1][2]--; if(wheel[1][2] < 0) {wheel[1][2] = 25;}}
      if(keyval == 40) {wheel[0][2]--; if(wheel[0][2] < 0) {wheel[0][2] = 25;}}
      windex = 0; }
   
    dig2 = wheel[2][2];  dig3 = wheel[1][2]; dig4 = wheel[0][2]; dig1 = reflect[1];
    nixisend();
    dig1 =37; dig2 = 37; dig3 = 37; dig4 = 37;
    digitalWrite(led3, LOW);
  }

// Define the Plugboard pairs 
  void mode4() {
    int index = 0;
    digitalWrite(led4, HIGH);
    if(pluguse <= 9) {
    if(plugval[0][paindex] == 1) {for(index = paindex;(index == paindex) || (index == pbindex) || (plugval[0][index] == 1); index++) {if(index > 24) {index = -1;}} paindex = index;}
    if(plugval[0][pbindex] == 1) {for(index = pbindex;(index == pbindex) || (index == paindex) || (plugval[0][index] == 1); index++) {if(index > 24) {index = -1;}} pbindex = index;}
    if(windex == 1)  {
    if(keyval == 46) { for(index = paindex;(index == paindex) || (index == pbindex) || (plugval[0][index] == 1); index++) {if(index > 24) {index = -1;}} paindex = index; windex = 0; }
    if(keyval == 43) { for(index = paindex;(index == paindex) || (index == pbindex) || (plugval[0][index] == 1); index--) {if(index < 1) {index = 26;}} paindex = index; windex = 0;  }
    if(keyval == 49) { for(index = pbindex;(index == pbindex) || (index == paindex) || (plugval[0][index] == 1); index++) {if(index > 24) {index = -1;}} pbindex = index; windex = 0; }
    if(keyval == 40) { for(index = pbindex;(index == pbindex) || (index == paindex) || (plugval[0][index] == 1); index--) {if(index < 1) {index = 26;}} pbindex = index; windex = 0;  }
    if(keyval == 44) { plugval[0][paindex] = 1; plugval[1][paindex] = pbindex; plugval[0][pbindex] = 1; plugval[1][pbindex] = paindex; windex = 0; pluguse++;}
    }
    dig2 = 19; dig3 = 14; dig4 = pbindex; dig1 = paindex;
    nixisend();
    dig1 =37; dig2 = 37; dig3 = 37; dig4 = 37;
      }
      else {done();}
    digitalWrite(led4, LOW);
  }

// This is Normal Operation Mode to Encrypt/Decrypt 
  void mode5() {
    int pv = 0;
    digitalWrite(led5, HIGH);
   
    if((keyval >= 0) && (keyval <= 25)) {  if(windex == 1){procesvala = keyval;  indexwheels();}}
    windex = 0;
    procesval = procesvala;
    procesval = plugval[1][procesval];
   // Serial.print (procesval); Serial.print("   ");
   
    pv = (procesval + (wheel[0][2] - wheel[0][1]));
    if(pv < 0) {pv = pv + 26;}
    procesval = rotorvals[wheel[0][0] -27][pv];
    if(procesval >= 100) {procesval = procesval - 100;}
    procesval = (procesval - (wheel[0][2] - wheel[0][1]));
    if(procesval < 0) {procesval = procesval + 26;}if(procesval > 25) {procesval = procesval - 26;}
  //  Serial.print (procesval); Serial.print("   ");
   
    pv = (procesval + (wheel[1][2] - wheel[1][1]));
    if(pv < 0) {pv = pv + 26;}
    procesval = rotorvals[wheel[1][0] -27][pv];
    if(procesval >= 100) {procesval = procesval - 100;}
    procesval = (procesval - (wheel[1][2] - wheel[1][1]));
    if(procesval < 0) {procesval = procesval + 26;}if(procesval > 25) {procesval = procesval - 26;}
   // Serial.print (procesval); Serial.print("   ");
   
    pv = (procesval + (wheel[2][2] - wheel[2][1]));
    if(pv < 0) {pv = pv + 26;}
    procesval = rotorvals[wheel[2][0] -27][pv];
    if(procesval >= 100) {procesval = procesval - 100;}
    procesval = (procesval - (wheel[2][2] - wheel[2][1]));
    if(procesval < 0) {procesval = procesval + 26;}if(procesval > 25) {procesval = procesval - 26;}
   // Serial.print (procesval); Serial.print("   ");
  
    pv = (procesval );
    procesval = rotorvals[reflect[0] + 7][pv];
    if(procesval >= 100) {procesval = procesval - 100;}
    if(procesval < 0) {procesval = procesval + 26;}if(procesval > 25) {procesval = procesval - 26;}
    //Serial.print (procesval); Serial.print("   ");
  
    procesval = rotorvals[reflect[0] + 9][procesval];
    //Serial.print (procesval); Serial.print("   ");
  
    pv = (procesval +26);
    procesval = rotorvali[reflect[0] + 7][pv];
    if(procesval >= 100) {procesval = procesval - 100;}
    if(procesval < 0) {procesval = procesval + 26;}if(procesval > 25) {procesval = procesval - 26;}
  // Serial.print (procesval); Serial.print("   ");
 
    pv = (procesval + (wheel[2][2] - wheel[2][1]));
    if(pv < 0) {pv = pv + 26;}
    procesval = rotorvali[wheel[2][0] -27][pv];
    if(procesval >= 100) {procesval = procesval - 100;}
    procesval = (procesval - (wheel[2][2] - wheel[2][1]));
    if(procesval < 0) {procesval = procesval + 26;}if(procesval > 25) {procesval = procesval - 26;}
   //Serial.print (procesval); Serial.print("   ");
 
    pv = (procesval + (wheel[1][2] - wheel[1][1]));
    if(pv < 0) {pv = pv + 26;}
    procesval = rotorvali[wheel[1][0] -27][pv];
    if(procesval >= 100) {procesval = procesval - 100;}
    procesval = (procesval - (wheel[1][2] - wheel[1][1]));
    if(procesval < 0) {procesval = procesval + 26;}if(procesval > 25) {procesval = procesval - 26;}
   //Serial.print (procesval); Serial.print("   ");
  
    pv = (procesval + (wheel[0][2] - wheel[0][1]));
    if(pv < 0) {pv = pv + 26;}
    procesval = rotorvali[wheel[0][0] -27][pv];
    if(procesval >= 100) {procesval = procesval - 100;}
    procesval = (procesval - (wheel[0][2] - wheel[0][1]));
    if(procesval < 0) {procesval = procesval + 26;}if(procesval > 25) {procesval = procesval - 26;}
  
   // Serial.print (procesval); Serial.print("   ");
  
    procesval = plugval[1][procesval];
  
    lampval = procesval;
    //Serial.println(lampval);
    dig2 = wheel[2][2];  dig3 = wheel[1][2]; dig4 = wheel[0][2]; dig1 = reflect[1];
    lampita();
    nixisend();
    lampitb();
    dig1 =37; dig2 = 37; dig3 = 37; dig4 = 37;
    digitalWrite(led5, LOW);
  }

// Helper Function to light the proper key
void lampita() {
   digitalWrite(lamparray[lampval][0],0);
   digitalWrite(lamparray[lampval][1],0);
}
void lampitb(){
   digitalWrite(lamparray[lampval][0],1);
   digitalWrite(lamparray[lampval][1],1); 
}

// Help Function to illuminate "Nixies"
void nixisend() {
sixteenSegWrite(0, dig1);
sixteenSegWrite(1, dig2);
sixteenSegWrite(2, dig3);
sixteenSegWrite(3, dig4);
}

void marquee() {
 
time = millis();
if( mtime < time) {
   mtime = time + 400;
mdex++;}
dig1 = data[mdex];
dig2 = data[mdex + 1];
dig3 = data[mdex + 2];
dig4 = data[mdex + 3];
if (mdex >= 31) {mdex = 0;}
nixisend();

}
// Function that actually turns on each of 17 appropriate segments on each "Nixie"
void sixteenSegWrite(int digit, int character) {
  digitalWrite(anode[digit],0);
  for (int index = 0; index < 17; index++) {
  digitalWrite(segment[index], segmentvals[character][index]);
  }
  delay(7);
  for (int index =0; index <= 16; index++) {
    digitalWrite(segment[index], 1);
  }
  digitalWrite(anode[digit], 1);
  }

  void done() {
    dig1 = 3; dig2 = 14; dig3 = 13; dig4 = 4;
    nixisend();
    dig1 =37; dig2 = 37; dig3 = 37; dig4 = 37;
    }
   
  void indexwheels() {
   // Serial.print(rotorvals[wheel[0][0]-27][wheel[0][2]]);
   // Serial.print("    "); Serial.print(wheel[0][0]-27); Serial.print("    "); Serial.println(wheel[0][2]);
    if(rotorvals[wheel[0][0]-27][wheel[0][2]] >= 100) {windex1 = 1;}
    wheel[0][2]++; if(wheel[0][2] > 25) {wheel[0][2] = 0;}
    windex = 0;
    if(windex1 == 1){
    if(rotorvals[wheel[1][0]-27][wheel[1][2]] >= 100) {windex2 = 1;}
    wheel[1][2]++; if(wheel[1][2] > 25) {wheel[1][2] = 0;}}
    windex1 = 0;
    if(windex2 == 1){
    wheel[2][2]++; if(wheel[2][2] > 25) {wheel[2][2] = 0;}
      windex2 = 0; }
  }

IF there is enough interest, we plan on are creating a PCB that would will allow for a much easier assembly of this wonderful fully functional Enigma replica. Please visit http://www.stgeotronics.com to find out about availability, pricing & to place your order or pre-order now. The Circuit schematics are published, so the PCB has entered it's development stage. Soon to be tested.

Step 9: Circuit Schematics

Picture of Circuit Schematics

In response to the popular demand, here are the two Circuit Schematics.

The first one shows how our fake nixie tubes (the 4 elevated 16-Segment units) are wired in order to provide the response that the rotors provide on a real Enigma machine. They are also used in each setup mode to provide feedback on the setting up of the machine.

The second one shows how each of the 26 keyboard buttons and 10 function keys, the 26 key lamps & the 5 LEDS are all wired.

All LED resistors are 470 Ohms and all Pushbutton resistors are 1KOhm.

Stay tuned for the PCB design file...

We hope you enjoyed our first Instructable!

Thank You for your time.

Step 10: Prototype Boards

Picture of Prototype Boards

Due to popular demand, we designed & ordered some Printed Circuit Boards. Well, our PCBs are finally in and at first glance, they look beautiful! We have been busy populating & testing one to make sure it performs as good as it looks and more importantly, as well as our proof-of-concept device.

The boards we ordered are almost perfect: they each need a little jumper wire to fix a small design flaw. This small flaw does not affect behavior or functionality and is an easy fix.

With this jumper in place, you can now make your own Enigma Replica much easier & faster than running all wires this instructable shows. So, we are now happy to report that testing is completed & the new boards work just fine!

We are now accepting orders at www.stgeotronics.com & have started shipping.
Pictures of the assembly have been added as Step 11.

Thank You for your overwhelming support & wonderful feedback!

Step 11: Assembled Kits

Picture of Assembled Kits

This assembly took one evening & you can look at assembly pictures above for an overview of the process.

Thank You for the support & feedback!

Comments

ST-Geotronics (author)2013-12-05

Boards are tested, working great and available now for shipping. Kits & assembled/tested/boxed Enigma Replicas are also available. www.stgeotronics.com to order.

DIY9393 (author)2013-11-19

This is amazing!

You deserve a reward!

DIY9393 (author)DIY93932013-11-19

If you don't mind me asking, how much did all of this cost you?

ST-Geotronics (author)DIY93932013-11-20

Thank You DIY9393 for the kind words.
I guess we should have mentioned the hardware costs in the instructable. All in all, we spent less than $200 in materials. But QUITE a few hours...

DIY9393 (author)ST-Geotronics2013-11-20

No problem!

Thanks for the info!

ST-Geotronics (author)2013-11-20

The PCB drawing phase is completed. We have ordered them from the Fab & are anxiously awaiting their arrival so we can populate & test 1 set ensuring that everything works fine. As soon as this crucial step is completed, they will be available for ordering/shipping.

NOTE: There was NOT enough space on the Enigma PCB to have all necessary components AND connect to the Arduino Mega2560, so we had to create a daughter card for the Mosfets & to receive the Duino. This daughter card will be sandwiched between the motherboard & the Mega2560.

ST-Geotronics (author)2013-10-12

We just posted the second and last Circuit Schematic (for the lampfield and keyboard) at the end of the instructable.

We will start soon working on the PCB design, so stay tuned. Don't forget to vote, every vote counts. Thank You!

Thank you!!

stringstretcher (author)2013-10-15

reflector wheel=b
wheel order 1,2,3ring setting A,A,A
ground setting RAF
HLCI LVSV GXOH YCIE GIYW UQLO JWHT LETL S

ST-Geotronics (author)2013-10-12

In response to the popular demand, we just added the first of 2 Circuit Schematic at the end of the Instructable. You can now find how each of the 4 16-Segment Displays are wired. Stay tuned: We are currently working on the 2nd Circuit Schematic, which will show the rest of the Perfboard wiring: how the 26 keyboard buttons, the 10 function keys, the 26 keyboard lamps & the 5 LEDs are all hooked up. After that, we will design & post the PCB file.

Thank You for the overwhelming positive feedback & don't forget to vote for this Instructable in both contests if you enjoyed it.

thompsms (author)2013-10-07

I just can't wait for the PCB!! Astounding. You deserve a Bletchley Park Medal.

Junophor (author)2013-10-07

I am really deeply impressed!!
Take a bow

Yours Aeon Junophor

bob3030 (author)2013-10-07

Most intriguing instructable I've seen. Must be a record for lines of code in an instructable. Your patience in the wiring is commendable. I would be interested in the PCB you mentioned. Thanks for posting.

Kjuuu (author)2017-08-01

Hello I want to etch the platines myself. Have you any PCB files uploaded?

Amcfarm (author)2017-02-25

Hey, I'm confused on how the leds and the alpha buttons are wired. Do you have any pictures or suggestions on how to wire them?

Amcfarm (author)2017-02-23

Hello Again! When I copy and paste the code into my Arduino program, I get an error stating "stray '/302' in program". Is there any way I can fix this?

Amcfarm (author)2017-02-04

Is it possible to use dual 16 segment displays instead of single 16 segment displays?

ST-Geotronics (author)Amcfarm2017-02-05

It is not possible on our Printed Circuit Board, but if you are building is from scratch, you can certainly use the dual or the quad...

Amcfarm (author)ST-Geotronics2017-02-06

Thank you!!!!

Amcfarm (author)2017-02-04

Hi! I'm trying to build this enigma machine as a school project. I can't seem to find the IRF9Z24N P-Channel MOSFET anywhere. Any idea where I can find it?

ST-Geotronics (author)Amcfarm2017-02-04

Yes, If you go on eBay and look for IRF9Z34N (which are the same), you will find them for $1 to $2 a piece or less...

Amcfarm (author)ST-Geotronics2017-02-05

Thank you!

WalkingD2 (author)2016-06-16

Hi, I am in the process of trying to figure out how to build this from this instructable. And I am so confused by the alpha buttons. What are they? I have tried searching on the internet to figure out what exactly they are but I cannot seem to figure it out. I know that they are simply LEDs that will represent the alphabet.... but what's the like..... holding thing called.... In the photograph it is black with a white protrusion. Also, I have not been able to find banana plugs that have banana plugs on both ends. Am I just looking for the wrong thing? Thanks so much! This is a wicked awesome instructable!

ST-Geotronics (author)WalkingD22016-06-16

WalkingD2, because the alpha buttons we used for this prototype were so difficult to find and expensive, we decided instead to use simple surface mount LEDs. So you can use any through-hole White LED or the 3528 SMT we use. You simply print a paper keyboard to go on top and the proper letter will be illuminated.

For Plugboard Jumpers, we buy single Banana plugs and 8" of cloth covered wire. We screw the male banana plug at each end and test for continuity...

Good Luck! Please post pictures of your build.

WalkingD2 (author)ST-Geotronics2016-06-16

Splendid! Thank you so much for the quick response!! I will try to post pictures when I finish. :)

WalkingD2 (author)2016-06-16

Hi, I am in the process of trying to figure out how to build this from this instructable. And I am so confused by the alpha buttons. What are they? I have tried searching on the internet to figure out what exactly they are but I cannot seem to figure it out. I know that they are simply LEDs that will represent the alphabet.... but what's the like..... holding thing called.... In the photograph it is black with a white protrusion. Also, I have not been able to find banana plugs that have banana plugs on both ends. Am I just looking for the wrong thing? Thanks so much! This is a wicked awesome instructable!

lcgumboy (author)2016-04-01

Hi i am building a replica enigma machine for a middle school project and i was wondering if there are any ways to make just the outside of th emachine so it will still look the same but it wont function, hopefully this would also cut down the cost. thanks

DiegoC14 (author)2015-08-25
DiegoC14 (author)2015-08-25

Technovation (author)2015-06-10

COOOOOOOL!!!

Technovation (author)2015-06-09

awesome!!!!!!!!!!!!!!!!!!!!!!!!!!!

DyerMors (author)2014-12-28

I was wondering about the plugboard. If i haven't got that wrong, it isn't really connected, it's only for imitation proupose, isn't it? All the plugboard thing is handed by the programm?

ST-Geotronics (author)DyerMors2014-12-28

Originally, and as described in this Instructable, you are correct, the plugboard was only for show as it was implemented in software only. However, we have since modified the daughter PCB to receive a fully functional plugboard. This 3 PCB combo is now available as circuits boards only, kit, and fully assembled unit at www.stgeotronics.com

do'malley (author)ST-Geotronics2015-01-28

Schematics for the plugboard would be excellent. Any plans to release?

DyerMors (author)ST-Geotronics2015-01-12

I was wondering, though, will you ever give us the schematics for the project with the fully functional plugboard?? I'm relatively new to electronics so figure out a solution to implement the plugboard is quite a difficult task :(

DyerMors (author)ST-Geotronics2014-12-30

That's really amazing, but just for the sake of the challenge, i wanna build it on perfboard, but i still love the fact that you make available the pcb as well as the project schematics! Keep up the awsome work

SimonAdam (author)2015-01-27

Wow, this is amazing and an epic code... good work.

I was wondering if you able to provide a schematics for the project with a fully functional plugboard. i would like to know how the plug board is wired and how it fits into the Arduino or daughter board?

Regards

do'malley (author)2015-01-25

I am currently building this, but can you tell me which switch on the board is switch 0, switch 1 etc. Is it like the attached image with mode button as sw0? I dont want to wire it up wrong. Excuse the crude editing, it was done using android!

Thanks, David

DavidO2 (author)2014-11-25

What exactly are the "Alpha buttons" and where can I find them?

Are LEDs attached to them to light up the correct letter, or how does it work?

ST-Geotronics (author)DavidO22014-11-25

DavidO2, for the first unit we ever made described in this instructable, (and the next couple), we used normally open buttons containing a blue led with a cap with a character of the alphabet. We found these on ebay but seem to no longer be available. These were a pain to install and solder, not to mention very expensive.

Since then (and for every machine sold in our kickstarter), we simply used surface mount white LEDs and added a printed sheet on top that contains every key in sequence of the keyboard. This provides more light and looks a lot more like a real Enigma...

Visit www.stgeotronics.com for components, kits and assembled/tested units...

Razapple12 (author)2014-05-07

What kind of buttons did you use? I'm trying to make one... :) This is a really great looking replica by the way

ST-Geotronics (author)Razapple122014-05-07

Razapple12, Like most everything else, we found them on eBay:

Search for something like: "Momentary Tactile Push Button Switch 12x12x11mm DIP + Black Round Cap"

This is an example:

http://www.ebay.com/itm/20pcs-Momentary-Tact-Tactile-Push-Button-Switch-12x12x11mm-DIP-Black-Round-Cap-/310569400583?pt=LH_DefaultDomain_0&hash=item484f60f907

Razapple12 (author)2014-05-07

Where did you buy your buttons?

ST-Geotronics (author)Razapple122014-05-07

Razapple12, Like most everything else, we found them on eBay:

Search for something like: "Momentary Tact Tactile Push Button Switch 12x12x11mm DIP + Black Round Cap"

This is an example:

http://www.ebay.com/itm/20pcs-Momentary-Tact-Tacti...

nwsayer (author)2014-04-06

This is great, but it always astonishes me greatly when folks embed a prototyping board in a custom printed circuit board design. If you're going to all the trouble to design a custom printed circuit board, then why not just embed the ATMega chip directly into your design? It just can't help but be cheaper, lighter and smaller that way.

MarkCauer (author)2014-03-13

How does the arduino measure the resistance if there is no current traveling through the resistor and pushbutton setup? Shouldn't there be a ground somewhere?

qbrown2 (author)2013-12-17

I guess i can peak at the code but how did you translate the 7 segment digit dispays to nixie ?

ST-Geotronics (author)qbrown22013-12-17

QBrown2, we didn't:

The 7 Segment displays are actually 16-Segment displays (17 if you count the decimal point) and we are using these as opposed to 7 Segment so we can have a nice Alphabet.

We decided to wire them standing up & encapsulate them inside a test tube to give it somewhat the look of period accurate Nixie Tubes.

So, no Nixies were used in this project...
P.S. the printed circuit board we made allows for 16-Segments LEDs to be horizontal or vertical, but still has not been designed with Nixies in mind...

ST-Geotronics (author)2013-12-03

HURRAY! HURRAY!
Thanksgiving Holiday brought us our Prototype boards. We are now busy populating & testing one to make sure it works as great as the proof of concept does. We are now accepting orders at www.stgeotronics.com & expect very soon to start shipping. We added Step 10 to this Instructable to show pictures & more details.

ST-Geotronics (author)2013-11-02

We are finished drawing the motherboard PCB (top), and have started drawing the daughter car (interface between top PCB & Arduino). Daughter card is required cause we can't fit all components on motherboard. As soon as daughter board is complete and we verify they fit together in Enigma machine, we will send them for production. We expect both boards in our hands sometime in December.

About This Instructable

193,258views

599favorites

License:

Bio: We love to tinker. There is nothing that we can't do if it involves Arduino. Challenge us: Do you have an idea for something ... More »
More by ST-Geotronics:The Twins Electronic GameGPS Data LoggerMake it Blow!
Add instructable to: