Monday, April 30, 2018

RC2018/04 wrap-up

At the beginning of April., I entered the Sinclair Scientific Calculator emulator in the Retrochallenge 2018/04.

The following was the description of the goals associated with this challenge:

"For this retrochallenge. I want to completely redesign the PCB so it has the same dimensions as the original: 111 mm tall / 50 mm wide. While the display will remain the not period-accurate LED, all the components will be placed so that their centerline is in the same position as the originals. The board might end up being used with an enclosure, so components will be placed away from the edges such that a smaller version can be be quickly manufactured. Lastly, for aesthetic reasons, the board will have the same color scheme as the calculator and the traces will be discreetly run in the back, as much as possible."

The calculator at that time looked like this:


While it was an improvement over the Green V1 PCB, it was not quite the right dimension, the buttons were not placed with the correct spacing and there were some visible traces in the front. The circuit was also based on the KIM-1 and while it worked, I now realize that it was not the most efficient use of I/O pins for this particular combination of keys and digits.

The initial goals were somewhat easy, redesign the above circuit so it is size accurate and no traces in the front.

At the time, I already knew how to conceal vias by tenting them (placing soldermask and silkscreen over them. The following project log shows the technique:
https://hackaday.io/project/91895-sinclair-scientific-calculator-emulator/log/123664-12252017-finished-routing-the-board-and-submited-for-production

I had already learned how to do a keyboard label using negative silkscreen as shown in the project log:
https://hackaday.io/project/91895-sinclair-scientific-calculator-emulator/log/143883-01232018-slimmer-black-and-white-v2-board-sent-to-production

Another PCB design technique learned during this month was how to create custom PCB shapes. This can be as discreet as a rectangle with rounded corners or as exotic as an insect shape board:
https://hackaday.io/project/91895-sinclair-scientific-calculator-emulator/log/144392-how-to-design-a-custom-pcb-shape-for-fritzing-no-more-sharp-corners

By playing with an actual Sinclair Scientific calculator and pressing multiple keys, the connections between the keyboard the the display were deduced without disassembling the unit:
https://hackaday.io/project/91895-sinclair-scientific-calculator-emulator/log/144393-reverse-engineering-the-keyboard-and-display-circuit-on-a-real-sinclair-scientific

The following schematic was drawn using the information learned:



Using all these techniques, the following board was designed. The placement of the components matches the position of those of the real calculator. Most of the copper is in the bottom. Some unavoidable pieces are placed as long horizontal lines in the front. A couple of tracks that needed to go in the front were hidden under the 8 key.

View of the back of the board copper layer:



Copper in the front of the board:


An assembly guide was put together showing how to solder all the components;
https://hackaday.io/project/91895-sinclair-scientific-calculator-emulator/log/145323-assembly-instructions-for-pcb-v6

And here are pictures of the evolution of this project:

'


The latest version is placed next to the original


Overall, I am satisfied with the progress of this project. The latest version (V6) implements a calculator that is dimensionally and electrically correct.

All of the lessons learned are documented in the following page:
https://hackaday.io/project/91895-sinclair-scientific-calculator-emulator

Friday, April 20, 2018

A review of @Jon_Raymond_ Banana Ruler

It all started when the following tweet showed up on my timeline.


What a brilliant idea, we can finally have a PCB ruler to accurately measure objects in fractions of a banana.

The order was placed with @Oshpark and 2 weeks and $9.50 later, three of these showed up in the mail.


It's absolutely beautiful. The copper layer is exposed to form the shape of the banana, the numerals and the manufacturer logo in the back. The color of the ENIG (electroless nickel immersion gold) coated copper perfectly represents that of a ripe banana.

Technically, this is a beautiful board. The PCB is a custom shape, a rectangle with adjacent corners having a different radius, but opposing corners radiused the same. The copper layer is the same shape as the PCB, but kept away from the edge 1/22 banana. The PCB version number has been written as a negative space in the top(?) copper layer. The use of negative space continues in the soldermask layer. Both the shape of the banana and the numerals are in negative, exposing the copper underneath. No such tricks were employed in the silkscreen layer. The words "Banana Ruler" and the ruler line are unremarkable. A generous hole has been provided to attach this to a keyring. The inside of the hole has been plated.


I received v1.1 of the board. I am unsure what are the differences to v1.0


And now, for the question I am sure everyone is asking themselves. What is the conversion factor between the banana scale, standard and metric units.

The banana ruler end tick mark was carefully aligned with a Stanley tape measure.



The other end of the ruler seemed to be a cat hair over the 1 1/8" mark.

A set of digital calipers were used to measure the inner distance between the end marks.




28.34mm seemed too little. 28.35 was too much.

And there you have it. I highly recommend everybody gets their own Banana Ruler to insure the smooth flow of commerce and exchange of technical information. This is a quality product that with proper care should last you for a long time.

Here is a link to the Dirty Engineering's Banana Ruler shared project at Oshpark.
https://oshpark.com/shared_projects/oXdswtEn


Sunday, September 3, 2017

Assembling the External Lamp Field for the Arduino Enigma Machine Simulator.

The part we will be assembling:


Flip the pieces face down and align them. Put dots on the right side as a reminder of what the proper orientation is:


We will be using Loctite Go2 Gel. It works well to adhere the PCB and wood pieces. Flip the pieces horizontally, the smallest piece with the rectangular hole will go at the bottom.


Put dots of Go2 Gel on all visible surfaces of the smallest piece. Lift the medium piece and place it above the smallest piece. Align the lamp holes. This glue does not set fast, so the pieces can be moved to get the alignment right. Once aligned, place something heavy on top for half an hour until the glue hardens. Make sure no glue is coming out of the lamp holes.


Flip the pieces that were glued together and align the lamp holes with the bigger piece. Once happy with the alignment, draw lines on the big piece using the medium piece as a guide. When assembled, this will face down and not be visible.


Now is the time to glue the PCB to the small wood piece. Put glue dots on all visible surfaces of the small piece (not pictured), then set the PCB down on the small piece. Put something heavy over the assembly while the glue hardens.


While the glue is setting, let's get the lamp film ready. Print the film in a piece of paper. First I was considering printing it in clear film, but to avoid driving to the office supply store, ended up printing it in paper then laminating it with clear packing tape on both sides of the paper, then cutting it down to size.



Align the lamp film with the openings. Ensure the letter P is closest to the indexing dot that was drawn earlier.


Using small pieces of Scotch tape, secure the lamp film to the big piece. Use two small pieces on the sides and two pieces on the top and bottom each. Don't use too much tape. Avoid getting tape over the letters. An important thing to remember is that where there is tape, there wont be glue keeping the whole assembly together, so use only a little tape in 6 spots only. The space between the lens film and the pen lines is where the glue will secure the pieces together.



Ensure the LED are in the center of the hole, bend them carefully if not centered. Test the assembly before gluing it together.



Align the dots and be ready to glue the big piece to the other two.



Ensure the whole assembly is aligned.


Then apply Go2 Gel to the space outside the lens film, but inside the lines.


Put everything together and watch the alignment. Put something heavy over the PCB to keep everything together while the glue hardens.


That's it. Put the assembled pieces aside while the rest of the enclosure is assembled.


Tuesday, May 2, 2017

Retrochallenge 2017 RC2017/04 Introduction and Wrap Up

Introduction:

When the Enigma Z30 program project started, the final program size was a big unknown. 

The Atmel Atmega 328 used in the Arduino Pro Mini, which the KIM Uno uses has 1kB of EEPROM space. This is visible in the KIM-1 monitor from address 0400 to 07FF  

The KIM Uno had been used in a Hackaday project and already had a couple of programs at 0400, so the Enigma program was started at address 0500, RAM variables at 0050. Version 1, at 703 bytes, occupied the space from 0400 to 06BF. 

Initially, the program only supported lever stepping. This stepping mechanism has a double stepping anomaly. When any of the 3 right wheels show a 9, that wheel and the one to its left is incremented. The following sequence shows how a 9 is propagated through the rotors: 8888->8889->8890->8901->9002->9003. Since a lot of numbers are skipped, the actual machine period, the number of unique combinations between 0000 and 9999 is 8100. 

After reading the Enigma Z30 page at the cryptomuseum and realizing there were two different models of the machine, the decision was made to add gear stepping to the simulator. Gear stepping behaves like a car odometer and no numbers are skipped in between 0000 and 9999. 

Adding gear stepping to the program increased it in size slightly. The problems started with the built in menu system used to change the machine settings.

The enigma program detects when RAM contains the value of 0 and it initializes it with the default machine settings of rotors, 1,2,3 ring settings 1,1,1,1 and initial rotor positions of 4,3,2,1. Those values can be found in RAM starting at 0050 and can be manually edited to change the machine settings. Once the enigma program is started, it can be stopped and the RAM settings edited. The program can be restarted and it will encrypt with the new settings. 

A separate menu program was developed to make the process of changing the settings easier. The enigma program does not use the [A],[B] and [GO] keys. A few instructions in the key reading loop detect whether those keys have been pressed and it jumps to special locations in the enigma program. By default those locations contain a jump to the beginning of the key reading loop. When additional code is written, a jump can be inserted in those locations transfering control to the new code. The [GO] key vector has been initialized with a jump to the RAM variable initialization code and serves to zeroise the machine settings to their default values. A quick keypress can erase the current machine settings and prevent others from getting their hands on a machine with actual encryption keys.

The menu system was designed to re-use the enigma program code that changes the rotors. The first thing is must do is backup the rotor values to a temporary space in RAM. Then the desired settings to be changed can be copied to the rotor memory locations, read a keypress and decide what value to change, overflow conditions must be handled, for example, pushing up on rotor 3, selects rotor 1. 

Pressing the [B] key copies the settings from the rotor memory location to their actual location and copies the next settings to change to the rotor addresses. Any error checking must happen at that time, for example, the rotor settings must use rotors 1,2,3 in any order exactly once, 132 is a valid combination, 133 is not. 

Finally, pushing [B] restores the rotor values from temporary space to their correct memory location and jumps back to the enigma program.

The code sequence was: copy values out, copy values in, read key and handle increment / rollover, jump value checking if [B] is pushed, return to loop if invalid, jump to next setting.

Doing some copy and paste programming, the program quickly filled out the space from 06BF to 07FF. This was a problem, space below 500 had to be found to finish writing the menu system.

This was the initial driving force to optimize the program. Version 2 grouped some of the menu code into routines and with some other optimizations the program, now with dual gear and lever stepping and a menu system with a new step to select the gear mechanism, occupied the space from 0400 to 06CA. This was only 11 bytes more than V1 for a lot more functionality.

V2 was ready in time for arbitrary deadline of March 31 2017, the starting date for the Vintage Computer Festival East

The retrochallenge 2017/04 started that weekend and the idea was born to enter the contest with the goal to further optimize the program so it would be smaller than 703 bytes. 

Techniques:

The program was updated as it was being optimized and debugged.

1) Group temporary variable initializations to avoid having to load registers twice. 
i.e: if TEMP1 and TEMP2 are going to be used right away, but TEMP6 will be used further down in the code, initialize it when A has the desired value of 0. 
LDA 00
STA TEMP1
STA TEMP2
STA TEMP6
2) If an algorithm, ALWAYS sets a register to a certain value and that value is needed later, there is no need to initialize the register.
i.e: 
LDA 00
CLC
ADC *TEMP03 ;will have 0 or 1
ADC *TEMP04 ;will have 0 or 1
ADC *TEMP05 ;will have 0 or 1
CMP #$03
BEQ SETUOK
...
SETUOK ; A is NOW 3
3) Ensure the majority of the instructions are 2 bytes. Use RAM variables in page 0 when appropriate. If base+indexing instructions are used, prioritize the use of the X register for indexing 

