art with code

2013-04-27

Boolean Algebra, the crunchy version

First some ring axioms:
x + (y + z) = (x + y) + z
x + 0 = x
x + -x = 0
x + y = y + x

x * (y * z) = (x * y) * z
x * (y + z) = (x*y) + (x*z)
x * 1 = x
x * y = y * x


Let's define AND next:

a AND b = a * b

a AND 1 = a because x * 1 = x

a AND 0 = 0

x * 0 = 0 derives from
x * (y + z) = (x*y) + (x*z): call with z = 0 =>
x * (y+0) = (x * y) + (x * 0) <=>
x * y = (x * y) + (x * 0) <=>
x * 0 = 0

For 0 AND b = 0 and 1 AND b = b, apply x * y = y * x to the above.
Applying all the 0,1 combinations to AND we get the truth table:
0 AND 0 = 0
0 AND 1 = 0
1 AND 0 = 0
1 AND 1 = 1


Then NOT:


NOT a = 1 + -a

NOT 0 = 1 + -0, apply -0 = 0 and x + 0 = x
NOT 0 = 1
-0 = 0 because 
(0 + -0) = 0, apply x + y = y + x
(-0 + 0) = 0, apply x + 0 = x
-0 = 0

NOT 1 = 1 + -1, apply x + -x = 0
NOT 1 = 0


When we combine NOT with AND, we get NAND:

a NAND b = NOT (a AND b)

NOT (0 AND 0) = 1
NOT (0 AND 1) = 1
NOT (1 AND 0) = 1
NOT (1 AND 1) = 0

Writing it out as an equation:

a NAND b = 1 + -(a * b)


NAND is functionally complete so we can write all the 16 possible (binary, binary) -> binary -functions using only NANDs. 

2013-04-21

Boolean Algebra

I started implementing the logic gates in JS for the heck of it. In the process I figured out an interesting algebra for logic circuits. Let's start off with writing some basic JS logic to simulate an abstract transistor. This crummy transistor should give out a 1 when its two input pins are 1. And if either of those is 0 it should return a 0. Let's see:

Transistor = function(control, input) {
  if (control) {
    return input;
  } else {
    return 0;
  }
};

Hmm, well, that does work but it's a bit ugly. And if you know about transistors, they're not really like that. You can use a transistor to amplify a signal. Hook up a faint signal to the control and a powerful input and the transistor scales the input by the control signal. Hey, it's like multiplication!

Transistor = function(control, input) {
  return control * input;
};

Ok, so a transistor is the multiplication operator. How does that work with binary logic? If we take the set {0, 1} as the type of the inputs for both control and input, all works fine: a 1 in the control passes the input through unchanged, a 0 in the control makes the input 0. From that you can see that 1 is the multiplicative identity and multiplying by 0 annihilates the other operand.

To make a NAND gate we need a bit more than just a transistor though. We either need inverse transistors (for a CMOS NAND) or a ground wire (for a NMOS NAND). The NMOS version is a bit simpler so let's write a ground function for it next. A grounded circuit returns a 0 if the ground wire is connected, otherwise it passes the input through untouched.

Ground = function(ground, input) {
  if (ground) {
    return 0;
  } else {
    return input;
  }
};

Again, that's a bit ugly. Let's turn that into an arithmetic representation on our {0, 1} algebra.

Ground = function(ground, input) {
  return (1-ground)*input;
};

Right, it seems we had to introduce a few new concepts there. Algebra-wise 1-ground is shorthand for 1 + -ground. Which means that we need a second operator for our algebra: the addition. And we also have the additive inverse, thanks to the minus sign there. And as 1-0 should return 1, we also get the additive identity. Add 0 to any input and what you get is the input, unchanged.

The algebra we have now has addition, additive identity, additive inverse, multiplication and a multiplicative identity. I think we also have to expand our set to include the additive inverses, netting us the set {-1, 0, 1}. I haven't found a use for the negative numbers in the binary logic though. The alternative would be to turn (1-x) into an axiomatic operation of some sort, I guess.

Oh, also, the inverse transistor has the same formula as the ground operator (if a different wiring implementation).

