CINXE.COM
Ken Shirriff's blog: September 2019
<!DOCTYPE html> <html class='v2' dir='ltr' xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google.com/2005/gml/b' xmlns:data='http://www.google.com/2005/gml/data' xmlns:expr='http://www.google.com/2005/gml/expr'> <head> <link href='https://www.blogger.com/static/v1/widgets/3566091532-css_bundle_v2.css' rel='stylesheet' type='text/css'/> <meta content='width=1100' name='viewport'/> <meta content='text/html; charset=UTF-8' http-equiv='Content-Type'/> <meta content='blogger' name='generator'/> <link href='http://www.righto.com/favicon.ico' rel='icon' type='image/x-icon'/> <link href='http://www.righto.com/2019/09/' rel='canonical'/> <link rel="alternate" type="application/atom+xml" title="Ken Shirriff's blog - Atom" href="http://www.righto.com/feeds/posts/default" /> <link rel="alternate" type="application/rss+xml" title="Ken Shirriff's blog - RSS" href="http://www.righto.com/feeds/posts/default?alt=rss" /> <link rel="service.post" type="application/atom+xml" title="Ken Shirriff's blog - Atom" href="https://www.blogger.com/feeds/6264947694886887540/posts/default" /> <!--Can't find substitution for tag [blog.ieCssRetrofitLinks]--> <meta content='http://www.righto.com/2019/09/' property='og:url'/> <meta content='Ken Shirriff's blog' property='og:title'/> <meta content='Computer history, restoring vintage computers, IC reverse engineering, and whatever' property='og:description'/> <title>Ken Shirriff's blog: September 2019</title> <style type='text/css'>@font-face{font-family:'Play';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/play/v19/6aez4K2oVqwIvtg2H70Q13HqPA.woff2)format('woff2');unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F;}@font-face{font-family:'Play';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/play/v19/6aez4K2oVqwIvtE2H70Q13HqPA.woff2)format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;}@font-face{font-family:'Play';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/play/v19/6aez4K2oVqwIvtY2H70Q13HqPA.woff2)format('woff2');unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF;}@font-face{font-family:'Play';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/play/v19/6aez4K2oVqwIvto2H70Q13HqPA.woff2)format('woff2');unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB;}@font-face{font-family:'Play';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/play/v19/6aez4K2oVqwIvts2H70Q13HqPA.woff2)format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}@font-face{font-family:'Play';font-style:normal;font-weight:400;font-display:swap;src:url(//fonts.gstatic.com/s/play/v19/6aez4K2oVqwIvtU2H70Q13E.woff2)format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}</style> <style id='page-skin-1' type='text/css'><!-- /* ----------------------------------------------- Blogger Template Style Name: Simple Designer: Blogger URL: www.blogger.com ----------------------------------------------- */ /* Variable definitions ==================== <Variable name="keycolor" description="Main Color" type="color" default="#66bbdd"/> <Group description="Page Text" selector="body"> <Variable name="body.font" description="Font" type="font" default="normal normal 12px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="body.text.color" description="Text Color" type="color" default="#222222"/> </Group> <Group description="Backgrounds" selector=".body-fauxcolumns-outer"> <Variable name="body.background.color" description="Outer Background" type="color" default="#66bbdd"/> <Variable name="content.background.color" description="Main Background" type="color" default="#ffffff"/> <Variable name="header.background.color" description="Header Background" type="color" default="transparent"/> </Group> <Group description="Links" selector=".main-outer"> <Variable name="link.color" description="Link Color" type="color" default="#2288bb"/> <Variable name="link.visited.color" description="Visited Color" type="color" default="#888888"/> <Variable name="link.hover.color" description="Hover Color" type="color" default="#33aaff"/> </Group> <Group description="Blog Title" selector=".header h1"> <Variable name="header.font" description="Font" type="font" default="normal normal 60px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="header.text.color" description="Title Color" type="color" default="#3399bb" /> </Group> <Group description="Blog Description" selector=".header .description"> <Variable name="description.text.color" description="Description Color" type="color" default="#777777" /> </Group> <Group description="Tabs Text" selector=".tabs-inner .widget li a"> <Variable name="tabs.font" description="Font" type="font" default="normal normal 14px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="tabs.text.color" description="Text Color" type="color" default="#999999"/> <Variable name="tabs.selected.text.color" description="Selected Color" type="color" default="#000000"/> </Group> <Group description="Tabs Background" selector=".tabs-outer .PageList"> <Variable name="tabs.background.color" description="Background Color" type="color" default="#f5f5f5"/> <Variable name="tabs.selected.background.color" description="Selected Color" type="color" default="#eeeeee"/> </Group> <Group description="Post Title" selector="h3.post-title, .comments h4"> <Variable name="post.title.font" description="Font" type="font" default="normal normal 22px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> </Group> <Group description="Date Header" selector=".date-header"> <Variable name="date.header.color" description="Text Color" type="color" default="#222222"/> <Variable name="date.header.background.color" description="Background Color" type="color" default="transparent"/> <Variable name="date.header.font" description="Text Font" type="font" default="normal bold 11px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="date.header.padding" description="Date Header Padding" type="string" default="inherit"/> <Variable name="date.header.letterspacing" description="Date Header Letter Spacing" type="string" default="inherit"/> <Variable name="date.header.margin" description="Date Header Margin" type="string" default="inherit"/> </Group> <Group description="Post Footer" selector=".post-footer"> <Variable name="post.footer.text.color" description="Text Color" type="color" default="#666666"/> <Variable name="post.footer.background.color" description="Background Color" type="color" default="#f9f9f9"/> <Variable name="post.footer.border.color" description="Shadow Color" type="color" default="#eeeeee"/> </Group> <Group description="Gadgets" selector="h2"> <Variable name="widget.title.font" description="Title Font" type="font" default="normal bold 11px Arial, Tahoma, Helvetica, FreeSans, sans-serif"/> <Variable name="widget.title.text.color" description="Title Color" type="color" default="#000000"/> <Variable name="widget.alternate.text.color" description="Alternate Color" type="color" default="#999999"/> </Group> <Group description="Images" selector=".main-inner"> <Variable name="image.background.color" description="Background Color" type="color" default="#ffffff"/> <Variable name="image.border.color" description="Border Color" type="color" default="#eeeeee"/> <Variable name="image.text.color" description="Caption Text Color" type="color" default="#222222"/> </Group> <Group description="Accents" selector=".content-inner"> <Variable name="body.rule.color" description="Separator Line Color" type="color" default="#eeeeee"/> <Variable name="tabs.border.color" description="Tabs Border Color" type="color" default="#eeeeee"/> </Group> <Variable name="body.background" description="Body Background" type="background" color="#f6fbf6" default="$(color) none repeat scroll top left"/> <Variable name="body.background.override" description="Body Background Override" type="string" default=""/> <Variable name="body.background.gradient.cap" description="Body Gradient Cap" type="url" default="url(https://resources.blogblog.com/blogblog/data/1kt/simple/gradients_light.png)"/> <Variable name="body.background.gradient.tile" description="Body Gradient Tile" type="url" default="url(https://resources.blogblog.com/blogblog/data/1kt/simple/body_gradient_tile_light.png)"/> <Variable name="content.background.color.selector" description="Content Background Color Selector" type="string" default=".content-inner"/> <Variable name="content.padding" description="Content Padding" type="length" default="10px" min="0" max="100px"/> <Variable name="content.padding.horizontal" description="Content Horizontal Padding" type="length" default="10px" min="0" max="100px"/> <Variable name="content.shadow.spread" description="Content Shadow Spread" type="length" default="40px" min="0" max="100px"/> <Variable name="content.shadow.spread.webkit" description="Content Shadow Spread (WebKit)" type="length" default="5px" min="0" max="100px"/> <Variable name="content.shadow.spread.ie" description="Content Shadow Spread (IE)" type="length" default="10px" min="0" max="100px"/> <Variable name="main.border.width" description="Main Border Width" type="length" default="0" min="0" max="10px"/> <Variable name="header.background.gradient" description="Header Gradient" type="url" default="none"/> <Variable name="header.shadow.offset.left" description="Header Shadow Offset Left" type="length" default="-1px" min="-50px" max="50px"/> <Variable name="header.shadow.offset.top" description="Header Shadow Offset Top" type="length" default="-1px" min="-50px" max="50px"/> <Variable name="header.shadow.spread" description="Header Shadow Spread" type="length" default="1px" min="0" max="100px"/> <Variable name="header.padding" description="Header Padding" type="length" default="30px" min="0" max="100px"/> <Variable name="header.border.size" description="Header Border Size" type="length" default="1px" min="0" max="10px"/> <Variable name="header.bottom.border.size" description="Header Bottom Border Size" type="length" default="0" min="0" max="10px"/> <Variable name="header.border.horizontalsize" description="Header Horizontal Border Size" type="length" default="0" min="0" max="10px"/> <Variable name="description.text.size" description="Description Text Size" type="string" default="140%"/> <Variable name="tabs.margin.top" description="Tabs Margin Top" type="length" default="0" min="0" max="100px"/> <Variable name="tabs.margin.side" description="Tabs Side Margin" type="length" default="30px" min="0" max="100px"/> <Variable name="tabs.background.gradient" description="Tabs Background Gradient" type="url" default="url(https://resources.blogblog.com/blogblog/data/1kt/simple/gradients_light.png)"/> <Variable name="tabs.border.width" description="Tabs Border Width" type="length" default="1px" min="0" max="10px"/> <Variable name="tabs.bevel.border.width" description="Tabs Bevel Border Width" type="length" default="1px" min="0" max="10px"/> <Variable name="post.margin.bottom" description="Post Bottom Margin" type="length" default="25px" min="0" max="100px"/> <Variable name="image.border.small.size" description="Image Border Small Size" type="length" default="2px" min="0" max="10px"/> <Variable name="image.border.large.size" description="Image Border Large Size" type="length" default="5px" min="0" max="10px"/> <Variable name="page.width.selector" description="Page Width Selector" type="string" default=".region-inner"/> <Variable name="page.width" description="Page Width" type="string" default="auto"/> <Variable name="main.section.margin" description="Main Section Margin" type="length" default="15px" min="0" max="100px"/> <Variable name="main.padding" description="Main Padding" type="length" default="15px" min="0" max="100px"/> <Variable name="main.padding.top" description="Main Padding Top" type="length" default="30px" min="0" max="100px"/> <Variable name="main.padding.bottom" description="Main Padding Bottom" type="length" default="30px" min="0" max="100px"/> <Variable name="paging.background" color="#ffffff" description="Background of blog paging area" type="background" default="transparent none no-repeat scroll top center"/> <Variable name="footer.bevel" description="Bevel border length of footer" type="length" default="0" min="0" max="10px"/> <Variable name="mobile.background.overlay" description="Mobile Background Overlay" type="string" default="transparent none repeat scroll top left"/> <Variable name="mobile.background.size" description="Mobile Background Size" type="string" default="auto"/> <Variable name="mobile.button.color" description="Mobile Button Color" type="color" default="#ffffff" /> <Variable name="startSide" description="Side where text starts in blog language" type="automatic" default="left"/> <Variable name="endSide" description="Side where text ends in blog language" type="automatic" default="right"/> */ /* Content ----------------------------------------------- */ body { font: normal normal 14px Arial, Tahoma, Helvetica, FreeSans, sans-serif; color: #222222; background: #f6fbf6 none repeat scroll top left; padding: 0 40px 40px 40px; } html body .region-inner { min-width: 0; max-width: 100%; width: auto; } h2 { font-size: 22px; } a:link { text-decoration:none; color: #121fb3; } a:visited { text-decoration:none; color: #121fb3; } a:hover { text-decoration:underline; color: #1a00ff; } .body-fauxcolumn-outer .fauxcolumn-inner { background: transparent url(//www.blogblog.com/1kt/simple/body_gradient_tile_light.png) repeat scroll top left; _background-image: none; } .body-fauxcolumn-outer .cap-top { position: absolute; z-index: 1; height: 400px; width: 100%; } .body-fauxcolumn-outer .cap-top .cap-left { width: 100%; background: transparent url(//www.blogblog.com/1kt/simple/gradients_light.png) repeat-x scroll top left; _background-image: none; } .content-outer { -moz-box-shadow: 0 0 40px rgba(0, 0, 0, .15); -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .15); -goog-ms-box-shadow: 0 0 10px #333333; box-shadow: 0 0 40px rgba(0, 0, 0, .15); margin-bottom: 1px; } .content-inner { padding: 10px 10px; } .content-inner { background-color: #ffffff; } /* Header ----------------------------------------------- */ .header-outer { background: #f6fbf7 url(//www.blogblog.com/1kt/simple/gradients_light.png) repeat-x scroll 0 -400px; _background-image: none; } .Header h1 { font: normal normal 42px Play; color: #666666; text-shadow: 1px 2px 3px rgba(0, 0, 0, .2); } .Header h1 a { color: #666666; } .Header .description { font-size: 140%; color: #666666; } .header-inner .Header .titlewrapper { padding: 22px 30px; } .header-inner .Header .descriptionwrapper { padding: 0 30px; } /* Tabs ----------------------------------------------- */ .tabs-inner .section:first-child { border-top: 0 solid #eeeeee; } .tabs-inner .section:first-child ul { margin-top: -0; border-top: 0 solid #eeeeee; border-left: 0 solid #eeeeee; border-right: 0 solid #eeeeee; } .tabs-inner .widget ul { background: #f5f5f5 url(//www.blogblog.com/1kt/simple/gradients_light.png) repeat-x scroll 0 -800px; _background-image: none; border-bottom: 1px solid #eeeeee; margin-top: 0; margin-left: -30px; margin-right: -30px; } .tabs-inner .widget li a { display: inline-block; padding: .6em 1em; font: normal normal 14px Arial, Tahoma, Helvetica, FreeSans, sans-serif; color: #999999; border-left: 1px solid #ffffff; border-right: 1px solid #eeeeee; } .tabs-inner .widget li:first-child a { border-left: none; } .tabs-inner .widget li.selected a, .tabs-inner .widget li a:hover { color: #000000; background-color: #eeeeee; text-decoration: none; } /* Columns ----------------------------------------------- */ .main-outer { border-top: 0 solid #eeeeee; } .fauxcolumn-left-outer .fauxcolumn-inner { border-right: 1px solid #eeeeee; } .fauxcolumn-right-outer .fauxcolumn-inner { border-left: 1px solid #eeeeee; } /* Headings ----------------------------------------------- */ div.widget > h2, div.widget h2.title { margin: 0 0 1em 0; font: normal bold 11px Arial, Tahoma, Helvetica, FreeSans, sans-serif; color: #000000; } /* Widgets ----------------------------------------------- */ .widget .zippy { color: #999999; text-shadow: 2px 2px 1px rgba(0, 0, 0, .1); } .widget .popular-posts ul { list-style: none; } /* Posts ----------------------------------------------- */ h2.date-header { font: normal bold 11px Arial, Tahoma, Helvetica, FreeSans, sans-serif; } .date-header span { background-color: transparent; color: transparent; padding: inherit; letter-spacing: inherit; margin: inherit; } .main-inner { padding-top: 30px; padding-bottom: 30px; } .main-inner .column-center-inner { padding: 0 15px; } .main-inner .column-center-inner .section { margin: 0 15px; } .post { margin: 0 0 25px 0; } h3.post-title, .comments h4 { font: normal normal 22px Arial, Tahoma, Helvetica, FreeSans, sans-serif; margin: .75em 0 0; } .post-body { font-size: 110%; line-height: 1.4; position: relative; } .post-body img, .post-body .tr-caption-container, .Profile img, .Image img, .BlogList .item-thumbnail img { padding: 2px; background: #ffffff; border: 1px solid #ffffff; -moz-box-shadow: 1px 1px 5px rgba(0, 0, 0, .1); -webkit-box-shadow: 1px 1px 5px rgba(0, 0, 0, .1); box-shadow: 1px 1px 5px rgba(0, 0, 0, .1); } .post-body img, .post-body .tr-caption-container { padding: 5px; } .post-body .tr-caption-container { color: #222222; } .post-body .tr-caption-container img { padding: 0; background: transparent; border: none; -moz-box-shadow: 0 0 0 rgba(0, 0, 0, .1); -webkit-box-shadow: 0 0 0 rgba(0, 0, 0, .1); box-shadow: 0 0 0 rgba(0, 0, 0, .1); } .post-header { margin: 0 0 1.5em; line-height: 1.6; font-size: 90%; } .post-footer { margin: 20px -2px 0; padding: 5px 10px; color: #666666; background-color: #f9f9f9; border-bottom: 1px solid #eeeeee; line-height: 1.6; font-size: 90%; } #comments .comment-author { padding-top: 1.5em; border-top: 1px solid #eeeeee; background-position: 0 1.5em; } #comments .comment-author:first-child { padding-top: 0; border-top: none; } .avatar-image-container { margin: .2em 0 0; } #comments .avatar-image-container img { border: 1px solid #ffffff; } /* Comments ----------------------------------------------- */ .comments .comments-content .icon.blog-author { background-repeat: no-repeat; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9sLFwMeCjjhcOMAAAD+SURBVDjLtZSvTgNBEIe/WRRnm3U8RC1neQdsm1zSBIU9VVF1FkUguQQsD9ITmD7ECZIJSE4OZo9stoVjC/zc7ky+zH9hXwVwDpTAWWLrgS3QAe8AZgaAJI5zYAmc8r0G4AHYHQKVwII8PZrZFsBFkeRCABYiMh9BRUhnSkPTNCtVXYXURi1FpBDgArj8QU1eVXUzfnjv7yP7kwu1mYrkWlU33vs1QNu2qU8pwN0UpKoqokjWwCztrMuBhEhmh8bD5UDqur75asbcX0BGUB9/HAMB+r32hznJgXy2v0sGLBcyAJ1EK3LFcbo1s91JeLwAbwGYu7TP/3ZGfnXYPgAVNngtqatUNgAAAABJRU5ErkJggg==); } .comments .comments-content .loadmore a { border-top: 1px solid #999999; border-bottom: 1px solid #999999; } .comments .comment-thread.inline-thread { background-color: #f9f9f9; } .comments .continue { border-top: 2px solid #999999; } /* Accents ---------------------------------------------- */ .section-columns td.columns-cell { border-left: 1px solid #eeeeee; } .blog-pager { background: transparent none no-repeat scroll top center; } .blog-pager-older-link, .home-link, .blog-pager-newer-link { background-color: #ffffff; padding: 5px; } .footer-outer { border-top: 0 dashed #bbbbbb; } /* Mobile ----------------------------------------------- */ body.mobile { background-size: auto; } .mobile .body-fauxcolumn-outer { background: transparent none repeat scroll top left; } .mobile .body-fauxcolumn-outer .cap-top { background-size: 100% auto; } .mobile .content-outer { -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, .15); box-shadow: 0 0 3px rgba(0, 0, 0, .15); } .mobile .tabs-inner .widget ul { margin-left: 0; margin-right: 0; } .mobile .post { margin: 0; } .mobile .main-inner .column-center-inner .section { margin: 0; } .mobile .date-header span { padding: 0.1em 10px; margin: 0 -10px; } .mobile h3.post-title { margin: 0; } .mobile .blog-pager { background: transparent none no-repeat scroll top center; } .mobile .footer-outer { border-top: none; } .mobile .main-inner, .mobile .footer-inner { background-color: #ffffff; } .mobile-index-contents { color: #222222; } .mobile-link-button { background-color: #121fb3; } .mobile-link-button a:link, .mobile-link-button a:visited { color: #ffffff; } .mobile .tabs-inner .section:first-child { border-top: none; } .mobile .tabs-inner .PageList .widget-content { background-color: #eeeeee; color: #000000; border-top: 1px solid #eeeeee; border-bottom: 1px solid #eeeeee; } .mobile .tabs-inner .PageList .widget-content .pagelist-arrow { border-left: 1px solid #eeeeee; } .content-outer { max-width: 1400px !important; } /* fix header */ #header-inner { width: 100% !important; background-position: right !important; } .titlewrapper { padding: 11px 30px 0 !important; } .descriptionwrapper { margin-bottom: 0 !important; } .description { font-size: 120% !important; } /* suppress things */ .date-header { display: none; } #Attribution1 { display: none; } .post-author, .post-timestamp, .reaction-buttons { display: none; } /* h2: sidebar titles */ /* h3: post title */ .post-title , .entry-title { font-size: 180% !important; margin-top: 0 !important; } .entry-title a:link, .entry-title a:visited, .entry-title a:active{ color: #a03; } #main h2 { color:#333; margin-bottom:.4em; margin-top: 13px; font-size:140%; } #main h3 { color:#333; margin-bottom:.4em; margin-top: 13px; font-size:110%; } #main h4 { color:#333; margin-bottom:.5em; } #sidebar-right-1 a:link, #sidebar-right-1 a:visited, #sidebar-right-1 a:active { color: #666; } #sidebar-right-1 h2 { font-size: 100%; color: #666; } /* disable image box */ element.style { } table.chargers img { height: 18px; } table.chargers img { height: 18px; } .post-body img, .post-body .tr-caption-container { padding: 5px; } .post-body img, .post-body .tr-caption-container, .Profile img, .Image img, .BlogList .item-thumbnail img { padding: 0; background: #ffffff; border: none; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; } /* Special items */ a:link img.hilite, a:visited img.hilite { color: #fff; } a:hover img.hilite, a:hover img.hilite2 { color: #f66; } a:active img.hilite { color: #33c; } .hilite {cursor:zoom-in} pre {color:#000000;border:1px solid #000000;} pre.repl { background-color:#e0e0f0; font-size:120%;} pre.arc { background-color:#e0e0f0; font-size:120%;} pre.code { background-color:#e0f0e0; font-size:120%; white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word;text-wrap:unrestricted;} code { font-size: 100%;} blockquote { font-size: 110%; background: transparent url("//static.righto.com/images/blockquote.gif") no-repeat 0 0; margin: 20px 0px; padding: 0px 40px;} div.cite {font-size: .8em;.; font-style: italic; color: #888; margin-bottom: 9px;} a.ref { color: gray;vertical-align: super; text-decoration: none; font-size:60%;margin-left: 2px;} a img.hilite { border: 1px solid; color: #888; z-index: 2; } a img.hilite2, a:active img.hilite2 { border: 1px solid; color: #f6fbf6; } table.chargers { border-width: 1px; border-spacing: 2px; border-style: outset; border-color: gray; border-collapse: collapse; background-color: white; } table.chargers th.maker { padding-right: 5px; text-align: right; } table.chargers th { border-width: 1px; padding: 3px; border-style: inset; border-color: gray; background-color: white; text-align: center; } table.chargers img { height: 18px; } table.chargers td { text-align: center; border-width: 1px; padding: 2px 8px; border-style: inset; border-color: gray; background-color: white; } --></style> <style id='template-skin-1' type='text/css'><!-- body { min-width: 750px; } .content-outer, .content-fauxcolumn-outer, .region-inner { min-width: 750px; max-width: 750px; _width: 750px; } .main-inner .columns { padding-left: 0px; padding-right: 240px; } .main-inner .fauxcolumn-center-outer { left: 0px; right: 240px; /* IE6 does not respect left and right together */ _width: expression(this.parentNode.offsetWidth - parseInt("0px") - parseInt("240px") + 'px'); } .main-inner .fauxcolumn-left-outer { width: 0px; } .main-inner .fauxcolumn-right-outer { width: 240px; } .main-inner .column-left-outer { width: 0px; right: 100%; margin-left: -0px; } .main-inner .column-right-outer { width: 240px; margin-right: -240px; } #layout { min-width: 0; } #layout .content-outer { min-width: 0; width: 800px; } #layout .region-inner { min-width: 0; width: auto; } --></style> <meta content='width=device-width, initial-scale=1.0, maximum-scale=12.0, minimum-scale=.25, user-scalable=yes' name='viewport'/> <meta content='mw8ww70r3jW0GzXY6j1d' name='follow_it-verification-code'/> <link href='https://www.blogger.com/dyn-css/authorization.css?targetBlogID=6264947694886887540&zx=3ec77cae-5f21-4849-8349-390c6a91e2db' media='none' onload='if(media!='all')media='all'' rel='stylesheet'/><noscript><link href='https://www.blogger.com/dyn-css/authorization.css?targetBlogID=6264947694886887540&zx=3ec77cae-5f21-4849-8349-390c6a91e2db' rel='stylesheet'/></noscript> <meta name='google-adsense-platform-account' content='ca-host-pub-1556223355139109'/> <meta name='google-adsense-platform-domain' content='blogspot.com'/> </head> <body class='loading'> <div class='navbar no-items section' id='navbar'> </div> <div class='body-fauxcolumns'> <div class='fauxcolumn-outer body-fauxcolumn-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </div> <div class='content'> <div class='content-fauxcolumns'> <div class='fauxcolumn-outer content-fauxcolumn-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </div> <div class='content-outer'> <div class='content-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left content-fauxborder-left'> <div class='fauxborder-right content-fauxborder-right'></div> <div class='content-inner'> <header> <div class='header-outer'> <div class='header-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left header-fauxborder-left'> <div class='fauxborder-right header-fauxborder-right'></div> <div class='region-inner header-inner'> <div class='header section' id='header'><div class='widget Header' data-version='1' id='Header1'> <div id='header-inner' style='background-image: url("https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-4KXwYe0lQ4HFzhAye9vvRlij2ZYvMbfPCnqEE__1o85Fjo3XgefxJQhWRdwR3EzNWNMWT3yMaj2QZaT9GazqQx3C6oWa3-hBNlRHG7f-Oib-lv1Wq_C2_A0rt8xZgs87iNqzRVKK7H0A/s800/background.jpg"); background-position: left; width: 550px; min-height: 105px; _height: 105px; background-repeat: no-repeat; '> <div class='titlewrapper' style='background: transparent'> <h1 class='title' style='background: transparent; border-width: 0px'> <a href='http://www.righto.com/'> Ken Shirriff's blog </a> </h1> </div> <div class='descriptionwrapper'> <p class='description'><span>Computer history, restoring vintage computers, IC reverse engineering, and whatever</span></p> </div> </div> </div></div> </div> </div> <div class='header-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </header> <div class='tabs-outer'> <div class='tabs-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left tabs-fauxborder-left'> <div class='fauxborder-right tabs-fauxborder-right'></div> <div class='region-inner tabs-inner'> <div class='tabs no-items section' id='crosscol'></div> <div class='tabs no-items section' id='crosscol-overflow'></div> </div> </div> <div class='tabs-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <div class='main-outer'> <div class='main-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left main-fauxborder-left'> <div class='fauxborder-right main-fauxborder-right'></div> <div class='region-inner main-inner'> <div class='columns fauxcolumns'> <div class='fauxcolumn-outer fauxcolumn-center-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <div class='fauxcolumn-outer fauxcolumn-left-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <div class='fauxcolumn-outer fauxcolumn-right-outer'> <div class='cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left'> <div class='fauxborder-right'></div> <div class='fauxcolumn-inner'> </div> </div> <div class='cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <!-- corrects IE6 width calculation --> <div class='columns-inner'> <div class='column-center-outer'> <div class='column-center-inner'> <div class='main section' id='main'><div class='widget Blog' data-version='1' id='Blog1'> <div class='blog-posts hfeed'> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='http://static.righto.com/images/agc-cpu/agc-opened-w500.jpg' itemprop='image_url'/> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='3418953779753810218' itemprop='postId'/> <a name='3418953779753810218'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2019/09/a-computer-built-from-nor-gates-inside.html'>A computer built from NOR gates: inside the Apollo Guidance Computer</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-3418953779753810218' itemprop='description articleBody'> <p>We recently <a href="https://www.wsj.com/articles/an-apollo-spacecraft-computer-is-brought-back-to-life-11563152761">restored</a> an Apollo Guidance Computer<span id="fnref:owner"><a class="ref" href="#fn:owner" rel="footnote">1</a></span>, the computer that provided guidance, navigation, and control onboard the Apollo flights to the Moon. This historic computer was one of the first to use integrated circuits and its CPU was built entirely from NOR gates.<span id="fnref:sense"><a class="ref" href="#fn:sense" rel="footnote">2</a></span> In this blog post, I describe the architecture and circuitry of the CPU.</p> <h2>Architecture of the Apollo Guidance Computer</h2> <p><a href="http://static.righto.com/images/agc-cpu/agc-opened.jpg"><img alt="The Apollo Guidance Computer with the two trays separated. The tray on the left holds the logic circuitry built from NOR gates. The tray on the right holds memory and supporting circuitry." class="hilite" height="281" src="http://static.righto.com/images/agc-cpu/agc-opened-w500.jpg" title="The Apollo Guidance Computer with the two trays separated. The tray on the left holds the logic circuitry built from NOR gates. The tray on the right holds memory and supporting circuitry." width="500" /></a><div class="cite">The Apollo Guidance Computer with the two trays separated. The tray on the left holds the logic circuitry built from NOR gates. The tray on the right holds memory and supporting circuitry.</div></p> <p>The <a href="https://en.wikipedia.org/wiki/Apollo_Guidance_Computer">Apollo Guidance Computer</a> was developed in the 1960s for the Apollo missions to the Moon. In an era when most computers ranged from refrigerator-sized to room-sized, the Apollo Guidance Computer was unusual—small enough to fit onboard the Apollo spacecraft, weighing 70 pounds and under a cubic foot in size.</p> <p>The AGC is a 15-bit computer. It may seem bizarre to have a word size that isn't a power of two, but in the 1960s before bytes became popular, computers used a wide variety of word sizes. In the case of the AGC, 15 bits provided sufficient accuracy to land on the moon (using double- and triple-precision values as needed), so 16 bits would have increased the size and weight of the computer unnecessarily.<span id="fnref:instruction-size"><a class="ref" href="#fn:instruction-size" rel="footnote">4</a></span></p> <p>The Apollo Guidance Computer has a fairly basic architecture, even by 1960s standards. Although it was built in the era of complex, powerful mainframes, the Apollo Guidance Computer had limited performance; it is more similar to an early microprocessor in power and architecture.<span id="fnref:comparison"><a class="ref" href="#fn:comparison" rel="footnote">3</a></span> The AGC's strengths were its compact size and extensive real-time I/O capability. (I'll discuss I/O in another article.)<span id="fnref:architecture"><a class="ref" href="#fn:architecture" rel="footnote">5</a></span></p> <p>The architecture diagram below shows the main components of the AGC. The parts I'll focus on are highlighted. The AGC has a small set of registers, along with a simple arithmetic unit that only does addition. It has just 36K words of ROM (fixed memory) and 2K words of RAM (erasable memory). The "write bus" was the main communication path between the components. Instruction decoding and the sequence generator produced the control pulses that directed the AGC.</p> <p><a href="http://static.righto.com/images/agc-cpu/block-diagram-highlighted.jpg"><img alt="Block diagram of the Apollo Guidance Computer. From Space Navigation Guidance and Control, R-500, VI-14." class="hilite" height="414" src="http://static.righto.com/images/agc-cpu/block-diagram-highlighted-w600.jpg" title="Block diagram of the Apollo Guidance Computer. From Space Navigation Guidance and Control, R-500, VI-14." width="600" /></a><div class="cite">Block diagram of the Apollo Guidance Computer. From <a href="http://www.ibiblio.org/apollo/Documents/R-500%20Volume%202%20of%202.pdf">Space Navigation Guidance and Control, R-500</a>, VI-14.</div></p> <p>About half of the architecture diagram is taken up by memory, reflecting that in many ways the architecture of the Apollo Guidance Computer was designed around its memory. Like most computers of the 1960s, the AGC used core memory, storing each bit in a tiny ferrite ring (core) threaded onto a grid of wires. (Because a separate physical core was required for every bit, core memory capacity was drastically smaller than modern semiconductor memory.) A property of core memory was that reading a word from memory erased that word, so a value had to be written back to memory after each access. The AGC also had fixed (ROM), the famous core ropes used for program storage where bits were physically woven into the wiring pattern (below). (I've written about the <a href="http://www.righto.com/2019/01/inside-apollo-guidance-computers-core.html">AGC's core memory</a> and <a href="http://www.righto.com/2019/07/software-woven-into-wire-core-rope-and.html">core rope memory</a> in detail.)</p> <p><a href="http://static.righto.com/images/agc-cpu/Plate_19.jpg"><img alt="Detail of core rope memory wiring from an early (Block I) Apollo Guidance Computer. Photo from Raytheon." class="hilite" height="242" src="http://static.righto.com/images/agc-cpu/Plate_19-w300.jpg" title="Detail of core rope memory wiring from an early (Block I) Apollo Guidance Computer. Photo from Raytheon." width="300" /></a><div class="cite">Detail of core rope memory wiring from an early (Block I) Apollo Guidance Computer. <a href="https://authors.library.caltech.edu/5456/1/hrst.mit.edu/hrs/apollo/public/visual3.htm">Photo</a> from Raytheon.</div></p> <!-- The AGC manual has a [functional block diagram](https://archive.org/details/acelectroniclmma00acel_0/page/n34) of the processor but I find it more confusing than helpful. --> <h2>NOR gates</h2> <p>The Apollo Guidance Computer was one of the very first computers to use integrated circuits. These early ICs were very limited; the AGC's chips (below)<span id="fnref:sense"><a class="ref" href="#fn:sense" rel="footnote">2</a></span> contained just six transistors and eight resistors, implementing two 3-input NOR gates.</p> <p><a href="http://static.righto.com/images/agc-cpu/nor-die.jpg"><img alt="Die photo of the dual 3-input NOR gate used in the AGC. The ten bond wires around the outside of the die connect to the IC's external pins. Photo by Lisa Young, Smithsonian." class="hilite" height="250" src="http://static.righto.com/images/agc-cpu/nor-die-w250.jpg" title="Die photo of the dual 3-input NOR gate used in the AGC. The ten bond wires around the outside of the die connect to the IC's external pins. Photo by Lisa Young, Smithsonian." width="250" /></a><div class="cite">Die photo of the dual 3-input NOR gate used in the AGC. The ten bond wires around the outside of the die connect to the IC's external pins. Photo by <a href="https://airandspace.si.edu/stories/editorial/apollo-guidance-computer-and-first-silicon-chips">Lisa Young, Smithsonian</a>.</div></p> <!--  --> <p>The symbol for a <a href="https://en.wikipedia.org/wiki/NOR_gate">NOR gate</a> is shown below. It is a very simple logic gate: if all inputs are low, the output is high. It might be surprising that NOR gates are sufficient to build a computer, but NOR is a universal gate: you can make any other logic gate out of NOR gates. For instance, wiring the inputs of a NOR gate together forms an inverter. Putting an inverter on the output of a NOR gate produces an OR gate. Putting inverters on the inputs of a NOR gate produces an AND gate.<span id="fnref:nand"><a class="ref" href="#fn:nand" rel="footnote">6</a></span> More complex circuits, such as flip flops, adders, and counters can be built from these gates.</p> <p><a href="http://static.righto.com/images/agc-cpu/nor.jpg"><img alt="The NOR gate generates a 1 output if all inputs are 0. If any input is a 1 (or multiple inputs), the NOR gate generates a 0 output. " class="hilite" height="140" src="http://static.righto.com/images/agc-cpu/nor-w200.jpg" title="The NOR gate generates a 1 output if all inputs are 0. If any input is a 1 (or multiple inputs), the NOR gate generates a 0 output. " width="200" /></a><div class="cite">The NOR gate generates a 1 output if all inputs are 0. If any input is a 1 (or multiple inputs), the NOR gate generates a 0 output. </div></p> <p>One building block that appears frequently in the AGC is the set-reset latch. This simple circuit is built from two NOR gates and stores one bit of data: the set input stores a 1 bit and the reset input stores a 0 bit. In more detail, a 1 pulse on the set input turns the top NOR gate off and the bottom one on, so the output is a 1. A 1 pulse on the reset input does the opposite so the output is a 0. If both inputs are 0, the latch remembers its previous state, providing storage. The next section will show how the latch circuit is used to build registers.</p> <p><a href="http://static.righto.com/images/agc-cpu/latch.jpg"><img alt="A set-reset latch built from two NOR gates. If one NOR gate is on, it forces the other one off. The overbar on the top output indicates that it is the complement of the lower output." class="hilite" height="143" src="http://static.righto.com/images/agc-cpu/latch-w250.jpg" title="A set-reset latch built from two NOR gates. If one NOR gate is on, it forces the other one off. The overbar on the top output indicates that it is the complement of the lower output." width="250" /></a><div class="cite">A set-reset latch built from two NOR gates. If one NOR gate is on, it forces the other one off. The overbar on the top output indicates that it is the complement of the lower output.</div></p> <h2>The registers</h2> <p>The Apollo Guidance Computer has a small <a href="https://www.ibiblio.org/apollo/assembly_language_manual.html#CPU_Architecture_Registers">set of registers</a> to store values temporarily outside of core memory. The main register is the accumulator (A), which is used in many arithmetic operations. The AGC also has a program counter register (Z), arithmetic unit registers (X and Y), a buffer register (B), return address register (Q)<span id="fnref:subroutine"><a class="ref" href="#fn:subroutine" rel="footnote">7</a></span>, and a few others. For memory accesses, the AGC has a memory address register (S) and a memory buffer register (G) for data. <!-- https://archive.org/details/acelectroniclmma00acel_0/page/n33 --> The AGC also has some registers that reside in core memory, such as I/O counters.</p> <p>The following diagram outlines the register circuitry for the AGC, simplified to a single bit and two registers (Q and Z). Each register bit has a latch (flip-flop), using the circuit described earlier (blue and purple). Data is transmitted both to and from the registers on the write bus (red). To write to a register, the latch is first reset by a clear signal (CQG or CZG, green). A "write service" gate signal (WQG or WZG, orange) then allows the data on the write bus to set the corresponding register latch. To read a register, a "read service" gate signal (RQG or RZG, cyan) passes the latch's output through the write amplifier to the write bus, for use by other parts of the AGC. The complete <a href="https://archive.org/details/agc_handbook_jp2/page/n213">register circuitry</a> is more complex, with multiple 16-bit registers, but follows this basic structure.</p> <p><a href="http://static.righto.com/images/agc-cpu/register-diagram.jpg"><img alt="Simplified diagram of AGC register structure, showing one bit of the Q and Z registers. (Source)" class="hilite" height="292" src="http://static.righto.com/images/agc-cpu/register-diagram-w500.jpg" title="Simplified diagram of AGC register structure, showing one bit of the Q and Z registers. (Source)" width="500" /></a><div class="cite">Simplified diagram of AGC register structure, showing one bit of the Q and Z registers. (<a href="https://archive.org/details/acelectroniclmma00acel_0/page/n39">Source</a>)</div></p> <p>The register diagram illustrates three key points. First, the register circuitry is built from NOR gates. Second, data movement through the AGC centers on the write bus. Finally, the register actions (like other AGC actions) depend on specific control signals at the right time; the "control" section of this post will discuss how these signals are generated.</p> <h2>The arithmetic unit</h2> <p>Most computers have an <a href="https://en.wikipedia.org/wiki/Arithmetic_logic_unit">arithmetic logic unit</a> (ALU) that performs arithmetic and Boolean logic operations. Compared to most computers, the AGC's arithmetic unit is very limited: the only operation it performs is addition of 16-bit values, so it's called an arithmetic unit, not an arithmetic logic unit. (Despite its limited arithmetic unit, the AGC can perform a variety of arithmetic and logic operations including multiplication and division, as explained in the footnote.<span id="fnref:logicops"><a class="ref" href="#fn:logicops" rel="footnote">9</a></span>)</p> <!-- The Apollo Guidance Computer's arithmetic unit performs 1's complement addition on 16-bit values. The arithmetic unit can also add fixed values of +1, -1, +2 and octal 40000. --> <!-- adder service https://archive.org/details/acelectroniclmma00acel_0/page/n77 --> <!-- ALU and register schematic https://archive.org/details/agc_handbook_jp2/page/n213 --> <p>The schematic below shows one bit of the AGC's arithmetic unit. The <a href="https://en.wikipedia.org/wiki/Adder_(electronics)#Full_adder">full adder</a> (red) computes the sum of two bits and a carry. In particular, the adder sums the X bit, Y bit, and carry-in, generating the sum bit (sent to the write bus) and carry bit. The carry is passed to the next adder, allowing adders to be combined to add longer words.<span id="fnref:carryskip"><a class="ref" href="#fn:carryskip" rel="footnote">8</a></span>)</p> <p><a href="http://static.righto.com/images/agc-cpu/alu-schematic-labeled.jpg"><img alt="Schematic of one bit in the AGC's arithmetic unit. (Based on AGC handbook p214.)" class="hilite" height="200" src="http://static.righto.com/images/agc-cpu/alu-schematic-labeled-w700.jpg" title="Schematic of one bit in the AGC's arithmetic unit. (Based on AGC handbook p214.)" width="700" /></a><div class="cite">Schematic of one bit in the AGC's arithmetic unit. (Based on <a href="https://archive.org/details/agc_handbook_jp2/page/n213">AGC handbook</a> p214.)</div></p> <p>The X register and Y register (purple and green) provide the two inputs to the adder. These are implemented with the NOR-gate latch circuits described earlier. The circuitry in blue writes a value to the X or Y register as specified by the control signals. This circuitry is fairly complex since it allows constants and shifted values to be stored in the registers, but I won't go into the details. Note the "A2X" control signal that gates the A register value into the X register; it will be important in the following discussion.</p> <!-- Page 4-407 of https://www.ibiblio.org/apollo/Documents/apollolunarexcuracel.pdf explains the control signals --> <p>The photo below shows the physical implementation of the AGC's circuitry. This module implements four bits of the registers and arithmetic unit. The flat-pack ICs are the black rectangles; each module has two boards with 60 chips each, for a total of 240 NOR gates. The arithmetic unit and registers are built from four identical modules, each handling four bits; this is similar to a <a href="https://en.wikipedia.org/wiki/Bit_slicing">bit-slice processor</a>.</p> <p><a href="http://static.righto.com/images/agc-cpu/module-a8.jpg"><img alt="The arithmetic unit and registers are implemented in four identical modules. Each module implements 4 bits. The modules are installed in slots A8 through A11 of the AGC." class="hilite" height="135" src="http://static.righto.com/images/agc-cpu/module-a8-w600.jpg" title="The arithmetic unit and registers are implemented in four identical modules. Each module implements 4 bits. The modules are installed in slots A8 through A11 of the AGC." width="600" /></a><div class="cite">The arithmetic unit and registers are implemented in four identical modules. Each module implements 4 bits. The modules are installed in slots A8 through A11 of the AGC.</div></p> <!-- RAND0 shown on page 32-156 of blk2 instructions, ROR0 on 32-159 --> <h2>Executing an instruction</h2> <p>This section illustrates the sequence of operations that the AGC performs to execute an instruction. In particular, I'll show how an addition instruction, ADS (add to storage), takes place. This instruction reads a value from memory, adds it to the accumulator (A register), and stores the sum in both the accumulator and memory. This is a single machine instruction, but the AGC performs many steps and many values move back and forth to accomplish it.</p> <p>Instruction timing is driven by the core memory subsystem. In particular, reading a value from core memory erases the stored value, so a value must be written back after each read. Also, when accessing core memory there is a delay between when the address is set up and when the data is available. The result is that each memory cycle takes 12 time steps to perform first a read and then a write. Each time interval (T1 to T12) takes just under one microsecond, and the full memory cycle takes 11.7µs, called a Memory Cycle Time (MCT).</p> <p><a href="http://static.righto.com/images/agc-cpu/erasable-module.jpg"><img alt="The erasable core memory module from the Apollo Guidance Computer. This module holds 2 kilowords of memory, with a tiny ferrite core storing each bit. To read memory, high-current pulses flip the magnetization of the cores, erasing the word." class="hilite" height="174" src="http://static.righto.com/images/agc-cpu/erasable-module-w600.jpg" title="The erasable core memory module from the Apollo Guidance Computer. This module holds 2 kilowords of memory, with a tiny ferrite core storing each bit. To read memory, high-current pulses flip the magnetization of the cores, erasing the word." width="600" /></a><div class="cite">The erasable core memory module from the Apollo Guidance Computer. This module holds 2 kilowords of memory, with a tiny ferrite core storing each bit. To read memory, high-current pulses flip the magnetization of the cores, erasing the word.</div></p> <p>The MCT is the basic time unit for instruction execution. A typical instruction requires two memory cycles: one memory access to fetch the instruction from memory, and one memory access to perform the operation.<span id="fnref:subinstructions"><a class="ref" href="#fn:subinstructions" rel="footnote">13</a></span> Thus, a typical instruction requires two MCTs (23.4µs), yielding about 43,000 instructions per second. (This is extremely slow compared to modern processors performing billions of instructions per second.)</p> <p>Internally, the Apollo Guidance Computer processes instructions by breaking an instruction into subinstructions, where each subinstruction takes one memory cycle For example, the ADS instruction consists of two subinstructions: the ADS0 subinstruction (which does the addition) and the STD2 subinstruction (which fetches the next instruction, and is common to most instructions). The diagram below shows the data movement inside the AGC to execute the ADS0 subinstruction. The 12 times steps are indicated left to right.</p> <!-- Link describing all the instructions http://www.ibiblio.org/apollo/Documents/agcis_32_blk2_instructions.pdf --> <p><a href="http://static.righto.com/images/agc-cpu/ads0-labeled.jpg"><img alt="Operations during the ADS0 (add to storage) subinstruction. Arrows show important data movement. Based on the manual." class="hilite" height="530" src="http://static.righto.com/images/agc-cpu/ads0-labeled-w700.jpg" title="Operations during the ADS0 (add to storage) subinstruction. Arrows show important data movement. Based on the manual." width="700" /></a><div class="cite">Operations during the ADS0 (add to storage) subinstruction. Arrows show important data movement. Based on the <a href="https://archive.org/details/apollolunarexcuracel_0/page/126">manual</a>.</div></p> <p>The important steps are: <br>T1: The operand address is copied from the instruction register (B) to the memory address register (S) to start a memory read. <br>T4: The operand is read from core memory to the memory data register (G). <br>T5: The operand is copied from (G) to the adder (Y). The accumulator value (A) is copied to the adder (X). <br>T6: The adder computes the sum (U), which is copied to the memory data register (G). <br>T8: The program counter (Z) is copied to the memory address register (S) to prepare for fetching the next instruction from core memory. <br>T10: The sum in the memory data register (G) is written back to core memory. <br>T11: The sum (U) is copied to the accumulator (A).</p> <!-- Followed by STD2 subinstruction: https://archive.org/details/apollolunarexcuracel_0/page/112 Read from address S into G, B, write back. Address in instruction (026077) moved to S for next fetch. Instruction address in Z goes through Y, incremented. Written to S. (Previous S used for writeback.) Instr addr 521 -> 522. --> <p>Even though this is a simple add instruction, many values are moved around during the 12 time intervals. Each of these actions has a control signal associated with it; for instance, the signal A2X at time T5 causes the accumulator (A) value to be copied to the X register. Copying the G register to the Y register takes two control pulses: RG (read G) and WY (write Y). The next section will explain how the AGC's control unit generates the appropriate control signals for each instruction, focusing on these A2X, RG, and WY control pulses needed by ADS0 at time T5.</p> <!-- To complete the ADS add instruction, this subinstruction is followed by another subinstruction (STD2) that takes another 12 time intervals to fetch the next instruction and increment the program counter (Z). I won't illustrate that subinstruction here, but it also copies many values back and forth. --> <h2>The control unit</h2> <p>As in most computers, the AGC's control unit decodes each instruction and generates the control signals that tell the rest of the processor (the datapath) what to do. The AGC is designed with microcoded approach, but the control signals are generated from a <a href="https://en.wikipedia.org/wiki/Control_unit#Hardwired_control_unit">hardwired control unit</a> built from NOR gates. Specifically, there are no microinstructions and the AGC does not have a control store holding microcode (which would have taken too much physical space).<span id="fnref:microprogram"><a class="ref" href="#fn:microprogram" rel="footnote">12</a></span>You can think of the AGC as implementing the microcode ROM with highly-optimized logic gates.</p> <!-- Extended opcode in SQ register. 4-5.4.5 Opcode decoded into SQ0-SQ7, SQEXT. Quartercode QC0 through QC3. Stage counter ST counts the subinstructions. Subinstruction decoder produces subinstruction and instruction signals. 4-5.4.7 (An instruction signal indicates multiple (similar) subinstructions, not an instruction. --> <p>The heart of the AGC's control unit is called the crosspoint generator. Conceptually, the crosspoint generator takes the subinstruction and the time step, and generates the control signals for that combination of subinstruction and time step. (You can think of the crosspoint generator as a grid with subinstructions in one direction and time steps in the other, with control signals assigned to each point where the lines cross.) For instance, going back to the ADS0 subinstruction, at time T5 the crosspoint generator would generate the A2X, RG, and WY control pulses, causing the desired data movement.</p> <p><a href="http://static.righto.com/images/agc-cpu/a6-module.jpg"><img alt="The crosspoint generator required a lot of circuitry and was split across three modules; this is module A6. Note the added wires to modify the circuitry. This is an earlier module used for ground testing; modules in flight did not have these wires." class="hilite" height="121" src="http://static.righto.com/images/agc-cpu/a6-module-w600.jpg" title="The crosspoint generator required a lot of circuitry and was split across three modules; this is module A6. Note the added wires to modify the circuitry. This is an earlier module used for ground testing; modules in flight did not have these wires." width="600" /></a><div class="cite">The crosspoint generator required a lot of circuitry and was split across three modules; this is module A6. Note the added wires to modify the circuitry. This is an earlier module used for ground testing; modules in flight did not have these wires.</div></p> <p>For efficiency, the implementation of the control unit is highly optimized. Instructions with similar behavior are combined and processed together by the crosspoint generator to reduce circuitry. <!-- These inputs are called "commands" acelectroniclmma00acel.pdf p335. See Table 4-X for a list. --> For instance, the AGC has a "Double-precision Add to Storage" instruction (DAS). Since this is roughly similar to performing two single-word adds, the DAS1 subinstruction and ADS0 subinstruction share logic in the crosspoint generator. The schematic below shows the crosspoint generator circuitry for time T5, highlighting the logic for subinstruction ADS0 (using the DAS1 signal). For instance, the 5K signal is generated from the combination of DAS1 and T5.</p> <p><a href="http://static.righto.com/images/agc-cpu/t05-labeled.jpg"><img alt="Crosspoint circuit for signals generated at time T5. With negative inputs, these NOR gates act as AND gates, detecting a particular subinstruction AND T05. From Apollo Lunar Excursion Manual." class="hilite" height="383" src="http://static.righto.com/images/agc-cpu/t05-labeled-w500.jpg" title="Crosspoint circuit for signals generated at time T5. With negative inputs, these NOR gates act as AND gates, detecting a particular subinstruction AND T05. From Apollo Lunar Excursion Manual." width="500" /></a><div class="cite">Crosspoint circuit for signals generated at time T5. With negative inputs, these NOR gates act as AND gates, detecting a particular subinstruction AND T05. From <a href="https://archive.org/details/acelectroniclmma00acel/page/n367">Apollo Lunar Excursion Manual</a>.</div></p> <p>But what are the 5K and 5L signals? These are another optimization. Many control pulses often occur together, so instead of generating all the control pulses directly, the crosspoint generates intermediate crosspoint signals. For instance, 5K generates both the A2X and RG control pulses, while 5L generates the WY control pulse. The diagram below shows how the A2X signal is generated: any of 8 different signals (including 5K) generate A2X.<span id="fnref:actions"><a class="ref" href="#fn:actions" rel="footnote">15</a></span> Similar circuits generate the other control pulses. These optimizations reduced the size of the crosspoint generator, but it was still large, split across three modules in the AGC.</p> <p><a href="http://static.righto.com/images/agc-cpu/a2x.jpg"><img alt="The A2X control signal is generated from multiple "crosspoint pulses" from the crosspoint generator. The different possibilities are ORed together. From manual, page 4-351." class="hilite" height="186" src="http://static.righto.com/images/agc-cpu/a2x-w300.jpg" title="The A2X control signal is generated from multiple "crosspoint pulses" from the crosspoint generator. The different possibilities are ORed together. From manual, page 4-351." width="300" /></a><div class="cite">The A2X control signal is generated from multiple "crosspoint pulses" from the crosspoint generator. The different possibilities are ORed together. From <a href="https://archive.org/details/acelectroniclmma00acel/page/n433">manual, page 4-351</a>.</div></p> <!-- The control pulses generated for the ADS0 subinstruction are listed [here](https://archive.org/details/acelectroniclmma00acel/page/n401). --> <p>To summarize, the control unit is responsible for telling the rest of the CPU what to do in order to execute an instruction. Instructions are first decoded into subinstructions. The crosspoint generator creates the proper control pulses for each time interval and subinstruction, telling the AGC's registers, arithmetic unit, and memory what to do.<span id="fnref:pla"><a class="ref" href="#fn:pla" rel="footnote">14</a></span></p> <!-- crosspoint schematic https://archive.org/details/agc_handbook_jp2/page/n248 --> <h2>Conclusion</h2> <p>This has been a whirlwind tour of the Apollo Guidance Computer's CPU. To keep it manageable, I've focused on the ADS addition instruction and a few of the control pulses (A2X, RG, and WY) that make it operate. Hopefully, this gives you an idea of how a computer can be built from components as primitive as NOR gates.</p> <p>The most visible part of the architecture is the datapath: arithmetic unit, registers, and the data bus. The AGC's registers are built from simple NOR-gate latches. Even though the AGC's arithmetic unit can only do addition, the computer still manages to perform a full set of operations including multiplication and division and Boolean operations.<span id="fnref:logicops"><a class="ref" href="#fn:logicops" rel="footnote">9</a></span></p> <p>However, the datapath is just part of the computer. The other critical component is the control unit, which tells the data path components what to do. The AGC uses an approach centered around a crosspoint generator, which uses highly-optimized hardwired logic to generate the right control pulses for a particular subinstruction and time interval.</p> <p>Using these pieces, the Apollo Guidance Computer provided guidance, navigation, and control onboard the Apollo missions, making the Moon landings possible. The AGC also provided a huge boost to the early integrated circuit industry, using 60% of the United States' IC production in 1963. Thus, modern computers owe a lot to the AGC and its simple NOR gate components.</p> <p><a href="http://static.righto.com/images/agc-cpu/agc-with-scope.jpg"><img alt="The Apollo Guidance Computer running in Marc's lab, hooked up to a vintage Tektronix scope." class="hilite" height="275" src="http://static.righto.com/images/agc-cpu/agc-with-scope-w500.jpg" title="The Apollo Guidance Computer running in Marc's lab, hooked up to a vintage Tektronix scope." width="500" /></a><div class="cite">The Apollo Guidance Computer running in Marc's lab, hooked up to a vintage Tektronix scope.</div></p> <p>CuriousMarc has a <a href="https://www.youtube.com/watch?v=2KSahAoOLdU">series of AGC videos</a> which you should watch for more information on the restoration project. I announce my latest blog posts on Twitter, so follow me <a href="https://twitter.com/kenshirriff">@kenshirriff</a> for future articles. I also have an <a href="http://www.righto.com/feeds/posts/default">RSS feed</a>. Thanks to Mike Stewart for supplying images and extensive information.</p> <h2>Notes and references</h2> <div class="footnote"> <ol> <li id="fn:owner"> <p>The AGC restoration team consists of Mike Stewart (creator of <a href="https://github.com/virtualagc/agc_simulation">FPGA AGC</a>), <a href="https://rescue1130.blogspot.com/2018/11/restoring-apollo-guidance-computer-part.html">Carl Claunch</a>, Marc Verdiell (<a href="https://www.youtube.com/channel/UC3bosUr3WlKYm4sBaLs-Adw">CuriousMarc</a> on YouTube) and myself. The AGC that we're restoring belongs to a private owner who picked it up at a scrapyard in the 1970s after NASA scrapped it. <a class="footnote-backref" href="#fnref:owner" rev="footnote" title="Jump back to footnote 1 in the text">↩</a></p> </li> <li id="fn:sense"> <p>In addition to the NOR-gate logic chips, the AGC used a second type of integrated circuit for its memory circuitry, a sense amplifier. (The earlier Block I Apollo Guidance Computer used NOR gate ICs that contained a single NOR gate.) <a class="footnote-backref" href="#fnref:sense" rev="footnote" title="Jump back to footnote 2 in the text">↩</a></p> </li> <li id="fn:comparison"> <p>How does the AGC stack up to early microprocessors? Architecturally, I'd say it was more advanced than early 8-bit processors like the 6502 (1975) or Z-80 (1976), since the AGC had 15 bits instead of 8, as well as more advanced instructions such as multiplication and division. But I consider the AGC less advanced than the 16-bit Intel 8086 (1978) which has a larger register set, advanced indexing, and instruction queue. Note, though, that the AGC was in a class of its own as far as I/O, with 227 interface circuits connected to the rest of the spacecraft.</p> <p>Looking at transistor counts, the Apollo Guidance Computer had about 17,000 transistors in total in its ICs, <!-- 5600 gates * 3. 120 packages / module, 24 modules --> which puts it between the Z80 microprocessor (8,500 transistors) and the Intel 8086 (29,000 transistors).</p> <p>As far as performance, the AGC did a 15-bit add in 23.4渭s and a multiply in 46.8渭s. The 6502 took about 3.9渭s for an 8-bit add (much faster, but a smaller word). Implementing an 8-bit multiply loop on the 6502 might take over 100渭s, considerably worse than the AGC. The AGC's processor cycle speed of 1.024 MHz was almost exactly the same as the Apple II's 1.023 MHz clock, but the AGC took 24 cycles for a typical instruction, compared to 4 on the 6502. The big limitation on AGC performance was the 11.7渭s memory cycle time, compared to 300 ns for the Apple II's 4116 DRAM chips. <!-- Times on an Intel 8086 running at 10 MHz varied, but typically 0.3-2渭s for an add, and 7-16渭s for a multiply, so much faster than the AGC. --> <a class="footnote-backref" href="#fnref:comparison" rev="footnote" title="Jump back to footnote 3 in the text">↩</a></p> </li> <li id="fn:instruction-size"> <p>An AGC instruction fit into a 15-bit word and consisted of a 3-bit opcode and a 12-bit memory address. Unfortunately, both the opcode and memory address were too small, resulting in multiple workarounds that make the architecture kind of clunky.</p> <p>The AGC's 15-bit instructions included a 12-bit memory address which could only address 4K words. This was inconvenient since the AGC had 2K words of core RAM and 36K words of core rope ROM. To access this memory with a 12-bit address, the AGC used a <a href="https://www.ibiblio.org/apollo/assembly_language_manual.html#Memory_Map">complex bank-switching scheme</a> with multiple bank registers. In other words, you could only access RAM in 256-word chunks and ROM in somewhat larger chunks.</p> <p>The AGC's instructions had a 3-bit opcode field, which was too small to directly specify the AGC's 34 instructions. The AGC used several tricks to specify more opcodes. First, an <code>EXTEND</code> instruction changed the meaning of the following instruction, allowing twice as many opcodes but wasting a word. Also, some AGC opcodes didn't make sense if performed on a ROM address (such as incrementing), so four different instructions ("quartercode instructions") could share an opcode field. Instructions that act on peripherals only use 9 address bits, freeing up 3 additional bits for opcode use. This allows, for instance, Boolean operations (AND, OR, XOR) to fit into the opcode space, but they can only access peripheral addresses, not main memory addresses.</p> <p>The AGC also used some techniques to keep the opcode count small. For example, it had some "magic" memory locations such as the "shift right register". Writing to this address performed a shift; this avoided a separate opcode for "shift right".</p> <!-- Another feature is the <a href="https://www.ibiblio.org/apollo/assembly_language_manual.html#CPU_Architecture_Registers">special-purpose registers</a> that implement shifts. For instance, writing to the Shift Right register (SR) at address 21 shifts the word one bit to the right. These registers are not physical registers, but part of regular memory. A write to a special address blocks the normal write to memory and instead writes the shifted value. (The implementation is a multiplexer (of NOR gates) that selects which bits are stored in the G register (the memory data register), selecting the shifted value if the right address is selected. --> <!-- See https://www.ibiblio.org/apollo/Documents/apollolunarexcuracel.pdf page 4-405 --> <p>The AGC also had some instructions that wedged multiple functions into a single instruction. For instance, the "Transfer to Storage" instruction not only transferred a value to storage, but also checked the overflow flag and updated the accumulator and skipped an instruction if there had been an arithmetic overflow. Another complex instruction was "Count, Compare, and Skip", which loaded a value from memory, decremented it, and did a four-way branch depending on its value. See <a href="https://www.ibiblio.org/apollo/assembly_language_manual.html#AGC4_Instruction_Set">AGC instruction set</a> for details. <a class="footnote-backref" href="#fnref:instruction-size" rev="footnote" title="Jump back to footnote 4 in the text">↩</a></p> </li> <li id="fn:architecture"> <p>For more on the AGC's architecture, see the <a href="https://www.ibiblio.org/apollo/assembly_language_manual.html">Virtual AGC</a> and the <a href="https://www.youtube.com/watch?v=xx7Lfh5SKUQ">Ultimate Apollo Guidance Computer Talk</a>. <a class="footnote-backref" href="#fnref:architecture" rev="footnote" title="Jump back to footnote 5 in the text">↩</a></p> </li> <li id="fn:nand"> <p>The NAND gate also has the same property of being a universal gate. (In modern circuits, NAND gates are usually more popular than NOR gates for <a href="https://electronics.stackexchange.com/questions/110649/why-is-nand-gate-preferred-over-nor-gate-in-industry">technical</a> <a href="https://www.quora.com/NAND-and-NOR-are-both-universal-gates-Why-is-NAND-preferred-over-NOR-gate-in-most-applications">reasons</a>.) The popular <a href="https://www.nand2tetris.org">NAND to Tetris</a> course describes how to build up a computer from NAND gates, ending with an implementation of Tetris. This approach starts by building a set of logic gates (NOT, AND, OR, XOR, multiplexer, demultiplexer) from NAND gates. Then larger building blocks (flip flop, adder, incrementer, ALU, register) are built from these gates, and finally a computer is built from these building blocks. <a class="footnote-backref" href="#fnref:nand" rev="footnote" title="Jump back to footnote 6 in the text">↩</a></p> </li> <li id="fn:subroutine"> <p>Modern computers usually have a stack that is used for subroutine calling and returning. However, the AGC (like many other computers of its era) didn't have a stack, but stored the return address in a <a href="https://en.wikipedia.org/wiki/Link_register">link register</a> (the AGC's Q register). To use recursion, a programmer would need to implement their own stack. <a class="footnote-backref" href="#fnref:subroutine" rev="footnote" title="Jump back to footnote 7 in the text">↩</a></p> </li> <li id="fn:carryskip"> <p>A carry-skip circuit improves the performance of the adder. The problem with binary addition is that propagating a carry through all the bits is slow. For example, if you add 111111111111111 + 1, the carry from the low-order bit gets added to the next bit. This generates a carry which propagates to the next bit, and so forth. This "ripple carry" causes the addition to be essentially one bit at a time. To avoid this problem, the AGC uses a <a href="https://en.wikipedia.org/wiki/Carry-skip_adder">carry-skip</a> circuit that looks at groups of four bits. If there is a carry in, and each position has at least one bit set, there is certain to be a carry, so a carry-out is generated immediately. Thus, propagating a carry is approximately three times as fast. (With groups of four bits, you'd expect four times as fast, but the carry-skip circuit has its own overhead.) <a class="footnote-backref" href="#fnref:carryskip" rev="footnote" title="Jump back to footnote 8 in the text">↩</a></p> </li> <li id="fn:logicops"> <p>You might wonder how the AGC performs a variety of arithmetic and logic operations if the arithmetic unit only supports addition. Subtraction is performed by complementing one value (i.e. flipping the bits) and then adding. Most computers have a complement circuit built into the ALU, but the AGC is different: when the B register is read, it can provide either the value or the complement of the stored value.<span id="fnref:complement"><a class="ref" href="#fn:complement" rel="footnote">10</a></span> So to subtract a value, the value is stored in the B register and then the complement is read out and added. <!-- The adder can perform both 1's complement addition and 2's complement addition, controlled by NEACON, which inhibits the end-around carry. See acelectroniclmma00acel.pdf p 4-313. --></p> <p>What about Boolean functions? While most computers implement Boolean functions with logic circuitry in the ALU, the Apollo Guidance Computer manages to implement them without extra hardware. The OR operation is implemented through a trick of the register circuitry. By gating two registers onto the write bus at the same time, a 1 from either register will set the bus high, yielding the OR of the two values. AND is performed using the formula <em>A ∧ H = ~(~A ∨ ~H)</em>; complementing both arguments, doing an OR, and then complementing the result yields the AND operation. XOR is computed using the formula <em>A ⊕ H = ~(A ∨ ~H) ∨ ~(H ∨ ~A)</em>, which uses only complements and ORs. It may seem inefficient to perform so many complement and OR operations, but since the instruction has to take 12 time intervals in any case (due to memory timing), the multiple steps don't slow down the instruction.</p> <p>Multiplication is performed by repeated additions, subtractions, and shifts using a <a href="https://www.digikey.com/eewiki/pages/viewpage.action?pageId=11042852">Radix-4 Booth algorithm</a> that operates two bits at a time. Division is performed by repeated subtractions and shifts.<span id="fnref:division"><a class="ref" href="#fn:division" rel="footnote">11</a></span> <!-- p4-406 in Apoll Lunar Exc. --> <!-- Multiply: p32-98 of blk2 instructions --> Since multiply and divide require multiple steps internally, they are slower than other arithmetic instructions. <a class="footnote-backref" href="#fnref:logicops" rev="footnote" title="Jump back to footnote 9 in the text">↩</a></p> </li> <li id="fn:complement"> <p>Since a latch has outputs for both a bit and the complement of the bit, it is straightforward to get the complemented value out of a latch. Look near the bottom of <a href="https://archive.org/details/agc_handbook_jp2/page/n215">the schematic</a> to see the B register's circuitry that provides the complemented value. <a class="footnote-backref" href="#fnref:complement" rev="footnote" title="Jump back to footnote 10 in the text">↩</a></p> </li> <li id="fn:division"> <p>The AGC's division algorithm is a bit unusual. Instead of subtracting the divisor at each step, a negative dividend / remainder is used through the division and the divisor is added. (This is essentially the same as subtracting the divisor, except everything is complemented.) See <a href="https://www.ibiblio.org/apollo/Documents/agcis_32_blk2_instructions.pdf">Block II Machine Instructions</a> section 32-158 for details. <a class="footnote-backref" href="#fnref:division" rev="footnote" title="Jump back to footnote 11 in the text">↩</a></p> </li> <li id="fn:microprogram"> <p>The AGC doesn't use microcode but confusingly some sources say it was microprogrammed. The book "<a href="https://amzn.to/2VjCTTz">Journey to the Moon</a>" by Eldon Hall (creator of the AGC) says: <!-- p12 --> <blockquote> The instruction selection logic and control matrix was a microprogrammed instruction sequence generator, equivalent to a read-only memory implemented in logic. Outputs of the microprogrammed memory were a sequence of control pulses that were logic products of timing pulses, tests of priority activity, instruction code, and memory address. </blockquote></p> <p>This doesn't make sense, since the whole point of microprogramming is to use read-only memory instead of hardwired control logic. (See <a href="https://people.cs.clemson.edu/~mark/uprog.html">A brief history of microprogramming</a>, <a href="https://amzn.to/2LL0JEB">Computer architecture: A quantitative approach</a> section 5.4, or <a href="https://en.wikipedia.org/wiki/Adder_(electronics)#Full_adder">Microprogramming: principles and practices</a>.) Perhaps Hall means that the AGC's control was "inspired" by microprogramming, using a clearly-stated set of sequenced control signals with control hardware separated from the data path (like most modern computers, hardwired or microcoded). (In contrast, in many 1950s computers (like the IBM 1401) each instruction's circuitry generated its own ad hoc control signals.)</p> <p>By the way, implementing the AGC in microcode would have required about 8 kilobytes of microcode (79 control pulses for about 70 subinstructions with 12 time periods. This would have been impractical for the AGC, especially when you consider that microcode storage needs to be faster than regular storage. <!-- The control pulses are described in detail in the <a href="https://archive.org/details/apollolunarexcuracel_0/page/72">manual</a>. --> <!-- 79 control pulses * 70 subinstructions * 12 time periods = 8295 bytes of microcode storage --> <!-- Confusingly, some AGC <a href="http://tcm.computerhistory.org/ComputerTimeline/Chap7_AGC_CS1.pdf">documents</a> refers to the control signals as a "microprogram", but this is not a microprogram in the microcode sense. --> <a class="footnote-backref" href="#fnref:microprogram" rev="footnote" title="Jump back to footnote 12 in the text">↩</a></p> </li> <li id="fn:subinstructions"> <p>While instructions typically used two subinstructions, there were exceptions. Some instructions, such as multiply and divide, required multiple subinstructions because they took many steps. On the other hand, the jump instruction (TC) used a single subinstruction since fetching the next instruction was the only task to do. <a class="footnote-backref" href="#fnref:subinstructions" rev="footnote" title="Jump back to footnote 13 in the text">↩</a></p> </li> <li id="fn:pla"> <p>Other processors use different approaches to generate control signals. The <a href="http://visual6502.org/wiki/index.php?title=6507_Decode_ROM">6502</a> and many other early microprocessors decoded instructions with a <a href="https://en.wikipedia.org/wiki/Programmable_logic_array">Programmable Logic Array</a> (PLA), a ROM-like way of implementing AND-OR logic. The Z-80 used a PLA, followed by logic very similar to the crosspoint generator to generate the right signals for each time step. Many computers use microcode, storing the sequence of control steps explicitly in ROM. Since minimizing the number of chips in the AGC was critical, optimizing the circuitry was more important than using a clean, structured approach.</p> <p><a href="http://static.righto.com/images/agc-cpu/6502_labeled.jpg"><img alt="Die photo of the 6502 microprocessor. The 6502 used a PLA and random logic for the control logic, which occupies over half the chip. Note the regular, grid-like structure of the PLA. Die photo courtesy of Visual 6502." class="hilite" height="348" src="http://static.righto.com/images/agc-cpu/6502_labeled-w400.jpg" title="Die photo of the 6502 microprocessor. The 6502 used a PLA and random logic for the control logic, which occupies over half the chip. Note the regular, grid-like structure of the PLA. Die photo courtesy of Visual 6502." width="400" /></a><div class="cite">Die photo of the 6502 microprocessor. The 6502 used a PLA and random logic for the control logic, which occupies over half the chip. Note the regular, grid-like structure of the PLA. <a href="http://visual6502.org/images/6502/index.html">Die photo</a> courtesy of Visual 6502.</div></p> <p><!-- --> <a class="footnote-backref" href="#fnref:pla" rev="footnote" title="Jump back to footnote 14 in the text">↩</a></p> </li> <li id="fn:actions"> <p>Each subinstruction's actions at each time interval are described in the <a href="https://archive.org/details/apollolunarexcuracel_0/page/80">manual</a>. The control pulses are described in detail in the <a href="https://archive.org/details/apollolunarexcuracel_0/page/72">manual</a>. (The full set of control pulses for ADS0 are listed <a href="https://archive.org/details/acelectroniclmma00acel/page/n401">here</a>.) <a class="footnote-backref" href="#fnref:actions" rev="footnote" title="Jump back to footnote 15 in the text">↩</a></p> </li> </ol> </div> <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/6264947694886887540/3418953779753810218' onclick=''> 11 comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post/6264947694886887540/3418953779753810218' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=3418953779753810218&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=3418953779753810218&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=3418953779753810218&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=3418953779753810218&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=3418953779753810218&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=3418953779753810218&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/Apollo' rel='tag'>Apollo</a>, <a href='http://www.righto.com/search/label/electronics' rel='tag'>electronics</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='http://static.righto.com/images/analog-opamps/computer-w400.jpg' itemprop='image_url'/> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='1901309647511643034' itemprop='postId'/> <a name='1901309647511643034'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2019/09/reverse-engineering-precision-op-amps.html'>Reverse-engineering precision op amps from a 1969 analog computer</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-1901309647511643034' itemprop='description articleBody'> <p>We are restoring a vintage<span id="fnref:date"><a class="ref" href="#fn:date" rel="footnote">1</a></span> computer that <a href="https://www.youtube.com/user/mverdiell/videos">CuriousMarc</a> recently obtained. Analog computers were formerly popular for fast scientific computation, but pretty much died out in the 1970s. They are interesting, though, as a completely different computing paradigm from digital computers. In this blog post, I'm going to focus on the op amps used in Marc's analog computer, a Simulators Inc. model 240.</p> <p><a href="http://static.righto.com/images/analog-opamps/computer.jpg"><img alt="The Model 240 analog computer from Simulators Inc. was a "precision general purpose analog computer" for the desk top, with up to 24 op amps. (This one has 20 op amps.)" class="hilite" height="497" src="http://static.righto.com/images/analog-opamps/computer-w400.jpg" title="The Model 240 analog computer from Simulators Inc. was a "precision general purpose analog computer" for the desk top, with up to 24 op amps. (This one has 20 op amps.)" width="400" /></a><div class="cite">The Model 240 analog computer from Simulators Inc. was a "precision general purpose analog computer" for the desk top, with up to 24 op amps. (This one has 20 op amps.)</div></p> <h2>What's an analog computer?</h2> <p>An analog computer performs computations using physical, continuously changeable values such as voltages. This is in contrast to a digital computer that uses discrete binary values. Analog computers have a <a href="https://en.wikipedia.org/wiki/Analog_computer#Timeline_of_analog_computers">long history</a> including gear mechanisms, slide rules, wheel-and-disk integrators, tide computers, and mechanical gun targeting systems. The "classic" analog computers of the 1950s and 1960s, however, used op amps and integrators to solve differential equations. <!-- p2 Hausner --> They were typically programmed by plugging cables into a patch panel, yielding a spaghetti-like tangle of wires.</p> <p><a href="http://static.righto.com/images/analog-opamps/analog-wiring.jpg"><img alt="An analog computer was "programmed" by plugging wires into the patch panel. This panel is from an EAI analog computer at the Computer History Museum." class="hilite" height="390" src="http://static.righto.com/images/analog-opamps/analog-wiring-w500.jpg" title="An analog computer was "programmed" by plugging wires into the patch panel. This panel is from an EAI analog computer at the Computer History Museum." width="500" /></a><div class="cite">An analog computer was "programmed" by plugging wires into the patch panel. This panel is from an EAI analog computer at the Computer History Museum.</div></p> <p>The big advantage of analog computers was their speed. They computed results almost instantaneously with their components operating in parallel, while digital computers needed to chug away performing calculations, often for a long time. This made analog computers especially useful for real-time simulations. A disadvantage of analog computers is they were only as accurate as their components; if you wanted 4 digits of accuracy, you needed expensive 0.01% accurate resistors. (In contrast, digital computers can be made as accurate as desired simply by using more bits of precision.) Unfortunately for analog computers, digital computers became exponentially faster and more powerful, so by the 1970s there was little reason to use analog computers.</p> <h2>Inside the analog computer</h2> <p>The heart of the analog computer was its operational amplifiers or op amps. Op amps could sum and scale their inputs, providing basic mathematics. But more importantly, integrators were constructed by combining an op amp with a precision capacitor (below). An integrator computed the integral of its input over time by charging the capacitor. This allowed analog computers to solve differential equations. (It may seem strange that integration, a mathematically sophisticated operation, was a basic building block of analog computers, but that's the way the hardware worked out.)</p> <p><a href="http://static.righto.com/images/analog-opamps/capacitors.jpg"><img alt="The integrators in the analog computer used large precision capacitors. The adjustable capacitor on top is 10 nanofarads, while the large metal box below is an adjustable 10 microfarad capacitor. These capacitors were designed for very low leakage so the integrated value wouldn't leak away. In front are relays to select the capacitors." class="hilite" height="337" src="http://static.righto.com/images/analog-opamps/capacitors-w400.jpg" title="The integrators in the analog computer used large precision capacitors. The adjustable capacitor on top is 10 nanofarads, while the large metal box below is an adjustable 10 microfarad capacitor. These capacitors were designed for very low leakage so the integrated value wouldn't leak away. In front are relays to select the capacitors." width="400" /></a><div class="cite">The integrators in the analog computer used large precision capacitors. The adjustable capacitor on top is 10 nanofarads, while the large metal box below is an adjustable 10 microfarad capacitor. These capacitors were designed for very low leakage so the integrated value wouldn't leak away. In front are relays to select the capacitors.</div></p> <p>Analog computers used multiple potentiometers (below) to set input values and scaling constants. These potentiometers rotated through 10 turns to provide high accuracy. A voltmeter was used to check the potentiometer values. The voltmeter could also be used to display output values, but more often, outputs were displayed on an oscilloscope, strip chart, or X-Y plotter.</p> <p><a href="http://static.righto.com/images/analog-opamps/digital-section.jpg"><img alt="At top, the digital section of the analog computer. The potentiometers are below; some were not installed in this model of the computer. The blank panel in the upper left could hold a digital voltmeter." class="hilite" height="313" src="http://static.righto.com/images/analog-opamps/digital-section-w500.jpg" title="At top, the digital section of the analog computer. The potentiometers are below; some were not installed in this model of the computer. The blank panel in the upper left could hold a digital voltmeter." width="500" /></a><div class="cite">At top, the digital section of the analog computer. The potentiometers are below; some were not installed in this model of the computer. The blank panel in the upper left could hold a digital voltmeter.</div></p> <p>Some analog computers included digital components such as gates, flip flops, one-shots, and counters. This functionality supported more complex techniques, such as iterating through a solution space. Marc's computer has some digital logic, accessed through the colorful patch panel shown above.</p> <!-- ## Programming an analog computer I won't get into the details of programming at this time. The basic idea was to convert the problem into a differential equation. The differential equation was then mapped onto the analog computer circuitry. Starting with the highest-order derivative, lower derivatives For instance, in a second-order differential equation, you'd start with y''(t). Putting it through an integrator yields y'(t). A second integrator yields y(t). Finally, these values are plugged into the equation for y'' (computed with summers, multipliers, etc.) and the result is fed back to yield the original y''. --> <p>The photo below shows the computer partially disassembled. The computer is more complex inside than I expected, with many circuit boards. The patch panel has been removed, revealing the grid of contacts behind it. When a cable is plugged into the patch panel, the cable connects to these contacts, wiring up the program. The computer has five modules behind the patch panel; the leftmost module has been removed and is sitting in front of the computer.<span id="fnref:modules"><a class="ref" href="#fn:modules" rel="footnote">2</a></span> The boards visible at the top of the computer support the digital logic and two analog multipliers. The power supply and circuitry for the front panel are at the bottom.</p> <p><a href="http://static.righto.com/images/analog-opamps/computer-opened.jpg"><img alt="The analog computer with the sides removed to show the internal circuitry. One module has been removed and placed in front of the computer." class="hilite" height="641" src="http://static.righto.com/images/analog-opamps/computer-opened-w500.jpg" title="The analog computer with the sides removed to show the internal circuitry. One module has been removed and placed in front of the computer." width="500" /></a><div class="cite">The analog computer with the sides removed to show the internal circuitry. One module has been removed and placed in front of the computer.</div></p> <p>A closeup of a module is shown below, with the patch panel contacts in front. The module's eight circuit boards can be seen at the back. From left to right, the boards are four op amps (4 boards), miscellaneous circuitry (1 board), and a multiplier (3 boards). Multiplication was surprisingly difficult to implement in an analog computer; the three boards implement a single circuit to multiply two values.<span id="fnref:parabolic"><a class="ref" href="#fn:parabolic" rel="footnote">3</a></span></p> <p><a href="http://static.righto.com/images/analog-opamps/module-front.jpg"><img alt="One of the modules. The "fingers" on front contact plugs inserted into the patch panel. Square high-precision (0.01%) resistors are visible behind the fingers." class="hilite" height="430" src="http://static.righto.com/images/analog-opamps/module-front-w450.jpg" title="One of the modules. The "fingers" on front contact plugs inserted into the patch panel. Square high-precision (0.01%) resistors are visible behind the fingers." width="450" /></a><div class="cite">One of the modules. The "fingers" on front contact plugs inserted into the patch panel. Square high-precision (0.01%) resistors are visible behind the fingers.</div></p> <h2>The op amps</h2> <p>In the above photo, each op amp took up a full board of components. Each board includes an op amp integrated circuit, which raises the question of why so many other components are required. The reason is that analog computers placed heavy demands on op amp performance. In particular, the op amps need to work with signals at DC and at low frequencies, and op amps inconveniently perform poorly in this range, operating better at higher frequencies.</p> <p>In 1949, a solution to op amp problems at low frequencies was developed: the chopper op amp.<span id="fnref:choppers"><a class="ref" href="#fn:choppers" rel="footnote">4</a></span> The idea is that a chopper modulates the input at, say 400 Hz. The op amp happily amplifies this 400-Hz AC signal. A second chopper demodulates the AC output back to DC<span id="fnref:modulation"><a class="ref" href="#fn:modulation" rel="footnote">5</a></span>, providing much better performance than directly amplifying the DC signal.<span id="fnref:choppers"><a class="ref" href="#fn:choppers" rel="footnote">4</a></span> The op amp boards in the analog computer add a chopper circuit to the IC op amp to improve its performance.<span id="fnref:diagram"><a class="ref" href="#fn:diagram" rel="footnote">6</a></span></p> <p>The diagram below shows one of the op amp boards.<span id="fnref:pinout"><a class="ref" href="#fn:pinout" rel="footnote">8</a></span> The op amp's single input<span id="fnref:differential"><a class="ref" href="#fn:differential" rel="footnote">7</a></span> is on the right (separated from all the other connections on the left, to avoid noise). The input is split into three paths. The first path is to the DC chopper amplifier. The signal goes through a low-pass filter (i.e. resistor and capacitor) to extract the DC and low-frequency signal. The chopper itself is pretty simple: a JFET transistor alternately grounds the signal as driven by an external 400 Hz oscillator. This modulated 400 Hz signal is fed to the op amp IC, an Amelco 809 high-performance op amp, introduced in 1967.<span id="fnref:amelco"><a class="ref" href="#fn:amelco" rel="footnote">9</a></span> The IC is in a round metal can; this packaging was common back then and helped shield the op amp from noise. Finally, the IC's output goes through a second chopper and filter to demodulate it.</p> <!-- History of semiconductor engineering page 156 --> <p><a href="http://static.righto.com/images/analog-opamps/op-amp-labeled.jpg"><img alt="An op amp board from the analog computer with functional groups labeled. Even though the board uses an integrated circuit op amp, many additional circuits are necessary to obtain the performance required." class="hilite" height="350" src="http://static.righto.com/images/analog-opamps/op-amp-labeled-w750.jpg" title="An op amp board from the analog computer with functional groups labeled. Even though the board uses an integrated circuit op amp, many additional circuits are necessary to obtain the performance required." width="750" /></a><div class="cite">An op amp board from the analog computer with functional groups labeled. Even though the board uses an integrated circuit op amp, many additional circuits are necessary to obtain the performance required.</div></p> <p>Next, the second input path is combined with the DC amplifier's output. Most op amps are based around a <a href="https://en.wikipedia.org/wiki/Differential_amplifier#Long-tailed_pair">differential pair</a>, and this board is no exception. In a differential pair, two transistors provide high-gain amplification of the difference between two input signals. This differential pair's inputs are the board's input and the signal from the DC chopper amp so it amplifies both the original input and the DC signal. The two transistors in the differential pair need to be exactly balanced for the op amp to function accurately. In particular, the two transistors need to be kept at the same temperature, so they are fastened together with a metal clip (below).</p> <p><a href="http://static.righto.com/images/analog-opamps/transistor-pairs.jpg"><img alt="Critical transistors are held together with metal clips to ensure they stay at the same temperature. The differential pair is on the right, while the transistors on the left buffer the inputs." class="hilite" height="205" src="http://static.righto.com/images/analog-opamps/transistor-pairs-w250.jpg" title="Critical transistors are held together with metal clips to ensure they stay at the same temperature. The differential pair is on the right, while the transistors on the left buffer the inputs." width="250" /></a><div class="cite">Critical transistors are held together with metal clips to ensure they stay at the same temperature. The differential pair is on the right, while the transistors on the left buffer the inputs.</div></p> <p>The third input path goes to the AC amplifier. The input goes through a high-pass filter (resistor and capacitor) and then a simple transistor buffer. This "feedforward" signal is combined with the output from the differential pair to improve the amplifier's frequency response. At this point, the input has been amplified three different ways to yield good low-frequency and high-frequency performance.</p> <!-- Feedforward: Korn & Korn p102 --> <p>The final stage of the op amp board is an output amplifier to provide high-current output for use by the rest of the computer. This amplifier is implemented with a <a href="https://en.wikipedia.org/wiki/Power_amplifier_classes#Class_AB">Class AB</a> amplifier circuit. Individual transistors at the time weren't sufficiently powerful, so it uses two NPN transistors and two PNP transistors to drive the output.</p> <p>Each op amp board has its input and output wired to the patch panel. On the patch panel below, the op amps (A1 through A4) are shaped like pieces of pie; their inputs are green and outputs are red. The op amps used for integrators are also wired to the integration capacitors.</p> <p><a href="http://static.righto.com/images/analog-opamps/plugboard-detail.jpg"><img alt="Detail of the patch panel showing the connections for op amps A1, A3, and A4. The inputs are green and the outputs are red. Initial conditions (IC) are in white. The potentiometer connections are above (yellow)." class="hilite" height="254" src="http://static.righto.com/images/analog-opamps/plugboard-detail-w300.jpg" title="Detail of the patch panel showing the connections for op amps A1, A3, and A4. The inputs are green and the outputs are red. Initial conditions (IC) are in white. The potentiometer connections are above (yellow)." width="300" /></a><div class="cite">Detail of the patch panel showing the connections for op amps A1, A3, and A4. The inputs are green and the outputs are red. Initial conditions (IC) are in white. The potentiometer connections are above (yellow).</div></p> <p>On the patch panel, each op amp has multiple input plugs with different resistor values for scaling; these are the "10" and "100" numbers above. The photo below shows these high-precision resistors (black cylinders) attached directly to the patch panel contacts. Integrator inputs are controlled by relays (below) and electronic switches so the analog computer can initialize the integration capacitors, run the computation, and then hold the result for analysis.</p> <p><a href="http://static.righto.com/images/analog-opamps/patch-panel-back.jpg"><img alt="Resistors (black cylinders) are attached directly to the patch panel contacts. The relays in the middle control the computer's different states: initial constants, operate, and hold. The circuit boards plug into the green connectors at the bottom." class="hilite" height="364" src="http://static.righto.com/images/analog-opamps/patch-panel-back-w500.jpg" title="Resistors (black cylinders) are attached directly to the patch panel contacts. The relays in the middle control the computer's different states: initial constants, operate, and hold. The circuit boards plug into the green connectors at the bottom." width="500" /></a><div class="cite">Resistors (black cylinders) are attached directly to the patch panel contacts. The relays in the middle control the computer's different states: initial constants, operate, and hold. The circuit boards plug into the green connectors at the bottom.</div></p> <h2>Conclusion</h2> <p>Even though op amp integrated circuits existed in the late 1960s, their performance wasn't good enough for analog computers. Instead, a whole board of components was used for a single op amp, combining the IC op amp with a chopper and other circuitry to yield a high-precision op amp. Although improvements in integrated circuits led to exponential increases in digital computer performance, analog computers received much smaller benefits from ICs. As a result, digital computers almost entirely took over and analog computers are now historical artifacts.</p> <p><a href="http://static.righto.com/images/analog-opamps/plugboard.jpg"><img alt="The removable patch panel for the analog computer. The computer was programmed by plugging wires into the holes. The panel is removable, so one programmer could use the analog computer while another is wiring up a panel. (Click to enlarge.)" class="hilite" height="298" src="http://static.righto.com/images/analog-opamps/plugboard-w700.jpg" title="The removable patch panel for the analog computer. The computer was programmed by plugging wires into the holes. The panel is removable, so one programmer could use the analog computer while another is wiring up a panel. (Click to enlarge.)" width="700" /></a><div class="cite">The removable patch panel for the analog computer. The computer was programmed by plugging wires into the holes. The panel is removable, so one programmer could use the analog computer while another is wiring up a panel. (Click to enlarge.)</div></p> <p>You might wonder why I'm studying the circuitry of this analog computer in such detail. The reason is that we're trying to restore the computer, but we don't have documentation.<span id="fnref:documentation"><a class="ref" href="#fn:documentation" rel="footnote">10</a></span><span id="fnref:references"><a class="ref" href="#fn:references" rel="footnote">11</a></span> Thus, I'm reverse-engineering it to determine how to restore it to operating condition and how to program it. While the circuit boards are not too complex, the computer contains many different boards to analyze. The hardest part is figuring out the connectivity of the many tightly-bundled wiring harnesses, mostly by brute-force beeping out connections with a multimeter.</p> <p>You can expect more analog computer posts as we continue the restoration. Follow me on Twitter <a href="https://twitter.com/kenshirriff">@kenshirriff</a> to stay informed of future articles. I also have an <a href="http://www.righto.com/feeds/posts/default">RSS feed</a>.</p> <h2>Notes and references</h2> <div class="footnote"> <ol> <li id="fn:date"> <p>The computer's integrated circuits have 1968 and 1969 date codes on them, so I think the computer was manufactured in 1969. <a class="footnote-backref" href="#fnref:date" rev="footnote" title="Jump back to footnote 1 in the text">↩</a></p> </li> <li id="fn:modules"> <p>When fully populated, the computer has 6 modules behind the patch panel, but the one on the right is missing. At first, we thought the module had been lost at some point, but it appears that this computer was a lower-cost model and was never fully populated. Evidence of this is that 1/4 of the potentiometers above the patch panel are not installed; these potentiometers would be handled by the missing module. <a class="footnote-backref" href="#fnref:modules" rev="footnote" title="Jump back to footnote 2 in the text">↩</a></p> </li> <li id="fn:parabolic"> <p>Analog computers could implement arbitrary functions using diode-resistor networks. (Each diode turned on at a particular input voltage level, and contributed a ramp to the output.) For multiplication, diode-resistor networks were configured to implement a parabolic function (i.e. squaring). Multiplication was implemented through the identity <em>X×Y = ((X+Y)<sup>2</sup> - (X-Y)<sup>2</sup>)/4</em>. The sum and difference were computed using op amps, while squaring was done with the parabolic function generator. <a class="footnote-backref" href="#fnref:parabolic" rev="footnote" title="Jump back to footnote 3 in the text">↩</a></p> </li> <li id="fn:choppers"> <p>Modern chopper op amps use a more complex chopper-stabilizing mechanism, with two op amps. A secondary op amp uses the chopped signal to null out the main op amp. <a href="https://www.analog.com/media/en/training-seminars/tutorials/MT-055.pdf">This tutorial</a> discusses the difference between the classic and modern chopper op amps; there's also a discussion <a href="https://hackaday.com/2018/02/27/chopper-and-chopper-stabilised-amplifiers-what-are-they-all-about-then/">here</a>. The point of this footnote is to avoid confusion between the design of chopper op amps used in the analog computer and modern chopper designs. <a class="footnote-backref" href="#fnref:choppers" rev="footnote" title="Jump back to footnote 4 in the text">↩</a></p> </li> <li id="fn:modulation"> <p>You can sort of think of the chopper as performing amplitude modulation on the signal, like an AM radio signal. However, the demodulation needs to be "phase-sensitive" so it can tell the difference between a positive input and a negative input. This is in contrast to AM-radio demodulation, which can be done with a diode since phase doesn't matter. <a class="footnote-backref" href="#fnref:modulation" rev="footnote" title="Jump back to footnote 5 in the text">↩</a></p> </li> <li id="fn:diagram"> <p>The diagram below (from the <a href="https://archive.org/details/TNM_Simulators_Incorporated_Advanced_Electronic_Simulation_Systems_Brochures/page/n11">brochure</a>) shows the structure of the op amp board. The basic idea is that part of the input goes through a capacitor (i.e. high-pass filter) into the AC amplifier. The input also goes into the "DC stabilizer amplifier", which has a chopper on its input. The output is demodulated and put through a low-pass filter (resistor/capacitor). The two amplifier outputs are combined and fed into the "DC amplifier", the output amplifier.</p> <p><a href="http://static.righto.com/images/analog-opamps/op-amp-schematic.jpg"><img alt="Simplified schematic of the op amp." class="hilite" height="367" src="http://static.righto.com/images/analog-opamps/op-amp-schematic-w500.jpg" title="Simplified schematic of the op amp." width="500" /></a><div class="cite">Simplified schematic of the op amp.</div></p> <p>Note the circuitry for overload detection and protection. In an analog computer, overload can easily happen if any of the values get higher than expected and exceed the op amp limits (+/- 10 volts). This is bad because it will cause the results to be wrong. The op amp detects overload and illuminates a panel light so the user knows there is a problem. An important part of analog computer programming is how to scale everything so the mathematical values fit within the physical limits of the system. <a class="footnote-backref" href="#fnref:diagram" rev="footnote" title="Jump back to footnote 6 in the text">↩</a></p> </li> <li id="fn:differential"> <p>Nowadays, op amps have a positive and negative input. In analog computers, however, op amps usually had just the negative input. Thus, they summed and inverted their inputs. <a class="footnote-backref" href="#fnref:differential" rev="footnote" title="Jump back to footnote 7 in the text">↩</a></p> </li> <li id="fn:pinout"> <p>For reference, I've reverse-engineered the pinout of the op amp board. The input is two shorted pins on the right. The pins along the left of the board (with their connector label) are: <br/>L: balance in <br/>K: chopper ground <br/>J: overload signal out <br/>H: chopper drive in <br/>F: ground <br/>E: ground <br/>D: -15V <br/>C: +15V <br/>B: op amp output <br/>A: unused <a class="footnote-backref" href="#fnref:pinout" rev="footnote" title="Jump back to footnote 8 in the text">↩</a></p> </li> <li id="fn:amelco"> <p>Although now almost forgotten, Amelco was an important semiconductor company producing high-performance op amps. Among other things, Amelco made the first JFET op amp. It was founded by <a href="https://en.wikipedia.org/wiki/Jean_Hoerni">Hoerni</a> (who invented the "planar process" for ICs at Fairchild). I reverse-engineered a hybrid Amelco op amp and discuss the history of Amelco in <a href="http://www.righto.com/2019/02/op-amp-on-moon-reverse-engineering.html">this article</a>. The Amelco 809C op amp datasheet can be found <a href="https://books.google.com/books?id=RcUgBQAAQBAJ&lpg=PR7&dq=809c%20operational%20amplifier%20%22amelco%22%20datasheet&pg=PA35#v=onepage&q&f=false">here</a>. <a class="footnote-backref" href="#fnref:amelco" rev="footnote" title="Jump back to footnote 9 in the text">↩</a></p> </li> <li id="fn:documentation"> <p>As far as documentation on this computer, archive.org has a <a href="https://archive.org/details/TNM_Simulators_Incorporated_Advanced_Electronic_Simulation_Systems_Brochures">Simulators Inc 240 brochure</a> scanned from "<a href="https://archive.org/details/tednelsonjunkmail">Ted Nelson's Junk Mail</a>". The Analog Computer Museum has a brochure in German for the <a href="http://www.analogmuseum.org/english/library.html">Dornier 240</a>, an almost identical computer. (I haven't been able to find out the relationship between Simulators Inc and Dornier, but presumably one company licensed it from the other.) <a class="footnote-backref" href="#fnref:documentation" rev="footnote" title="Jump back to footnote 10 in the text">↩</a></p> </li> <li id="fn:references"> <p>If you're looking for books on analog computers, here are my comments on ones I've read recently: <br><a href="https://amzn.to/3011Qsd">Analog computer programming</a> is a modern book on analog computers, and a good place to start. <br><a href="https://amzn.to/32O5u5A">Introduction to analog computer programming</a> is a reasonable introduction; the PDF is <a href="http://archive.computerhistory.org/resources/access/text/2017/02/102628334-05-01-acc.pdf">online</a>. <br><a href="https://amzn.to/3053W9L">Analog and analog/hybrid computer programming</a> comprehensively explains how to solve many different types of problems. <br><a href="https://amzn.to/302IfI4">Electronic analog and hybrid computers</a> has a detailed discussion of the hardware implementations of analog computers of this era. <br><a href="https://amzn.to/2Q8f69Y">Analog and hybrid computing</a> provides a basic description of analog computers and their programming. <br><a href="https://amzn.to/2LvlS5g">Analog computer techniques</a> is hard to follow and from the vacuum tube era, so I don't recommend it. <a class="footnote-backref" href="#fnref:references" rev="footnote" title="Jump back to footnote 11 in the text">↩</a></p> </li> </ol> </div> <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/6264947694886887540/1901309647511643034' onclick=''> 6 comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post/6264947694886887540/1901309647511643034' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=1901309647511643034&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=1901309647511643034&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=1901309647511643034&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=1901309647511643034&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=1901309647511643034&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=1901309647511643034&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/electronics' rel='tag'>electronics</a>, <a href='http://www.righto.com/search/label/reverse-engineering' rel='tag'>reverse-engineering</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> <div class="date-outer"> <div class="date-posts"> <div class='post-outer'> <div class='post hentry' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='https://i.ytimg.com/vi/Lu4SxJqU9I4/hqdefault.jpg' itemprop='image_url'/> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='2868727481564216307' itemprop='postId'/> <a name='2868727481564216307'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2019/09/risky-line-printer-music-on-vintage-ibm.html'>Risky line printer music on a vintage IBM mainframe</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-2868727481564216307' itemprop='description articleBody'> <style> pre.printer {white-space:pre-wrap; background-color: #eee; border: 1px solid #aaa; font-size:90%;} </style> <p>At the <a href="http://www.computerhistory.org/">Computer History Museum</a>, we recently obtained card decks for a 50-year-old computer music program. Back then, most computers didn't have sound cards but creative programmers found a way to generate music by using the line printer.<span id="fnref:radio"><a class="ref" href="#fn:radio" rel="footnote">2</a></span> We were a bit concerned that the program might destroy the printer, but we took the risk of running it on the vintage IBM 1401 mainframe. As you might expect, music from a line printer sounds pretty bad, but the tunes are recognizable and the printer survived unscathed.<span id="fnref:video"><a class="ref" href="#fn:video" rel="footnote">1</a></span></p> <iframe width="560" height="315" src="https://www.youtube.com/embed/Lu4SxJqU9I4" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> <p>The IBM 1401 business computer was announced in 1959 and went on to become the <a href="http://www-03.ibm.com/ibm/history/ibm100/us/en/icons/mainframe/">best-selling computer</a> of the mid-1960s, with more than 10,000 systems in use. A key selling point of the IBM 1401 was its high-speed line printer, the IBM 1403. By rapidly rotating a chain of characters (below), the printer produced output at high speed (10 lines per second) with excellent print quality, said to be the best printing until laser printers were introduced in the 1970s.</p> <p><a href="http://static.righto.com/images/1401-music/chain.jpg"><img alt="The type chain from the IBM 1401's printer. The chain has 48 different characters, repeated five times." class="hilite" height="123" src="http://static.righto.com/images/1401-music/chain-w700.jpg" title="The type chain from the IBM 1401's printer. The chain has 48 different characters, repeated five times." width="700" /></a><div class="cite">The type chain from the IBM 1401's printer. The chain has 48 different characters, repeated five times.</div></p> <p>Line printers produced a lot of noise, but programmers soon discovered that by printing specific lines of characters, the noise had specific frequencies. It was possible to play a tune by printing the right lines for each note. Around 1970, computer scientist <a href="https://www.cs.sjsu.edu/~mak/">Ron Mak</a> coded up some songs on punch cards using an earlier music program. He recently came across his old programs and gave us the opportunity to try them out.</p> <h2>How the line printer works</h2> <p>To print characters, the printer uses a chain of type slugs that rotates at high speed in front of the paper, with an inked ribbon between the paper and the chain. The printer produces 132-column output so each of the 132 print columns has a hammer and an electromagnet. At the right moment when the desired character passes the hammer, an electromagnet drives the hammer against the back of the paper, causing the paper and ribbon to hit the type slug, printing the character.</p> <p><a href="http://static.righto.com/images/1401-music/chain-diagram.png"><img alt="Printing mechanism of the IBM 1401 line printer. From 1401 Reference Manual, p11." class="hilite" height="373" src="http://static.righto.com/images/1401-music/chain-diagram-w400.png" title="Printing mechanism of the IBM 1401 line printer. From 1401 Reference Manual, p11." width="400" /></a><div class="cite">Printing mechanism of the IBM 1401 line printer. From <a href="http://ibm-1401.info/A24-1403-5_1401_Reference_Apr62--.pdf">1401 Reference Manual</a>, p11.</div></p> <p>The printer required careful timing to make this process work. The chain spins around rapidly at 7.5 feet per second and every 11.1 µs, a print slug lines up with a hammer. The control circuitry has just enough time to read that position's character from core memory, compare it to the character under the hammer, and fire the hammer if there is a match. After 132 time intervals, each hammer has had an opportunity to print one character; this is called a "scan".<span id="fnref:animation"><a class="ref" href="#fn:animation" rel="footnote">3</a></span> Since there are 48 characters in the character set (no lower case), this process must be repeated 48 times so all the characters can be printed in any column.<span id="fnref:printer"><a class="ref" href="#fn:printer" rel="footnote">5</a></span><span id="fnref:motivation"><a class="ref" href="#fn:motivation" rel="footnote">4</a></span> During each scan, the chain moves by just a single character's width<span id="fnref:vernier"><a class="ref" href="#fn:vernier" rel="footnote">6</a></span>.</p> <p><a href="http://static.righto.com/images/1401-music/hammers.jpg"><img alt="A hammer bank in the IBM 1403 printer. At the bottom, the impact points for the 132 hammers (one for each column) are visible. The coils and wiring for 1/4 (33) of the 132 hammers are visible at the top. " class="hilite" height="208" src="http://static.righto.com/images/1401-music/hammers-w500.jpg" title="A hammer bank in the IBM 1403 printer. At the bottom, the impact points for the 132 hammers (one for each column) are visible. The coils and wiring for 1/4 (33) of the 132 hammers are visible at the top. " width="500" /></a><div class="cite">A hammer bank in the IBM 1403 printer. At the bottom, the impact points for the 132 hammers (one for each column) are visible. The coils and wiring for 1/4 (33) of the 132 hammers are visible at the top. </div></p> <p>The photo below is a closeup of a hammer. The electromagnet coil and wires are on the upper left. We had to replace this hammer after the coil overheated and smoked; you can see a blackened region on the coil. (This problem happened a while ago due to a <a href="http://www.righto.com/2018/12/hammer-time-fixing-printer-on-vintage.html">bad circuit board</a>, and is unrelated to the printer music.)</p> <p><a href="http://static.righto.com/images/1401-music/hammer.jpg"><img alt="An individual hammer from the IBM 1403 printer." class="hilite" height="206" src="http://static.righto.com/images/1401-music/hammer-w400.jpg" title="An individual hammer from the IBM 1403 printer." width="400" /></a><div class="cite">An individual hammer from the IBM 1403 printer.</div></p> <h2>Generating music</h2> <p>Now that you see how the printer works, with a hammer potentially firing every 11.1 µs, the strategy to make music should be clearer. By printing carefully-selected text, you can control the times at which hammers fire. By firing hammers at specific intervals, you can create a desired frequency. An A note (440 Hz), for instance, can be produced by printing a line of text that fires the hammers every 1/440th of a second. This can be done by printing a 1 in column 1 (the first hammer to be aligned), followed by a # in column 14 on the next scan, a comma in column 30 the scan after that, and so forth. (There's no real pattern to this; it's just how things line up.<span id="fnref:animation"><a class="ref" href="#fn:animation" rel="footnote">3</a></span>) The full line printed to generate this note is below.<span id="fnref:frequency"><a class="ref" href="#fn:frequency" rel="footnote">7</a></span> (It may be a bit surprising that with a character set of just 48 characters, the printer includes unusual characters such as ⌑ and ‡.)</p> <pre class="printer"> 1 ⌑Y C# 0 Q 3, ‡F R T 4 - , I U $7 M V . * 9N ⌑ ZE @ P3 </pre> <p>The diagram below shows the timing of the hammers, illustrating the uniform 440 Hz frequency produced by the above print line. The diagram has time on the X-axis, with a red bar when each character is printed. The red bars are spaced evenly with a spacing of 1/440th of a second, generating a 440 Hz note. Each bar is labeled with the associated character and column on the page. Note that characters are printed in a different order from how they appear on the line. There's no simple relationship between the arrangement of characters on the line and their time sequence. There are a few gray lines where you'd expect a hammer to fire, but no character is printed. These correspond to times when the chain is syncing up and can't print.</p> <p><a href="http://static.righto.com/images/1401-music/A4.png"><img alt="Timing diagram for the note A4. Each red line indicates a printed character." class="hilite" height="90" src="http://static.righto.com/images/1401-music/A4-w740.png" title="Timing diagram for the note A4. Each red line indicates a printed character." width="740" /></a><div class="cite">Timing diagram for the note A4. Each red line indicates a printed character.</div></p> <p>By printing a different line, a different note can be produced. Below is the note B5, which is 987 Hz (over an octave higher). As you'd expect, the higher-frequency note has more characters. <pre class="printer"> 1 @EQ4S J 8. N D ‡ S H 7 AM Y#2 G- KV . 0 D Q S J 7& N D ‡/4 H AMX0 2 Q G J W. 0 DP‡ S 7&AM ‡/4G * MX0 D 3 </pre></p> <p><a href="http://static.righto.com/images/1401-music/B5.png"><img alt="Timing diagram for the note B5. Each red line indicates a printed character." class="hilite" height="80" src="http://static.righto.com/images/1401-music/B5-w740.png" title="Timing diagram for the note B5. Each red line indicates a printed character." width="740" /></a><div class="cite">Timing diagram for the note B5. Each red line indicates a printed character.</div></p> <p>The printed line for the low note C♯3 (138 Hz) is below. I was puzzled at first why this line (and the other C♯ notes) had all the characters clustered together, rather than scattered across the line like other notes. It turns out that 138 Hz just happens to correspond to hammers that are consecutive on the line. Even though the characters are clumped together on the line, they are spread out uniformly in time. <pre class="printer"> 16#UZKP*E&38 <br /> </pre></p> <p><a href="http://static.righto.com/images/1401-music/CS3.png"><img alt="Timing diagram for the note C♯3." class="hilite" height="90" src="http://static.righto.com/images/1401-music/CS3-w740.png" title="Timing diagram for the note C♯3." width="740" /></a><div class="cite">Timing diagram for the note C♯3.</div></p> <h2>Why chain music might be risky</h2> <p>We were concerned that the print chain music program might damage the printer. There are <a href="https://news.ycombinator.com/item?id=15893800">plenty of stories</a> of people destroying line printers by printing a line that fires all the hammers at once. I think these are mostly urban legends (among other things, the hammers on the 1403 fire one at a time, not all at once). Nonetheless, we were somewhat concerned about chain music overstressing the print chain and breaking it. The photo below shows a print chain that broke during normal use; you can see the broken wires and the individual type slugs.</p> <p><a href="http://static.righto.com/images/1401-music/broken-chain.jpg"><img alt="A broken 1403 print chain. It broke during normal use, not from line printer music. (Photo from TechWorks.)" class="hilite" height="313" src="http://static.righto.com/images/1401-music/broken-chain-w400.jpg" title="A broken 1403 print chain. It broke during normal use, not from line printer music. (Photo from TechWorks.)" width="400" /></a><div class="cite">A broken 1403 print chain. It broke during normal use, not from line printer music. (Photo from <a href="http://www.ctandi.org/vicc1403-chain-rebuild">TechWorks</a>.)</div></p> <p>Print chain were manufactured by winding a thin wire into a band, with type blocks attached. Up until recently, print chains were rare and irreplaceable; if the wire broke, there was no way to fix it. However, the <a href="http://www.ctandi.org/">Techworks!</a> museum in Binghamton, NY recently developed a <a href="http://www.ctandi.org/vicc1403-chain-rebuild">technique</a> to rebuild print chains. Because of this, Frank King (our IBM 1401 guru) approved the use of a rebuilt chain for line printer music, with some trepidation. Fortunately, the chain survived the music generation just fine. (After studying the music program carefully, I think it puts <em>less</em> stress on the chain than the average program, unless there's some really unfortunate resonance.)</p> <p><a href="http://static.righto.com/images/1401-music/typechain.jpg"><img alt="Closeup of the type chain (upside down) for an IBM 1403 line printer." class="hilite" height="162" src="http://static.righto.com/images/1401-music/typechain-w400.jpg" title="Closeup of the type chain (upside down) for an IBM 1403 line printer." width="400" /></a><div class="cite">Closeup of the type chain (upside down) for an IBM 1403 line printer.</div></p> <h2>The program</h2> <p><a href="http://static.righto.com/images/1401-music/PrinterMusicDecks.jpg"><img alt="Card decks to play a variety of songs, courtesy of Ron Mak." class="hilite" height="489" src="http://static.righto.com/images/1401-music/PrinterMusicDecks-w500.jpg" title="Card decks to play a variety of songs, courtesy of Ron Mak." width="500" /></a><div class="cite">Card decks to play a variety of songs, courtesy of Ron Mak.</div></p> <p>The source code to the program is long gone, so I disassembled the <a href="https://gist.github.com/shirriff/9aa707ddb4c418a2758fb49b439b9963">machine code</a> on the cards to determine how the program works (<a href="https://gist.github.com/shirriff/4b3c50ec23715552cb511fb5512b7ca9">listing here</a>). First, it reads "frequency cards" that define what line to print for each note. It builds up an array of print lines in memory, along with a table of note names and addresses of the print lines. Next, the program reads the notes of the song, one note per card. (As you can see above, some songs require many cards.) For each note, it looks up the appropriate print line in the note table. Based on the note's duration, it prints the line the appropriate number of times (using a jump table, not a loop). A rest is implemented by looping 200 to 2000 times to provide silence for the appropriate delay.</p> <p><a href="http://static.righto.com/images/1401-music/code-cards.jpg"><img alt="A closeup of cards with the machine code for the music program. For some reason, the contents of each card are printed twice on the card." class="hilite" height="311" src="http://static.righto.com/images/1401-music/code-cards-w400.jpg" title="A closeup of cards with the machine code for the music program. For some reason, the contents of each card are printed twice on the card." width="400" /></a><div class="cite">A closeup of cards with the machine code for the music program. For some reason, the contents of each card are printed twice on the card.</div></p> <p>Machine code for the 1401 is very different from modern machines. One difference is that <a href="https://en.wikipedia.org/wiki/Self-modifying_code">self-modifying code</a> was very common, while nowadays it is usually frowned upon. For instance, the table of print lines is created by actually modifying load instructions, replacing the address field in the instruction. Even subroutine returns use self-modifying code, putting the return address into a jump instruction at the end of the subroutine. To handle a note, the program generated on-the-fly a sequence of three instructions to load the print line, jump to the print code, and then jump back to the main loop. Self-modifying code made it more challenging for me to understand the program since the disassembled code isn't what actually gets run.</p> <p>The program cards are followed by frequency cards, defining the print line for each note. The code supported up to 20 different notes, so the frequency cards were selected according to the song's need. Each 132-column line is split across two cards, with the first card defining the right half of the line. Each card is punched at the right with the note name and frequency.</p> <p><a href="http://static.righto.com/images/1401-music/frequency-cards.jpg"><img alt="Frequency cards. Each pair of cards defines the 132-character print line that generates the specified note. At the right, the card is punched with the note name (e.g. E4) and frequency (e.g. 329 Hz). The notation F/C labels the first card in the deck." class="hilite" height="283" src="http://static.righto.com/images/1401-music/frequency-cards-w500.jpg" title="Frequency cards. Each pair of cards defines the 132-character print line that generates the specified note. At the right, the card is punched with the note name (e.g. E4) and frequency (e.g. 329 Hz). The notation F/C labels the first card in the deck." width="500" /></a><div class="cite">Frequency cards. Each pair of cards defines the 132-character print line that generates the specified note. At the right, the card is punched with the note name (e.g. E4) and frequency (e.g. 329 Hz). The notation F/C labels the first card in the deck.</div></p> <p>The final set of cards creates the tune, with one card per note (or rest). Each card is punched with a note and duration. A long song may use hundreds of cards. It is straightforward to create a new song, just a matter of punching the tune onto cards. The notes are specified in <a href="https://en.wikipedia.org/wiki/Scientific_pitch_notation">Standard Pitch Notation</a> with the note name followed by an octave number. For example, C4 is middle C. Since only some print chains had the # symbol, sharps were indicated with an "S", e.g. CS for C♯.</p> <p><a href="http://static.righto.com/images/1401-music/note-cards.jpg"><img alt="Closeup of the cards for the song Silver Bells. Each card has the note and octave, followed by its duration. The first card is (confusingly) "END", indicating the end of the frequency cards." class="hilite" height="246" src="http://static.righto.com/images/1401-music/note-cards-w250.jpg" title="Closeup of the cards for the song Silver Bells. Each card has the note and octave, followed by its duration. The first card is (confusingly) "END", indicating the end of the frequency cards." width="250" /></a><div class="cite">Closeup of the cards for the song <i>Silver Bells</i>. Each card has the note and octave, followed by its duration. The first card is (confusingly) "END", indicating the end of the frequency cards.</div></p> <h2>Conclusion</h2> <p>We succeeded in generating music on the IBM 1403 printer, running programs that hadn't been run in almost 50 years. Although the music quality isn't very good, we were happy that the printer didn't self-destruct. Ron Mak last ran these programs in 1970; <a href="https://web.archive.org/web/20060206215721/https:/www.computerhistory.org/exhibits/highlights/">this link</a> has some songs from then, such as <a href="https://web.archive.org/web/20060206215721/https:/www.computerhistory.org/exhibits/highlights/1403_raindrops.mp3">Raindrops keep fallin' on my head</a>. The video below shows an excerpt of <em>La Marseillaise</em>; in this video you can see each line being printed.</p> <iframe width="560" height="315" src="https://www.youtube.com/embed/EfSgdOuFA4s" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> <p>I announce my latest blog posts on Twitter, so follow me at <a href="https://twitter.com/kenshirriff">@kenshirriff</a> for future articles. I also have an <a href="http://www.righto.com/feeds/posts/default">RSS feed</a>. The Computer History Museum in Mountain View runs demonstrations of the IBM 1401 on Wednesdays and Saturdays so if you're in the area you should definitely check it out (<a href="http://www.computerhistory.org/hours/">schedule</a>). Thanks to Ron Mak for supplying the vintage programs, Carl Claunch for reading the cards, and the <a href="http://ibm-1401.info/TeamBios.html">1401 restoration team</a> for running the program, in particular, Robert Garner and Frank King.</p> <h2>Notes and references</h2> <div class="footnote"> <ol> <li id="fn:video"> <p>In case you're wondering why nothing shows up on the printer in the video, the printer's line feed was disabled to save paper. You can see the lines being printed in the video at the end of the article. <a class="footnote-backref" href="#fnref:video" rev="footnote" title="Jump back to footnote 1 in the text">↩</a></p> </li> <li id="fn:radio"> <p>Programmers also used the 1401 to generate music on an AM radio via RF interference. Running the right instruction sequence generated a particular tone. We hope to try this in the future. <a class="footnote-backref" href="#fnref:radio" rev="footnote" title="Jump back to footnote 2 in the text">↩</a></p> </li> <li id="fn:animation"> <p>I've created an animation of the print chain <a href="http://righto.com/ibm1401/printchain.html">here</a> that shows exactly how it works; it's more complex than you'd expect. <a class="footnote-backref" href="#fnref:animation" rev="footnote" title="Jump back to footnote 3 in the text">↩</a></p> </li> <li id="fn:motivation"> <p>The print chain and hammer alignment scheme may seem excessively complicated. But what makes it clever is that the 11.1 µs between hammer times is just enough time to read a character from core memory to see if it matches the chain slug under the hammer, and thus should be printed. In other words, the system is designed to match the mechanical speed of the chain to the electronic speed of core memory. <a class="footnote-backref" href="#fnref:motivation" rev="footnote" title="Jump back to footnote 4 in the text">↩</a></p> </li> <li id="fn:printer"> <p>The printer's operation is explained in detail in the <a href="http://ibm-1401.info/0KenShirriff/IBM_Field_Engineering_Manual_of_Instruction_1403_Printers_225_6492_3.pdf">Field Engineering Manual of Instruction</a>. The section starting on page 37 discusses the chain timing in detail. Each scan is broken down into 3 subscans, but I won't get into that here. Note that while a line is 132 characters, printing a line takes about 150 time intervals (1665 µs); the extra time is used to sync the chain position. (This explains why some notes have "missing" characters in the timing plots.) <a class="footnote-backref" href="#fnref:printer" rev="footnote" title="Jump back to footnote 5 in the text">↩</a></p> </li> <li id="fn:vernier"> <p>The chain only moves 1/1000 of an inch during the 11.1 µs time., but that is enough to line up the next character and hammer. The trick that makes this work is that the hammer spacing and the chain spacing are very slightly different (a <a href="https://en.wikipedia.org/wiki/Vernier_scale">vernier</a> mechanism), so a tiny chain movement causes a much larger change in the alignment position. <a class="footnote-backref" href="#fnref:vernier" rev="footnote" title="Jump back to footnote 6 in the text">↩</a></p> </li> <li id="fn:frequency"> <p>I've archived the code and full set of frequency cards <a href="https://gist.github.com/shirriff/9aa707ddb4c418a2758fb49b439b9963">here</a> for future reference. <a class="footnote-backref" href="#fnref:frequency" rev="footnote" title="Jump back to footnote 7 in the text">↩</a></p> </li> </ol> </div> <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'><span class='post-comment-link'> <a class='comment-link' href='https://www.blogger.com/comment/fullpage/post/6264947694886887540/2868727481564216307' onclick=''> 6 comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post/6264947694886887540/2868727481564216307' title='Email Post'> <img alt='' class='icon-action' height='13' src='http://img1.blogblog.com/img/icon18_email.gif' width='18'/> </a> </span> <span class='item-control blog-admin pid-1138732533'> <a href='https://www.blogger.com/post-edit.g?blogID=6264947694886887540&postID=2868727481564216307&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <span class='post-backlinks post-comment-link'> </span> <div class='post-share-buttons goog-inline-block'> <a class='goog-inline-block share-button sb-email' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=2868727481564216307&target=email' target='_blank' title='Email This'><span class='share-button-link-text'>Email This</span></a><a class='goog-inline-block share-button sb-blog' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=2868727481564216307&target=blog' onclick='window.open(this.href, "_blank", "height=270,width=475"); return false;' target='_blank' title='BlogThis!'><span class='share-button-link-text'>BlogThis!</span></a><a class='goog-inline-block share-button sb-twitter' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=2868727481564216307&target=twitter' target='_blank' title='Share to X'><span class='share-button-link-text'>Share to X</span></a><a class='goog-inline-block share-button sb-facebook' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=2868727481564216307&target=facebook' onclick='window.open(this.href, "_blank", "height=430,width=640"); return false;' target='_blank' title='Share to Facebook'><span class='share-button-link-text'>Share to Facebook</span></a><a class='goog-inline-block share-button sb-pinterest' href='https://www.blogger.com/share-post.g?blogID=6264947694886887540&postID=2868727481564216307&target=pinterest' target='_blank' title='Share to Pinterest'><span class='share-button-link-text'>Share to Pinterest</span></a> </div> </div> <div class='post-footer-line post-footer-line-2'><span class='post-labels'> Labels: <a href='http://www.righto.com/search/label/ibm1401' rel='tag'>ibm1401</a>, <a href='http://www.righto.com/search/label/reverse-engineering' rel='tag'>reverse-engineering</a> </span> </div> <div class='post-footer-line post-footer-line-3'></div> </div> </div> </div> </div></div> </div> <div class='blog-pager' id='blog-pager'> <span id='blog-pager-newer-link'> <a class='blog-pager-newer-link' href='http://www.righto.com/search?updated-max=2020-03-16T08:59:00-07:00&max-results=7&reverse-paginate=true' id='Blog1_blog-pager-newer-link' title='Newer Posts'>Newer Posts</a> </span> <span id='blog-pager-older-link'> <a class='blog-pager-older-link' href='http://www.righto.com/search?updated-max=2019-09-08T08:54:00-07:00&max-results=7' id='Blog1_blog-pager-older-link' title='Older Posts'>Older Posts</a> </span> <a class='home-link' href='http://www.righto.com/'>Home</a> </div> <div class='clear'></div> </div></div> </div> </div> <div class='column-left-outer'> <div class='column-left-inner'> <aside> </aside> </div> </div> <div class='column-right-outer'> <div class='column-right-inner'> <aside> <div class='sidebar section' id='sidebar-right-1'><div class='widget HTML' data-version='1' id='HTML2'> <div class='widget-content'> <style> @import url('https://fonts.googleapis.com/css?family=Montserrat:300,400,500,700'); .form-preview { display: flex; flex-direction: column; justify-content: center; margin-top: 30px; padding: clamp(17px, 5%, 40px) clamp(17px, 7%, 50px); max-width: 350px; min-height: 200px; border-radius: 6px; box-shadow: 0 5px 25px rgba(34, 60, 47, 0.25); } .form-preview, .form-preview *{ box-sizing: border-box; } .form-preview .preview-heading { width: 100%; } .form-preview .preview-heading h5{ margin-top: 0; margin-bottom: 0; } .form-preview .preview-input-field { margin-top: 20px; width: 100%; } .form-preview .preview-input-field input { width: 100%; height: 40px; border-radius: 6px; border: 2px solid #e9e8e8; background-color: #fff; outline: none; } .form-preview .preview-input-field input::placeholder, .form-preview .preview-input-field input { opacity: 0.5; color: #000; font-family: "Montserrat"; font-size: 14px; font-weight: 500; line-height: 20px; text-align: center; } .form-preview .preview-submit-button { margin-top: 10px; width: 100%; } .form-preview .preview-submit-button button { width: 100%; height: 40px; border: 0; border-radius: 6px; line-height: 0px; } .form-preview .preview-submit-button button:hover { cursor: pointer; } </style><form data-v-4c58e686="" action="https://api.follow.it/subscription-form/U3NBTmZKVkI1YVpCa000a0RCZHFiQ3FYMko1cWRTZTN6K3hJdWM2QWxJbE1uVXdXUHZZVzJVQzVLZGh5Y0RCVXB2d2JSTzBobGhuY0FsZnlHbVdFZ2VTN2Q4Vy84RnIxUTgzVlcrbXNIR0Y0aW93d3REM2J6VS9RL0gxWURnV1d8ZWN0YStwUWdWWUFiOTIyWDVGWjdYYVdGZEVNcC9qODZacjlwWXRIcEJQRT0=/8" method="post"><div data-v-4c58e686="" class="form-preview" style="background-color: rgb(255, 255, 255); border-style: solid; border-width: 1px; border-color: rgb(204, 204, 204); position: relative;"><div data-v-4c58e686="" class="preview-heading"><h5 data-v-4c58e686="" style="font-family: Montserrat; font-weight: bold; color: rgb(0, 0, 0); font-size: 12px; text-align: center;">Get new posts by email:</h5></div> <div data-v-4c58e686="" class="preview-input-field"><input data-v-4c58e686="" type="email" name="email" placeholder="Enter your email" spellcheck="false" /></div> <div data-v-4c58e686="" class="preview-submit-button"><button data-v-4c58e686="" type="submit" style="font-family: Montserrat; font-weight: bold; color: rgb(255, 255, 255); font-size: 12px; text-align: center; background-color: rgb(0, 0, 0);">Subscribe</button></div></div></form> </div> <div class='clear'></div> </div><div class='widget HTML' data-version='1' id='HTML3'> <h2 class='title'>About the site</h2> <div class='widget-content'> <a href="https://www.righto.com/p/index.html">Contact info and site index</a> </div> <div class='clear'></div> </div><div class='widget PopularPosts' data-version='1' id='PopularPosts1'> <h2>Popular Posts</h2> <div class='widget-content popular-posts'> <ul> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2025/03/mother-of-all-demos-usb-keyset-interface.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_spiLG2hBec7yXFa_x81KDnFOmlUW4AoeuJBRj--Mtr9D8ncFcg9iPOTFdmY9I3PA-KhgKhtO7P7375UnQUg6T_K4QiFSlYAlaTWh8D2_u7SlaRajHKYe3mLczJaFGjlTc=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2025/03/mother-of-all-demos-usb-keyset-interface.html'>A USB interface to the "Mother of All Demos" keyset</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2025/03/pentium-microcde-rom-circuitry.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_sAvVt7addu3DIvXwt94IQWTltvvEerJe44iDBx0T0LkHyVDZprtVxT_GccteVwCJof9l-KbtGr0KFg8A38LmEYG4JDm5CMTcT8pG7piyOr2P-fIAxkc37aWUrlvavOjedqUfkbZpOnEqnubn9nMfo=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2025/03/pentium-microcde-rom-circuitry.html'>Notes on the Pentium's microcode circuitry</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2025/03/pentium-multiplier-adder-reverse-engineered.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_sN7ufCAX0R_soxQG_NjYs8v2aOUzj3oSi5e36P_kNJ2-YYXeGyiYEXnHIpr22H_taaiJHH53StSjyHhv-t1Ujr19hmEtxDTOyYuJEELO3F0MQcq8BzO9-mLkcD5LbkvVroUCe6IJlQLnHs=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2025/03/pentium-multiplier-adder-reverse-engineered.html'>The Pentium contains a complicated circuit to multiply by three</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2024/05/blog-post.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_umU9XcohOWUFzpc269BRfqSEuO_QNrA7i4gnfzSN2NNcjmppZWQ0SKlvj5-5eka_SEKUsvp2Hmw4PBlm3SjcWGOMoGxwnGI4kIbrmIrWAg0zh8of6TEGtIdDyvYIQXtpe37KdkV7NZA7SU0u4JiuTa=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2024/05/blog-post.html'>Inside a vintage aerospace navigation computer of uncertain purpose</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_uBLgwfReRIDCeQycBC2-JFJ9AY5FgOSBivpvYxRqM--3Uw0gi2DtZkENIawZNJ8lR4a5Z4OG0wa2_VF28nkwplGoLXfcxAPngSmg4cDna3IDk=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html'>A Multi-Protocol Infrared Remote Library for the Arduino</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2012/10/a-dozen-usb-chargers-in-lab-apple-is.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_uxGMw0gbm8t28b0TEsquX_bGCAQNcnVHN3ZUVFEL05YfOFHjglfrvN-6NTjf2JTjuaR0N1TgQLE4n5UY1L77qgUY2RgGFFWb3dWcRL0mzaJDSmzA6Wd8HQmCD7D9Q=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2012/10/a-dozen-usb-chargers-in-lab-apple-is.html'>A dozen USB chargers in the lab: Apple is very good, but not quite the best</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2012/05/apple-iphone-charger-teardown-quality.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_suTBWNv1SpYv-8TNS-S6R5YZjnZ-GpOqKStLnnvivlF3yDWdhraT2Wk_EOgF2dB7cYmZaD0Tu8TcjHscF_zhpOoFRQDi-V5tVUKJcenGiLQd9qg3v7IacNsxC_Vv1TYQj2470423axeFH6Xm9zXe9bhRY=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2012/05/apple-iphone-charger-teardown-quality.html'>Apple iPhone charger teardown: quality in a tiny expensive package</a></div> </div> <div style='clear: both;'></div> </li> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2014/09/mining-bitcoin-with-pencil-and-paper.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_upXyT37C-mwvj2EgjJD9xJHPxUXXPEqhww1yZoQWh2IjU8JXf1_eK31pFlsxr6y0-bBjGdkIqfxFsCaY68p6hnDM0m9Bu6x5Ron2MrWF-9d-6OPqZcgvqJttZzY0wO8WRy=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2014/09/mining-bitcoin-with-pencil-and-paper.html'>Mining Bitcoin with pencil and paper: 0.67 hashes per day</a></div> </div> <div style='clear: both;'></div> </li> </ul> <div class='clear'></div> </div> </div><div class='widget BlogSearch' data-version='1' id='BlogSearch1'> <h2 class='title'>Search This Blog</h2> <div class='widget-content'> <div id='BlogSearch1_form'> <form action='http://www.righto.com/search' class='gsc-search-box' target='_top'> <table cellpadding='0' cellspacing='0' class='gsc-search-box'> <tbody> <tr> <td class='gsc-input'> <input autocomplete='off' class='gsc-input' name='q' size='10' title='search' type='text' value=''/> </td> <td class='gsc-search-button'> <input class='gsc-search-button' title='search' type='submit' value='Search'/> </td> </tr> </tbody> </table> </form> </div> </div> <div class='clear'></div> </div><div class='widget Label' data-version='1' id='Label1'> <h2>Labels</h2> <div class='widget-content cloud-label-widget-content'> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/386'>386</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/6502'>6502</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/8008'>8008</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/8085'>8085</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/8086'>8086</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/8087'>8087</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/8088'>8088</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/aerospace'>aerospace</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/alto'>alto</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/analog'>analog</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/Apollo'>Apollo</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/apple'>apple</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/arc'>arc</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/arduino'>arduino</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/arm'>arm</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/beaglebone'>beaglebone</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/bitcoin'>bitcoin</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/c%23'>c#</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/cadc'>cadc</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/calculator'>calculator</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/chips'>chips</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/css'>css</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/datapoint'>datapoint</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/dx7'>dx7</a> </span> <span class='label-size label-size-5'> <a dir='ltr' href='http://www.righto.com/search/label/electronics'>electronics</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/f%23'>f#</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/fairchild'>fairchild</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/fpga'>fpga</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/fractals'>fractals</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/genome'>genome</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/globus'>globus</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/haskell'>haskell</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/HP'>HP</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/html5'>html5</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/ibm'>ibm</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/ibm1401'>ibm1401</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/ibm360'>ibm360</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/intel'>intel</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/ipv6'>ipv6</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/ir'>ir</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/java'>java</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/javascript'>javascript</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/math'>math</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/microcode'>microcode</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/oscilloscope'>oscilloscope</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/Pentium'>Pentium</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/photo'>photo</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/power%20supply'>power supply</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/random'>random</a> </span> <span class='label-size label-size-5'> <a dir='ltr' href='http://www.righto.com/search/label/reverse-engineering'>reverse-engineering</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/sheevaplug'>sheevaplug</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/snark'>snark</a> </span> <span class='label-size label-size-3'> <a dir='ltr' href='http://www.righto.com/search/label/space'>space</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/spanish'>spanish</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/synth'>synth</a> </span> <span class='label-size label-size-4'> <a dir='ltr' href='http://www.righto.com/search/label/teardown'>teardown</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/theory'>theory</a> </span> <span class='label-size label-size-1'> <a dir='ltr' href='http://www.righto.com/search/label/unicode'>unicode</a> </span> <span class='label-size label-size-2'> <a dir='ltr' href='http://www.righto.com/search/label/Z-80'>Z-80</a> </span> <div class='clear'></div> </div> </div><div class='widget BlogArchive' data-version='1' id='BlogArchive1'> <h2>Blog Archive</h2> <div class='widget-content'> <div id='ArchiveList'> <div id='BlogArchive1_ArchiveList'> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2025/'> 2025 </a> <span class='post-count' dir='ltr'>(8)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2025/03/'> March </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2025/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2025/01/'> January </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/'> 2024 </a> <span class='post-count' dir='ltr'>(21)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/12/'> December </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/11/'> November </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/10/'> October </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/09/'> September </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/08/'> August </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/07/'> July </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/06/'> June </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/04/'> April </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/03/'> March </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/02/'> February </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2024/01/'> January </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/'> 2023 </a> <span class='post-count' dir='ltr'>(35)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/12/'> December </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/11/'> November </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/10/'> October </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/09/'> September </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/08/'> August </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/07/'> July </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/04/'> April </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/03/'> March </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/02/'> February </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2023/01/'> January </a> <span class='post-count' dir='ltr'>(8)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/'> 2022 </a> <span class='post-count' dir='ltr'>(18)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/11/'> November </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/07/'> July </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/06/'> June </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/04/'> April </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/03/'> March </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/02/'> February </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2022/01/'> January </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/'> 2021 </a> <span class='post-count' dir='ltr'>(26)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/12/'> December </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/11/'> November </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/09/'> September </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/07/'> July </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/06/'> June </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/04/'> April </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/03/'> March </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/02/'> February </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2021/01/'> January </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/'> 2020 </a> <span class='post-count' dir='ltr'>(33)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/11/'> November </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/10/'> October </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/09/'> September </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/08/'> August </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/07/'> July </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/06/'> June </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/05/'> May </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/04/'> April </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/03/'> March </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2020/01/'> January </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate expanded'> <a class='toggle' href='javascript:void(0)'> <span class='zippy toggle-open'> ▼  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/'> 2019 </a> <span class='post-count' dir='ltr'>(18)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/11/'> November </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/10/'> October </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate expanded'> <a class='toggle' href='javascript:void(0)'> <span class='zippy toggle-open'> ▼  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/09/'> September </a> <span class='post-count' dir='ltr'>(3)</span> <ul class='posts'> <li><a href='http://www.righto.com/2019/09/a-computer-built-from-nor-gates-inside.html'>A computer built from NOR gates: inside the Apollo...</a></li> <li><a href='http://www.righto.com/2019/09/reverse-engineering-precision-op-amps.html'>Reverse-engineering precision op amps from a 1969 ...</a></li> <li><a href='http://www.righto.com/2019/09/risky-line-printer-music-on-vintage-ibm.html'>Risky line printer music on a vintage IBM mainframe</a></li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/07/'> July </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/04/'> April </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/01/'> January </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/'> 2018 </a> <span class='post-count' dir='ltr'>(17)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/12/'> December </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/09/'> September </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/06/'> June </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/04/'> April </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/03/'> March </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2018/01/'> January </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/'> 2017 </a> <span class='post-count' dir='ltr'>(21)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/12/'> December </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/11/'> November </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/10/'> October </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/07/'> July </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/06/'> June </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/04/'> April </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/03/'> March </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2017/01/'> January </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/'> 2016 </a> <span class='post-count' dir='ltr'>(34)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/10/'> October </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/09/'> September </a> <span class='post-count' dir='ltr'>(8)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/08/'> August </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/07/'> July </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/06/'> June </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/04/'> April </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/03/'> March </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/02/'> February </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2016/01/'> January </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/'> 2015 </a> <span class='post-count' dir='ltr'>(12)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/11/'> November </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/10/'> October </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/05/'> May </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/03/'> March </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2015/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/'> 2014 </a> <span class='post-count' dir='ltr'>(13)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/12/'> December </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/10/'> October </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/09/'> September </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/05/'> May </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/03/'> March </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2014/02/'> February </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/'> 2013 </a> <span class='post-count' dir='ltr'>(24)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/11/'> November </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/09/'> September </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/08/'> August </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/07/'> July </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/06/'> June </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/04/'> April </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/03/'> March </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/02/'> February </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2013/01/'> January </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/'> 2012 </a> <span class='post-count' dir='ltr'>(10)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/12/'> December </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/11/'> November </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/10/'> October </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/05/'> May </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/03/'> March </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2012/02/'> February </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/'> 2011 </a> <span class='post-count' dir='ltr'>(11)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/07/'> July </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/05/'> May </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/04/'> April </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/03/'> March </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2011/02/'> February </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/'> 2010 </a> <span class='post-count' dir='ltr'>(22)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/11/'> November </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/10/'> October </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/08/'> August </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/06/'> June </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/05/'> May </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/04/'> April </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/03/'> March </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2010/01/'> January </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/'> 2009 </a> <span class='post-count' dir='ltr'>(22)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/12/'> December </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/11/'> November </a> <span class='post-count' dir='ltr'>(5)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/09/'> September </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/08/'> August </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/07/'> July </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/06/'> June </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/04/'> April </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/03/'> March </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/02/'> February </a> <span class='post-count' dir='ltr'>(2)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2009/01/'> January </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/'> 2008 </a> <span class='post-count' dir='ltr'>(27)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/07/'> July </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/06/'> June </a> <span class='post-count' dir='ltr'>(1)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/05/'> May </a> <span class='post-count' dir='ltr'>(3)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/04/'> April </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/03/'> March </a> <span class='post-count' dir='ltr'>(10)</span> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2008/02/'> February </a> <span class='post-count' dir='ltr'>(6)</span> </li> </ul> </li> </ul> </div> </div> <div class='clear'></div> </div> </div></div> </aside> </div> </div> </div> <div style='clear: both'></div> <!-- columns --> </div> <!-- main --> </div> </div> <div class='main-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> <footer> <div class='footer-outer'> <div class='footer-cap-top cap-top'> <div class='cap-left'></div> <div class='cap-right'></div> </div> <div class='fauxborder-left footer-fauxborder-left'> <div class='fauxborder-right footer-fauxborder-right'></div> <div class='region-inner footer-inner'> <div class='foot no-items section' id='footer-1'></div> <table border='0' cellpadding='0' cellspacing='0' class='section-columns columns-2'> <tbody> <tr> <td class='first columns-cell'> <div class='foot no-items section' id='footer-2-1'></div> </td> <td class='columns-cell'> <div class='foot no-items section' id='footer-2-2'></div> </td> </tr> </tbody> </table> <!-- outside of the include in order to lock Attribution widget --> <div class='foot section' id='footer-3'><div class='widget Attribution' data-version='1' id='Attribution1'> <div class='widget-content' style='text-align: center;'> Powered by <a href='https://www.blogger.com' target='_blank'>Blogger</a>. </div> <div class='clear'></div> </div></div> </div> </div> <div class='footer-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </footer> <!-- content --> </div> </div> <div class='content-cap-bottom cap-bottom'> <div class='cap-left'></div> <div class='cap-right'></div> </div> </div> </div> <script type='text/javascript'> window.setTimeout(function() { document.body.className = document.body.className.replace('loading', ''); }, 10); </script> <script type="text/javascript" src="https://www.blogger.com/static/v1/widgets/2806328968-widgets.js"></script> <script type='text/javascript'> window['__wavt'] = 'AOuZoY4fuKdEPGnxf9fg82YCwadFyNA0Xg:1743842666743';_WidgetManager._Init('//www.blogger.com/rearrange?blogID\x3d6264947694886887540','//www.righto.com/2019/09/','6264947694886887540'); _WidgetManager._SetDataContext([{'name': 'blog', 'data': {'blogId': '6264947694886887540', 'title': 'Ken Shirriff\x27s blog', 'url': 'http://www.righto.com/2019/09/', 'canonicalUrl': 'http://www.righto.com/2019/09/', 'homepageUrl': 'http://www.righto.com/', 'searchUrl': 'http://www.righto.com/search', 'canonicalHomepageUrl': 'http://www.righto.com/', 'blogspotFaviconUrl': 'http://www.righto.com/favicon.ico', 'bloggerUrl': 'https://www.blogger.com', 'hasCustomDomain': true, 'httpsEnabled': false, 'enabledCommentProfileImages': true, 'gPlusViewType': 'FILTERED_POSTMOD', 'adultContent': false, 'analyticsAccountNumber': 'UA-3782444-1', 'encoding': 'UTF-8', 'locale': 'en', 'localeUnderscoreDelimited': 'en', 'languageDirection': 'ltr', 'isPrivate': false, 'isMobile': false, 'isMobileRequest': false, 'mobileClass': '', 'isPrivateBlog': false, 'isDynamicViewsAvailable': true, 'feedLinks': '\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22Ken Shirriff\x26#39;s blog - Atom\x22 href\x3d\x22http://www.righto.com/feeds/posts/default\x22 /\x3e\n\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/rss+xml\x22 title\x3d\x22Ken Shirriff\x26#39;s blog - RSS\x22 href\x3d\x22http://www.righto.com/feeds/posts/default?alt\x3drss\x22 /\x3e\n\x3clink rel\x3d\x22service.post\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22Ken Shirriff\x26#39;s blog - Atom\x22 href\x3d\x22https://www.blogger.com/feeds/6264947694886887540/posts/default\x22 /\x3e\n', 'meTag': '', 'adsenseHostId': 'ca-host-pub-1556223355139109', 'adsenseHasAds': false, 'adsenseAutoAds': false, 'boqCommentIframeForm': true, 'loginRedirectParam': '', 'view': '', 'dynamicViewsCommentsSrc': '//www.blogblog.com/dynamicviews/4224c15c4e7c9321/js/comments.js', 'dynamicViewsScriptSrc': '//www.blogblog.com/dynamicviews/c4ef6ff9ae7c94eb', 'plusOneApiSrc': 'https://apis.google.com/js/platform.js', 'disableGComments': true, 'interstitialAccepted': false, 'sharing': {'platforms': [{'name': 'Get link', 'key': 'link', 'shareMessage': 'Get link', 'target': ''}, {'name': 'Facebook', 'key': 'facebook', 'shareMessage': 'Share to Facebook', 'target': 'facebook'}, {'name': 'BlogThis!', 'key': 'blogThis', 'shareMessage': 'BlogThis!', 'target': 'blog'}, {'name': 'X', 'key': 'twitter', 'shareMessage': 'Share to X', 'target': 'twitter'}, {'name': 'Pinterest', 'key': 'pinterest', 'shareMessage': 'Share to Pinterest', 'target': 'pinterest'}, {'name': 'Email', 'key': 'email', 'shareMessage': 'Email', 'target': 'email'}], 'disableGooglePlus': true, 'googlePlusShareButtonWidth': 0, 'googlePlusBootstrap': '\x3cscript type\x3d\x22text/javascript\x22\x3ewindow.___gcfg \x3d {\x27lang\x27: \x27en\x27};\x3c/script\x3e'}, 'hasCustomJumpLinkMessage': false, 'jumpLinkMessage': 'Read more', 'pageType': 'archive', 'pageName': 'September 2019', 'pageTitle': 'Ken Shirriff\x27s blog: September 2019'}}, {'name': 'features', 'data': {}}, {'name': 'messages', 'data': {'edit': 'Edit', 'linkCopiedToClipboard': 'Link copied to clipboard!', 'ok': 'Ok', 'postLink': 'Post Link'}}, {'name': 'template', 'data': {'name': 'custom', 'localizedName': 'Custom', 'isResponsive': false, 'isAlternateRendering': false, 'isCustom': true}}, {'name': 'view', 'data': {'classic': {'name': 'classic', 'url': '?view\x3dclassic'}, 'flipcard': {'name': 'flipcard', 'url': '?view\x3dflipcard'}, 'magazine': {'name': 'magazine', 'url': '?view\x3dmagazine'}, 'mosaic': {'name': 'mosaic', 'url': '?view\x3dmosaic'}, 'sidebar': {'name': 'sidebar', 'url': '?view\x3dsidebar'}, 'snapshot': {'name': 'snapshot', 'url': '?view\x3dsnapshot'}, 'timeslide': {'name': 'timeslide', 'url': '?view\x3dtimeslide'}, 'isMobile': false, 'title': 'Ken Shirriff\x27s blog', 'description': 'Computer history, restoring vintage computers, IC reverse engineering, and whatever', 'url': 'http://www.righto.com/2019/09/', 'type': 'feed', 'isSingleItem': false, 'isMultipleItems': true, 'isError': false, 'isPage': false, 'isPost': false, 'isHomepage': false, 'isArchive': true, 'isLabelSearch': false, 'archive': {'year': 2019, 'month': 9, 'rangeMessage': 'Showing posts from September, 2019'}}}]); _WidgetManager._RegisterWidget('_HeaderView', new _WidgetInfo('Header1', 'header', document.getElementById('Header1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogView', new _WidgetInfo('Blog1', 'main', document.getElementById('Blog1'), {'cmtInteractionsEnabled': false}, 'displayModeFull')); _WidgetManager._RegisterWidget('_HTMLView', new _WidgetInfo('HTML2', 'sidebar-right-1', document.getElementById('HTML2'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_HTMLView', new _WidgetInfo('HTML3', 'sidebar-right-1', document.getElementById('HTML3'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_PopularPostsView', new _WidgetInfo('PopularPosts1', 'sidebar-right-1', document.getElementById('PopularPosts1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogSearchView', new _WidgetInfo('BlogSearch1', 'sidebar-right-1', document.getElementById('BlogSearch1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_LabelView', new _WidgetInfo('Label1', 'sidebar-right-1', document.getElementById('Label1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogArchiveView', new _WidgetInfo('BlogArchive1', 'sidebar-right-1', document.getElementById('BlogArchive1'), {'languageDirection': 'ltr', 'loadingMessage': 'Loading\x26hellip;'}, 'displayModeFull')); _WidgetManager._RegisterWidget('_AttributionView', new _WidgetInfo('Attribution1', 'footer-3', document.getElementById('Attribution1'), {}, 'displayModeFull')); </script> </body> </html>