This function was rewritten so the instructions that use $F8 index with the X register (3 instructions (F8,x) @ 2 bytes + 2 instructions (ROTORS,Y) @ 3 bytes = 12 bytes) vs (3 instructions (F8,Y) @ 3 bytes + 2 instructions (ROTORS,X) @ 2 bytes = 13 bytes).
One byte saved is one byte earned.

05C0        LDY #$00        A0 00
05C2        LDX #$03        A2 03
05C4 SHOWND
05C4        LDA ROTORS,Y    B9 57 00
05C7        ASL A           0A
05C8        ASL A           0A
05C9        ASL A           0A
05CA        ASL A           0A
05CB        STA *$F8,X      95 F8
05CD        INY             C8
05CE        LDA ROTORS,Y    B9 57 00
05D1        ORA *$F8,X      15 F8
05D3        STA *$F8,X      95 F8
05D5        INY             C8
05D6        DEX             CA
05D7        BNE SHOWND      D0 EB

4) Fallthrough was used a couple of ocassions when two functions (A and B) are called one after the other, the return instruction in the first function is eliminated and control allowed to fall through to function B. Function B returns to the caller. Doing this saves 3 bytes for the call instruction in the calling loop and one byte for the return instruction, for a savings of 4 bytes.

...
call A
call B
...
Entry Point A
...
Return to Caller
 