ITransistor = function(control, input) {
  return (1-ground)*input;
};

Ok, enough setup, let's make a NAND gate! A NAND gate takes two inputs and outputs a 0 if both its inputs are 1, in other cases it outputs a 1. An NMOS NAND gate has two transistors controlled between a voltage source and ground, with the idea that if both transistors are on, the source is connected to the ground and the output signal is zero. And if either of the transistors is off, the source is not connected to the ground and the output signal is the source voltage.

NAND = function(a, b) {
  return Ground(Transistor(b, Transistor(a, 1)), 1);
};

The thing about the NAND gate is that it's functionally complete. You can implement any of the other binary logic gates using NAND gates. Don't believe me? Watch this!

NOT = function(v) {
  return NAND(v, v);
};

BUFFER = function(v) {
  return NOT(NOT(v));
};

AND = function(a, b) {
  return NOT(NAND(a, b));
};

Got that? NAND with the same signal to both inputs is a 1 if the signal is 0 and a 0 if the signal is a 1. And AND is the inverse of NAND. Still not enough? Let's do OR, NOR and XOR as well.

NOR = function(a, b) {
  return AND(NOT(a), NOT(b));
};

OR = function(a, b) {
  return NOT(NOR(a, b));
};

XOR = function(a, b) {
  return AND(OR(a, b), NAND(a, b));
};

With that we have functions to generate the truth tables 1110, 0001, 0111, 1000 and 0110 (I'm writing the entries as the outputs for the 2-bit numbers 00, 01, 10 and 11. So 1110 means the function returns the following: 00 -> 1, 01 -> 1, 10 -> 1, 11 -> 0.) But hey, there are 16 different permutations for those truth tables. Let's write more functions.

// 0000
ZERO = function(a, b) {
  return AND(AND(a, b), NAND(a, b));
};

// 0001 = AND
// 0010
XLEFT = function(a, b) {
  return AND(a, NOT(b));
};
// 0011
LEFT = function(a, b) {
  return AND(a, ONE(b, b));
};
// 0100
XRIGHT = function(a, b) {
  return AND(b, NOT(a));
};
// 0101
RIGHT = function(a, b) {
  return AND(b, ONE(a, a));
};
// 0110 = XOR
// 0111 = OR
// 1000 = NOR
// 1001
XNOR = function(a, b) {
  return NOT(XOR(a, b));
};
// 1010
NRIGHT = function(a, b) {
  return NOT(RIGHT(a, b));
};
// 1011
XNRIGHT = function(a, b) {
  return NOT(XRIGHT(a, b));
};
// 1100
NLEFT = function(a, b) {
  return NOT(LEFT(a, b));
};
// 1101
XNLEFT = function(a, b) {
  return NOT(XLEFT(a, b));
};
// 1110 = NAND
// 1111
ONE = function(a, b) {
  return OR(AND(a, b), NAND(a, b));
};

As you can see from the above, you can implement all the binary functions in {0, 1} using only NAND gates. And since our definition of NAND is in terms of a transistor and a ground operator, which are grounded in some basic arithmetic operations, you can actually write the gates as arithmetic functions.

NAND = function(a, b) {
  //   (1 - (b * (a * 1)) * 1
  // = 1 - (b * a)
  return 1 - b*a;
};

NOT = function(v) {
  // 1 - v*v (v*v = 0 when v = 0, v*v = 1 when v = 1)
  // so in {0,1}, 1-v*v = 1-v
  return 1 - v;
};

AND = function(a, b) {
  //   1 - (1 - b*a)
  // = 1 - 1 + b*a
  return b*a;
};

NOR = function(a, b) {
  // (1-b) * (1-a)
  return (1-b) * (1-a); 
};

OR = function(a, b) {
  //   1 - ((1-b) * (1-a))
  // = 1 - (1*1 + 1*-a + -b*1 + -b*-a)
  // = 1 - (1 - a - b + ba)
  // = 1 - 1 + a + b - ba
  // = a + b - ba
  return a+b - b*a;
};

XOR = function(a,b) {
  // (1-ba)*(a+b-ba)
  return (1-b*a)*(a+b-b*a);
};

And so forth.

Oh, and one more thing. You know the CPU inside your computer? It's made up of NAND gates. Lots and lots of NAND gates hooked up together to compose all the logic in the CPU. And if you think of each NAND as the equation 1-ab, you could think of the CPU as one humongous equation etched onto a silicon chip.

I've got the code for the logic gates and some adder generator code up on GitHub.

2013-04-18

NAND gates

And this should ground the previous to transistors and voltage planes.

I wonder if the implementation of an actual adder circuit would be more complicated. Probably lots of implementation details to consider. But yeah, hook the input pins of the adder to switches, put LEDs on the output pins.

2013-04-17

Circuit diagrams

I was listening to a Feynman lecture on what computers are and started doodling logic circuits based on that. First I made a 1-bit adder, then extended that into a 2-bit adder, doodled a 3-bit adder and generalized from there to arbitrary n-bit adders. Then I made a 4-bit adder out of two 2-bit adders and drew this thing in Photoshop that generalizes the idea to 2n-bit adders. And tried building the rest of the logic gates using just NAND gates. Fun fun :)

I tested the logic gates and the 1-bit and 2-bit adders in JavaScript but haven't tested the 4-bit and n-bit adders.

2013-02-04

Hosting a static website on AWS

Here's a quick guide to hosting a static website on Amazon Web Services. In this guide we set up a root domain for your site content, a www subdomain that redirects to the root domain, and a cdn subdomain that uses Amazon CloudFront as a content distribution network to make your site load faster.

Setting up S3 buckets for hosting the files


First off, go to aws.amazon.com and either log in or sign up for an AWS account. You'll need a credit card for that, mind. Now that you're logged in, go to the S3 console. There? Great!

The second step is to create a new bucket for your site content. Click on the big blue button that says Create Bucket. For the name, enter the domain of your website. Pick the region closest to your intended audience.

Now let's upload the site content into the bucket. Click on the name of the bucket to enter it. Now click the blue Upload button at the top of the page and add the files you want to upload.

As an aside, if you want a nice programmable way to upload files, install this aws shell script and maybe use this automagical hacky upload script of mine. You can also use one of the graphical clients like 3Hub.

Now go back to the S3 console buckets list and click on the magnifying glass next to the bucket name. Look to the right side of the page and select Static Website Hosting from the properties. Click Enable website hosting, write index.html to the Index Document field and click Save. Almost online now! You can see the URL for the bucket endpoint above the website hosting toggling. But if you try to visit the bucket endpoint URL now, it will give you an access denied error.

To make the site publicly visible, we need to edit the permissions for the bucket. Click on Permissions under the bucket Properties. Now click on Add bucket policy and paste in the following policy (remember to change MYBUCKET to the name of your bucket).


{
  "Version":"2008-10-17",
  "Statement":[{
 "Sid":"AddPerm",
        "Effect":"Allow",
   "Principal": {
            "AWS": "*"
         },
      "Action":["s3:GetObject"],
      "Resource":["arn:aws:s3:::MYBUCKET/*"
      ]
    }
  ]
}


Click on Save and then the blue Save button. Done! We're online! You can go to the bucket endpoint URL now and see your site load.

Using your own domain with Route 53


To use your own domain for the site, you can create a CNAME record from www.your_domain to the bucket endpoint URL. Now requests to the www.your_domain go to the bucket, zing! To make the root domain (your_domain with no www) go to the bucket as well, you either have to use Amazon's Route 53 to host your domain's DNS records or (if your DNS provider supports it) set up a redirect page to the www.your_domain from the root domain.

To use Route 53 for hosting your domain's DNS, go to the AWS Console and select Route 53 from Services. Click on Create Hosted Zone, enter your domain name and click on the Create button at the bottom of the form. Ok, now see the four server names in the Delegation Set? Go to your domain registrar and set those servers as the name servers for your domain.

Now tick your hosted zone to select it and click on the Go to Record Sets button. Click on Create Record Set. Leave the subdomain field empty, create an A-record, set Alias to yes and pick your bucket. Now requests to your domain will be served from the bucket. To make www.your_domain go to the bucket as well, create a CNAME record that points to your_domain.