Entry Point B
...
Return to Caller
 
vs: 
...
call A
...
Entry Point A
...
Entry Point B
...
Return to Caller

5) The SHOWEN routine that mixes the rotor values into the correct memory locations for the monitor display routine was modified to also call the KIM-1 display and readkey routines after realizing that both the main loop and the manu loop called SHOWEN and inmmediately called SCANS and then GETKEY. This saved 6 bytes in the menu code. Control to GETKEY is transferred with a jump instead of a call, the return instruction in GETKEY will return to SHOWEN caller, saves the one byte return instruction in SHOWEN

;REM_SUB_SHOWENIGMA
SHOWEN
;copy rotor values (ROTOR,X) into correct place for SCANS (F8,F9,FA)
JSR SCANS
JMP GETKEY ; this is a jump, so the return
NOP ; this was a Return to Caller that can now be eliminated

6) Loop Unrolling: sometimes its shorter to write a loop, sometimes it is better to unroll the loop into a series of repetitive instructions. Sometimes, the same code has to be written twice to select the shorter version. The code below used to be in a fancy loop. It was shorter and clearer to rewrite it the following way. This detects any combination of 1,2,3 at memory location $58 by creating a hash table at TMP02+X containing 1, if rotor X, with X being 1,2,3 was used, 0 if not. This is also a huge buffer overrun, writing 1 to arbitrary memory locations in page 0 depending on the value at LROTOR, MROTOR or RROTOR. The program ensures those memory locations will only have the values 1..3. The only way to exceed those values is through direct memory manipulation, and at that point, any location can be changed, so the only way to experience it is to already have full memory access.

0727        LDA #$01        A9 01
0729        LDX *LROTOR     A6 58
072B        STA *TMP02,X    95 5F
072D        LDX *MROTOR     A6 59
072F        STA *TMP02,X    95 5F
0731        LDX *RROTOR     A6 5A
0733        STA *TMP02,X    95 5F
0735        LDA #$00        A9 00
0737        CLC             18
0738        ADC *TMP03      65 60
073A        ADC *TMP04      65 61
073C        ADC *TMP05      65 62

7) Instead of writing code in the menu system to rollover the rotor values at 1,2,3 instead of the full 0..9, a generic routine was written that will rollover/under at any point. Once the F3 menu was added and restricted to 0..1 to select gear or lever stepping, this generic routine saved 2 bytes from the total program size. 

Wrapup:

Implementing all of the previous techiques, the total program size was reduced to 679 bytes, 24 bytes less than v1. 

Further optimization could concentrate on reducing the number of 3 byte instructions. This can be accomplished by changing all the jumps (3 bytes) to conditional jumps (2 bytes). To do that, the program needs to be analyzed so a flag that is constant at that point in the program can be used, maybe the overflow flag is a good candidate.

Also, any tables in program space can be moved to page 0 so that a two byte page0+X index instruction can be used instead of a three byte absolute+x index instruction. This modification increases RAM consumption in order to reduce program size. 