Content delivery network using CloudFront


Let's turn on the CDN now. Go to Services in the AWS console and click on CloudFront. To create a CDN for your bucket, click on Create Distribution. Select Download as the type of the distribution. Type the name of your bucket into the Origin Domain Name field and pick your bucket from the list of completions. Most of the form is alright as-is, so scroll down to Distribution Settings. Enter cdn.your_domain as the CNAME. Set default root object to index.html. Scroll to the bottom of the page and click Create Distribution.

To set up the cdn.your_domain subdomain for the CloudFront distribution, copy the distribution domain name (click on the [i] -button if you're in the list of distributions) and create a new CNAME record that directs cdn.your_domain to the distribution domain name. There we go, your CDN should be live now.

Now when you have images on your website, remember to use point them to your CDN server for best loading performance. Instead of src="http://my_domain/image.jpg", use src="http://cdn.my_domain/image.jpg". The CDN works best for content that change rarely if ever. For frequently changing files it's best to use regular S3, otherwise your edits take anywhere from a few minutes to an hour to appear on the site.

If you need to force a file to be reloaded on the CDN, you can go to Distribution Settings for the distribution (the [i]-icon). On the settings panel, go to the Invalidations tab. Click on Create Invalidation and enter the filenames in the bucket that you want to invalidate. The invalidation takes a few minutes to work and forces the CDN to refresh the invalidated files. You can do it a couple times a month for free, but if you do it a lot it's going to start costing money.

2013-01-22

Using CSS to make printed links readable

The problem: When you print your fancy HTML resume, the links don't show their URLs.
The solution: CSS!

Here's a link with a special print stylesheet. If you try to print this page, you'll see something like this: a link.

This magic trick uses a couple of different features in CSS. First of all, it uses CSS media types to apply a different stylesheet to printed documents. Second, it uses the :after selector to inject some content after each link. Finally, it uses the new CSS attr()-function to fill the :after content with the href of the link.

Putting all of the above together, we get a stylesheet that adds the href of a link after it, but only in printed documents. Here's what my stylesheet looks like:

@media print {
  a:after {
    content: "[" attr(href) "]";
    font-size: smaller;
    position: relative;
    top: -0.1em;
    left: 0.25em;
    padding-right: 0.15em;
    display: inline-block;
    color: black;
  }
}


2012-12-26

Using Swiffy to create HTML animations in Flash

Introduction


The above animation was drawn in Flash but runs in pure HTML5, so it works on your mobile as well. Go on, try it out! Magic, no? Keep reading to find out how to make your own HTML animations in Flash.

First off, get Flash. The easiest way is to get a Creative Cloud subscription and download it from there. Done? Ok. Now, draw your animation. Don't know how? No problem.

Creating your animation


Here's a five-line tutorial to creating Flash animations: Create a new ActionScript 2.0 project, go to the timeline pane, click the onion skin button (looks like two squares), hammer F6 to create new keyframes, use comma and period to move back and forward in the animation, use the brush tool to draw each frame. For more details, you could check out this Adobe tutorial for Flash basics, Drawn to Life for animation lessons, or for more advanced workflow, the Foundation Flash Cartoon Animation book.

Installing the Swiffy extension


Go to the Swiffy project page, download the Swiffy Extension and open it. The extension opens in the Adobe Extension Manager, which walks you through the installation process. Now the next time you open Flash, you should have an "Export to HTML5" menu item in the Commands menu.

Exporting your animation


To export your animation, go to the Commands menu and click on "Export to HTML5". You get a small HTML file with your animation in it, ready for use.

Embedding your animation on your website


The easiest way to use your animation is to put it in an IFRAME. The name of the Swiffy animation file is <your animation name>swf.html, so if you had a file MyAnimation.fla, the HTML file would be MyAnimation.swf.html. And to use it on your page you'd make an IFRAME like this <iframe src="MyAnimation.swf.html" width="500" height="400">.
As the animation is now plugin-free, all the usual CSS transforms and animations should work perfectly on it.

Done!


Now go forth to make your own HTML animations and wow the world!

The source is available on GitHub.






Blog Archive