Below is the breakdown in enigma algorithm vs. menu system program sizes for each version. Version 3 has an enigma engine that is 1 byte bigger, but it enables a significantly smalled menu, for a smaller total size. This byte can be saved by changing the loops to use 2 byte conditional jumps

v1: enigma 460 menu 243 total 703
v2: enigma 451 menu 263 total 714
v3: enigma 452 menu 227 total 679
 

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. Antoine de Saint-Exupery


Sunday, April 16, 2017

Sunday, April 2, 2017

My entry for RC2017/04, An Enigma Machine Z30 Simulator running on a Kim 1 / Uno

Just noticed this years retrochallenge is up! http://www.retrochallenge.org/

Here is the entry page:
http://www.retrochallenge.org/2017/03/rc201704-open-for-entrants.html

  1. Your name (or alias);
  2. Your Twitter handle (if applicable);
  3. Your blog location (for project updates); and
  4. A brief synopsis of your project.

And here is my entry:

1) Arduino Enigma

2) @ArduinoEnigma
     https://twitter.com/arduinoenigma

3) http://arduinoenigma.blogspot.com/

4) There are some cool kids out there making electronic versions of the Enigma Machine. They mostly seem to be some sort of microcontroller wired to 4x fourteen segment displays and pushbuttons to move the rotors and type the message to encrypt. I wanted to do the same but without rolling a custom PCB. A KIM Uno was laying around, having been used only to develop a 53 byte clock program. The idea was born to use the KIM to simulate an Enigma Machine. This 6502 program implements a 1930s encryption machine in a 1970s computer. It turns a KIM Uno into the cheapest physical enigma machine simulator out there.

The original, lever stepping only version was 703 bytes including the menu to change the encryption settings. The v2 gear and lever stepping enigma engine has already been optimized to be smaller than v1. The v2 menu system gained a third function to set the stepping mode. After optimizations, the feature richer v2 is now only 11 bytes bigger than v1.

The goal for this retrochallenge is to further optimize the code so its total size is smaller than v1.

For a bit of background, three rare, numbers only, Enigma Z30 were found in Sweden, an article in Cryptologia "Enigma Z30 retrieved" describes the wheel wiring. This machine can only encrypt numbers and the rotors have only 10 positions, it is thus perfect to be simulated in a KIM.Based on the published wheel wiring and some reasonable assumptions based on the architecture of other enigma machines, a 6502 program was written. The program has two parts, the core enigma functionality, the user being responsible for changing the machine settings via direct RAM manipulation using the KIM monitor and a menu system for a user friendly way of changing the machine settings. After learning that two versions of the machine existed, one with double stepping anomaly prone lever stepping and another with odometer like geared stepping, the program and its menu system ware modified to also support gear stepping.

Below are some demo videos of v1.

https://www.instagram.com/p/BOu3_X8h1rD/
https://www.instagram.com/p/BNbAu1Xhsde/
https://www.instagram.com/explore/tags/enigmaz30/

I had been looking for an excuse to make a new video of v2 showing the new F3 mode to select the stepping mechanism type and to shave a few more bytes off.

RC2017/04, here we come...