CINXE.COM
Ken Shirriff's blog: beaglebone
<!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/search/label/beaglebone' 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" /> <link rel="me" href="https://www.blogger.com/profile/08097301407311055124" /> <!--Can't find substitution for tag [blog.ieCssRetrofitLinks]--> <meta content='http://www.righto.com/search/label/beaglebone' 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: beaglebone</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/6aez4K2oVqwIvtU2Gw.eot);}</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=68bed08c-0595-4d46-96e9-d7a36a9f26b5' media='none' onload='if(media!='all')media='all'' rel='stylesheet'/><noscript><link href='https://www.blogger.com/dyn-css/authorization.css?targetBlogID=6264947694886887540&zx=68bed08c-0595-4d46-96e9-d7a36a9f26b5' 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 itemscope='itemscope' itemtype='http://schema.org/Blog' style='display: none;'> <meta content='Ken Shirriff's blog' itemprop='name'/> </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='status-msg-wrap'> <div class='status-msg-body'> Showing posts with label <b>beaglebone</b>. <a href="http://www.righto.com/">Show all posts</a> </div> <div class='status-msg-border'> <div class='status-msg-bg'> <div class='status-msg-hidden'>Showing posts with label <b>beaglebone</b>. <a href="http://www.righto.com/">Show all posts</a></div> </div> </div> </div> <div style='clear: both;'></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://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRI0TjIrzjXIzKCqUffIiUxOQfmLHQq8jwO421gGbg6mNaLHcWlcPsab4MXh8Ztgv3umpp-QrdDyCXEi-KQyyJ1YUgHzZzplN-Cfv_LRho1MrIrfyILD1NcfDtclb4gsfd9ot_GBxKM4NL/w400/vga-cable.jpg' itemprop='image_url'/> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='9125414566564773488' itemprop='postId'/> <a name='9125414566564773488'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2018/03/reading-vga-monitors-configuration-data.html'>Reading a VGA monitor's configuration data with I2C and a PocketBeagle</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-9125414566564773488' itemprop='description articleBody'> <style> pre {border:none;background-color:#eee;min-width:40em;padding:4px;display:inline-block;font-size:80%;line-height:120%;} code {background-color:#eee;} </style> <p>Have you ever wondered how your computer knows all the characteristics of your monitor— the supported resolutions, the model, and even the serial number? Most monitors use a system called <a href="https://en.wikipedia.org/wiki/Display_Data_Channel">DDC</a> to communicate this information to the computer.<span id="fnref:ddc"><a class="ref" href="#fn:ddc" rel="footnote">1</a></span> This information is transmitted using the I<sup>2</sup>C communication protocol—a protocol also popular for connecting hobbyist devices. In this post, I look inside a VGA monitor cable, use a tiny PocketBeagle (a single-board computer in the BeagleBone family) to read the I2C data from an LCD monitor, and then analyze this data.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRI0TjIrzjXIzKCqUffIiUxOQfmLHQq8jwO421gGbg6mNaLHcWlcPsab4MXh8Ztgv3umpp-QrdDyCXEi-KQyyJ1YUgHzZzplN-Cfv_LRho1MrIrfyILD1NcfDtclb4gsfd9ot_GBxKM4NL/w9999/vga-cable.jpg"><img alt="Inside a VGA cable. The cable is more complex than I expected, with multiple layers of shields. The green, red, white (sync) and blue wires are thicker and have their own shielding." class="hilite" height="359" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRI0TjIrzjXIzKCqUffIiUxOQfmLHQq8jwO421gGbg6mNaLHcWlcPsab4MXh8Ztgv3umpp-QrdDyCXEi-KQyyJ1YUgHzZzplN-Cfv_LRho1MrIrfyILD1NcfDtclb4gsfd9ot_GBxKM4NL/w400/vga-cable.jpg" title="Inside a VGA cable. The cable is more complex than I expected, with multiple layers of shields. The green, red, white (sync) and blue wires are thicker and have their own shielding." width="400" /></a><div class="cite">Inside a VGA cable. The cable is more complex than I expected, with multiple layers of shields. The green, red, white (sync) and blue wires are thicker and have their own shielding.</div></p> <p>To connect to the monitor, I cut a VGA cable in half and figured out which wire goes to which pin.<span id="fnref:connector"><a class="ref" href="#fn:connector" rel="footnote">3</a></span> The wire (above) is constructed in an interesting way, more complicated than I expected. The red, green, blue and horizontal sync signals are transmitted over coaxial-like cables formed by wrapping a wire a spiral of thin copper wires for shielding.<span id="fnref:coax"><a class="ref" href="#fn:coax" rel="footnote">2</a></span> The remaining signals travel over thinner plain wires. Several strands of string form the structural center of the VGA cable, and the ten internal wires are wrapped in a foil shield and woven outer shield.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2aqQI3FRNl2OfMn4dpdN3gvAFpMXFTgURx1Sy9tzUEkeMnQWta8e4ThAKtsQqaymc4_dyh5NgfaI-NlUakNdl2HB8MV9JsvgFgEHGpD6qOTLMex7Shnl0QimpWbuzDKrb4L_OJR5EgxxU/w9999/vga-connector.jpg"><img alt="The VGA connector consists of 3 rows of 5 pins. Pins are simply numbered left-to-right with 1 through 5 in the first row, 6-10 in the second, and 11-15 in the third. (Click image for a closeup.) " class="hilite" height="166" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2aqQI3FRNl2OfMn4dpdN3gvAFpMXFTgURx1Sy9tzUEkeMnQWta8e4ThAKtsQqaymc4_dyh5NgfaI-NlUakNdl2HB8MV9JsvgFgEHGpD6qOTLMex7Shnl0QimpWbuzDKrb4L_OJR5EgxxU/w350/vga-connector.jpg" title="The VGA connector consists of 3 rows of 5 pins. Pins are simply numbered left-to-right with 1 through 5 in the first row, 6-10 in the second, and 11-15 in the third. (Click image for a closeup.) " width="350" /></a><div class="cite">The VGA connector consists of 3 rows of 5 pins. Pins are simply numbered left-to-right with 1 through 5 in the first row, 6-10 in the second, and 11-15 in the third. (Click image for a closeup.) </div></p> <p>The photo above shows the male <a href="https://en.wikipedia.org/wiki/VGA_connector">VGA connector</a> on each end of the cable. The function assigned to each pin is shown in the table below. The I<sup>2</sup>C clock (SCL) and data (SDA) are the important pins for this project. The wire colors are not standardized; they refer to my VGA cable and may be different for a different cable.</p> <style> table#vga {border-collapse: collapse;font-size: 90%;} table#vga th {text-align: center; border-bottom: 1px solid #333} table#vga td {text-align: center; padding: 0 8px;} table#vga tr.ul {border-bottom: 1px solid #888;} </style> <table id="vga"><tr><th>Pin</th><th>Function</th><th>Wire color</th></tr> <tr><td>1</td><td>Red</td><td>Red coax</td></tr> <tr><td>2</td><td>Green</td><td>Green coax</td></tr> <tr><td>3</td><td>Blue</td><td>Blue coax</td></tr> <tr><td>4</td><td>Reserved</td><td>Shield</td></tr> <tr class="ul"><td>5</td><td>Ground</td><td>Black</td></tr> <tr><td>6</td><td>Red Ground</td><td>Shield</td></tr> <tr><td>7</td><td>Green Ground</td><td>Shield</td></tr> <tr><td>8</td><td>Blue Ground</td><td>Shield</td></tr> <tr><td>9</td><td>5V</td><td>Yellow</td></tr> <tr class="ul"><td>10</td><td>Ground</td><td>White</td></tr> <tr><td>11</td><td>Reserved</td><td>Shield</td></tr> <tr><td>12</td><td>SDA</td><td>Green</td></tr> <tr><td>13</td><td>HSync</td><td>White coax</td></tr> <tr><td>14</td><td>VSync</td><td>Brown</td></tr> <tr><td>15</td><td>SCL</td><td>Red</td></tr> </table> <p>The 5 volt wire in the cable has a clever purpose. This wire allows the computer to power the EEPROM chip that provides the configuration data. Thus, the computer can query the display's characteristics even if the display is turned off or even unplugged from the wall.</p> <h2>Reading the configuration data</h2> <p>To read the data over I<sup>2</sup>C, I used the <a href="http://www.righto.com/2017/12/hands-on-with-pocketbeagle-tiny-25.html">PocketBeagle</a>, a tiny Linux computer that I had handy. (You could use a different system that supports I<sup>2</sup>C, such as the <a href="https://learn.adafruit.com/adafruits-raspberry-pi-lesson-4-gpio-setup/configuring-i2c">Raspberry Pi</a>, <a href="https://www.teachmemicro.com/beaglebone-black-i2c-tutorial/">Beaglebone</a> or <a href="https://howtomechatronics.com/tutorials/arduino/how-i2c-communication-works-and-how-to-use-it-with-arduino/">Arduino</a>.) I simply connected the I<sup>2</sup>C clock (SCL), data (SDA) and ground wires from the VGA cable to the PocketBeagle's I<sup>2</sup>C pins as shown below.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfpaZnlYVkkeeIlsca6KZDiIhSTprdsXRxSonjmBLKXT8Oh00lTfZDJkut7lEMF1Jd5-1D7E5EWCc62Apz5zswPJR5aPfSCat8qBp5F8F2pQvytuWg7ZYMjVgxt9zdiAT0DBYN_XLl3rJH/w9999/pocketbeagle-vga.jpg"><img alt="Connecting a VGA cable to the PocketBeagle allows the configuration data to be read over I2C. The black wire is ground, the green wire is I2C data (SDA) and the red wire is I2C clock (SCL)." class="hilite" height="290" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfpaZnlYVkkeeIlsca6KZDiIhSTprdsXRxSonjmBLKXT8Oh00lTfZDJkut7lEMF1Jd5-1D7E5EWCc62Apz5zswPJR5aPfSCat8qBp5F8F2pQvytuWg7ZYMjVgxt9zdiAT0DBYN_XLl3rJH/w500/pocketbeagle-vga.jpg" title="Connecting a VGA cable to the PocketBeagle allows the configuration data to be read over I2C. The black wire is ground, the green wire is I2C data (SDA) and the red wire is I2C clock (SCL)." width="500" /></a><div class="cite">Connecting a VGA cable to the PocketBeagle allows the configuration data to be read over I<sup>2</sup>C. The black wire is ground, the green wire is I<sup>2</sup>C data (SDA) and the red wire is I<sup>2</sup>C clock (SCL).</div></p> <p>Simple Linux commands let me access I<sup>2</sup>C. First, I probed the I<sup>2</sup>C bus to see what devices were present, using the <code>i2cdetect</code> command. (Many devices can be connected to an I<sup>2</sup>C bus, each assigned a different address.) The output below shows that devices 30, 37, 4a, 4b and 50 responded on I<sup>2</sup>C bus 1. Device 50 is the relevant I<sup>2</sup>C device, assigned to the configuration information. Device 37 is <a href="https://en.wikipedia.org/wiki/Display_Data_Channel#DDC/CI">DDC/CI</a>, allowing monitor settings to be controlled by the computer, but I'll ignore it for this post. Devices 30, 4a, and 4b are a mystery to me so leave a comment if you know what they are. <pre> $ i2cdetect -y -r 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: 30 -- -- -- -- -- -- 37 -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- 4a 4b -- -- -- -- 50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- </pre></p> <p>Next, I used the <code>i2cdump</code> command to read 128 bytes from device 50's registers, providing the raw VGA information. The hex values are on the left and ASCII is on the right. <pre> $ i2cdump -y -r 0-127 1 0x50 b 0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef 00: 00 ff ff ff ff ff ff 00 04 69 fa 22 01 01 01 01 ........?i?"???? 10: 12 19 01 03 1e 30 1b 78 ea 3d 25 a3 59 51 a0 25 ?????0?x?=%?YQ?% 20: 0f 50 54 bf ef 00 71 4f 81 80 81 40 95 00 a9 40 ?PT??.qO???@?.?@ 30: b3 00 d1 c0 01 01 02 3a 80 18 71 38 2d 40 58 2c ?.?????:??q8-@X, 40: 45 00 dd 0c 11 00 00 1e 00 00 00 fd 00 32 4c 1e E.???..?...?.2L? 50: 53 11 00 0a 20 20 20 20 20 20 00 00 00 fc 00 56 S?.? ...?.V 60: 45 32 32 38 0a 20 20 20 20 20 20 20 00 00 00 ff E228? .... 70: 00 46 34 4c 4d 51 53 31 32 38 35 34 36 0a 00 bb .F4LMQS128546?.? </pre></p> <h2>Understanding the monitor's EDID data</h2> <p>The configuration data is encoded in the <a href="https://en.wikipedia.org/wiki/Extended_Display_Identification_Data">EDID</a> (Extended Display Identification Data) format, so it's not immediately obvious what the data means. But the format is <a href="https://en.wikipedia.org/wiki/Extended_Display_Identification_Data#EDID_1.4_data_format">well-documented</a>, so it's not too hard to figure out. For instance, the first 8 bytes <code>00 ff ff ff ff ff ff 00</code> are the header. The next two bytes <code>04 69</code> encode three 5-bit characters for the manufacturer ID, in this case "ACI" - Asus Computer International. (The data format uses a lot of annoying bit manipulations like these to make the data compact.) Near the end of the output, the ASCII strings "VE228" and "F4LMQS128546" are clearly visible; these are the monitor's model number and serial number.</p> <p>I made a <a href="https://gist.github.com/shirriff/dd9e35da12879cf1c5ed9ed92ff704ec">simple Python program</a> to decode the data, giving the following results: <pre style="max-height:18em;overflow:auto;white-space:pre-wrap;width:48em"> Header: Manufacturer: ACI Product code: 8954 Week: 18 Year: 2008 Edid version 1, revision 3 Analog input Levels: +0.7/-.03 Blank-to-black setup (pedestal) expected Separate sync supported Composite sync supported Sync on green supported Horizontal screen size: 48cm Vertical screen size: 27cm Display gamma: 2.200 DPMS standby supported DPMS suspend supported DPMS active-off supported Display type (analog): RGB color Preferred timing mode in descriptor block 1 Chromaticity coordinates: r: (0.637, 0.351), g: (0.319, 0.626), b: (0.145, 0.061), w: (0.313, 0.329) Established timings: 720x400 @ 70 Hz 640x480 @ 60 Hz 640x480 @ 67 Hz 640x480 @ 72 Hz 640x480 @ 75 Hz 800x600 @ 56 Hz 800x600 @ 60 Hz 800x600 @ 72 Hz 800x600 @ 75 Hz 832x624 @ 75 Hz 1024x768 @ 60 Hz 1024x768 @ 72 Hz 1024x768 @ 75 Hz 1280x1024 @ 75 Hz Standard timing information: X res: 1152, aspect 4:3, Y res (derived): 864), vertical frequency: 75 X res: 1280, aspect 5:4, Y res (derived): 1024), vertical frequency: 60 X res: 1280, aspect 4:3, Y res (derived): 960), vertical frequency: 60 X res: 1440, aspect 16:10, Y res (derived): 900), vertical frequency: 60 X res: 1600, aspect 4:3, Y res (derived): 1200), vertical frequency: 60 X res: 1680, aspect 16:10, Y res (derived): 1050), vertical frequency: 60 X res: 1920, aspect 16:9, Y res (derived): 1080), vertical frequency: 60 Descriptor 1: Detailed timing descriptor: Pixel clock: 148500kHz Horizontal active pixels: 1920 Horizontal blanking pixels: 280 Vertical active lines: 1080 Vertical blanking lines: 45 Horizontal front porch pixels: 88 Horizontal sync pulse pixels: 44 Vertical front porch lines: 4 Vertical sync pulse lines: 5 Horizontal image size: 477mm Vertical image size: 268mm Horizontal border pixels: 0 Vertical border lines: 0 Digital separate sync VSync serration Positive horizontal sync polarity Descriptor 2: Display range limits Minimum vertical field rate 50Hz Maximum vertical field rate 76Hz Minimum horizontal field rate 30Hz Maximum horizontal field rate 83Hz Maximum pixel clock rate: 170Mhz Default GTF Descriptor 3: Display name VE228 Descriptor 4: Display serial number F4LMQS128546 </pre></p> <p>As you can see, the EDID format crams a lot of configuration information into 128 bytes. The output starts off with some basic data about the monitor's characteristics and inputs. The VGA standard doesn't nail down as many things as you'd hope. For instance the <a href="https://en.wikipedia.org/wiki/Component_video_sync">sync signals</a> can be provided on one wire (composite), two wires (separate), or on the green wire. The output above shows my monitor supports all three sync types.</p> <p>The monitor then provides a long list of supported resolutions, which is how your computer knows what the monitor supports. The "detailed timing descriptor" provides more information on signal voltage levels and timings. The timing of VGA signals contains some strange features (e.g. blanking and "front porch") inherited from obsolete CRT (Cathode Ray Tube) displays. The values in the configuration provide the information necessary for the computer's graphics board to synthesize a proper VGA signal that the monitor can understand.</p> <p>The CIE chromaticity coordinates provided by the monitor are interesting, but need a bit of background to understand. A <a href="https://en.wikipedia.org/wiki/CIE_1931_color_space#CIE_xy_chromaticity_diagram_and_the_CIE_xyY_color_space">CIE chromaticity diagram</a> (below), shows all the colors in the real world. (Brightness is factored out, so grays and browns don't appear.) Individual wavelengths of light (i.e. the spectrum) curve around the outside of the diagram. The colors inside the curve are combinations of the pure spectral colors, with white in the middle.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPL1Dc4kOJZzc1X_HBKgcCzuYztdTq4CorPiGXkFrrsGYqm5L9dzWhwMh6DwfU3FBrCnMqExbTps0aLJfHSgJctK6cHDaFqN6LhT-bD1KJ-qdqNeGEVc94B1IHoPePbK_3bh99EWYyu0Fy/w9999/cie.jpg"><img alt="CIE diagram showing the color gamut and white point of my monitor." class="hilite" height="485" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPL1Dc4kOJZzc1X_HBKgcCzuYztdTq4CorPiGXkFrrsGYqm5L9dzWhwMh6DwfU3FBrCnMqExbTps0aLJfHSgJctK6cHDaFqN6LhT-bD1KJ-qdqNeGEVc94B1IHoPePbK_3bh99EWYyu0Fy/w450/cie.jpg" title="CIE diagram showing the color gamut and white point of my monitor." width="450" /></a><div class="cite">CIE diagram showing the color gamut and white point of my monitor.</div></p> <p>A display, however, generates its colors by combining red, green, and blue. The result is that a display can only show the colors inside the triangle above with red, green, and blue at the corners. A display doesn't generate the light wavelengths necessary to display colors outside the triangle. Like most monitors, this monitor can only show a surprisingly small fraction of the possible colors. (A <a href="https://en.wikipedia.org/wiki/Wide-gamut_RGB_color_space">wide-gamut display</a> uses different phosphors to expand the triangle and get more vivid colors.) The triangle vertices and white point<span id="fnref:d65"><a class="ref" href="#fn:d65" rel="footnote">4</a></span> in the diagram above come from the x,y chromaticity coordinates in the configuration data.</p> <p>You might wonder how you can see the whole CIE diagram on your display if only the colors inside the triangle can be displayed. The answer is the diagram "cheats"—the colors are scaled to fit into RGB values, so you're not seeing the exact colors but just an approximate representation. If you look at the spectrum through a prism, for instance, the colors will be more intense than what you see in the CIE diagram.</p> <h2>Inside I<sup>2</sup>C</h2> <p>The I<sup>2</sup>C protocol (Inter-Integrated Circuit) was <a href="https://learn.sparkfun.com/tutorials/i2c">invented in 1982</a> by Philips Semiconductor to connect a CPU to peripheral chips inside televisions. It's now a popular protocol for many purposes, including connecting sensors, small LED displays, and other devices to microcontrollers. Many I<sup>2</sup>C products are available from <a href="https://www.sparkfun.com/search/results?term=i2c&tab=products">Adafruit</a> and <a href="https://www.adafruit.com/?q=i2c">Sparkfun</a> for instance.</p> <p>The I<sup>2</sup>C protocol provides a simple, medium-speed way to connect multiple devices on a bus using just two wires—one for a clock and one for data. I<sup>2</sup>C is a serial protocol, but it differs from serial protocols like RS-232 in a couple ways. First, I<sup>2</sup>C is synchronous (using a clock), unlike RS-232 which is asynchronous (no clock). Second, I<sup>2</sup>C is a bus and can connect dozens of devices, while RS-232 connects two devices.<span id="fnref:moreinfo"><a class="ref" href="#fn:moreinfo" rel="footnote">5</a></span></p> <p>The oscilloscope trace below shows what an I<sup>2</sup>C communication with the monitor looks like on the wire. The top line (cyan) shows the clock. Note that the clock only runs while data is transmitted.) The yellow line is the binary data. At the bottom, the oscilloscope decoded the data (green). In this trace, register number 0x26 is being read from device 0x50. The I<sup>2</sup>C protocol is rather peculiar since a read is performed by doing a write followed by a read. That is, to read a byte, the master first does a write to the device of the desired register number: the master first sends 0x50 (the device ID) the write flag bit (indicated with "W:50"), and 0x26 (the register number, ASCII "&"). Then, the master does a read; it sends 0x50 and the read flag bit ("R:50"). The device responds with the value in the register, 0x71 (ASCII "q").<span id="fnref:complications"><a class="ref" href="#fn:complications" rel="footnote">6</a></span></p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0L1THAD2lJUF7ZBnEPruRDJ_CdKFoV1wcTloha-J3xP-YMPppKzemft2Jgvt701_T_Kgox6PIeqV23-Fu5nLtxNYJAxjNjuzkNSpkP5HFnLDf_9tPSIqOEe795HDNsyAiyNbPR6vinlu-/w9999/i2c-oscilloscope.png"><img alt="I2C trace: clock (SCL) in cyan and data (SDA) in yellow. Green shows decoded data. Oscilloscope was set to 20&micro;s/division and 2V/division." class="hilite" height="255" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0L1THAD2lJUF7ZBnEPruRDJ_CdKFoV1wcTloha-J3xP-YMPppKzemft2Jgvt701_T_Kgox6PIeqV23-Fu5nLtxNYJAxjNjuzkNSpkP5HFnLDf_9tPSIqOEe795HDNsyAiyNbPR6vinlu-/w601/i2c-oscilloscope.png" title="I2C trace: clock (SCL) in cyan and data (SDA) in yellow. Green shows decoded data. Oscilloscope was set to 20&micro;s/division and 2V/division." width="601" /></a><div class="cite">I<sup>2</sup>C trace: clock (SCL) in cyan and data (SDA) in yellow. Green shows decoded data. Oscilloscope was set to 20µs/division and 2V/division.</div></p> <p>Devices on the I<sup>2</sup>C bus can only pull a line low; pull-up resistors keeps the lines high by default.<span id="fnref:pullup"><a class="ref" href="#fn:pullup" rel="footnote">7</a></span> As a result, the traces above drop low sharply, but climb back up slowly.<span id="fnref:rc"><a class="ref" href="#fn:rc" rel="footnote">8</a></span> Even though the transitions look sloppy, the I<sup>2</sup>C bus worked fine. I couldn't find a source to tell me if VGA monitors included pull-up resistors, or if I needed to add them externally. However, I measured voltage on the lines coming from the monitor and everything worked without external resistors, so there must be pull-up resistors inside the monitor.</p> <h2>Conclusion</h2> <p>The VGA specification includes a data link that allows a computer to learn about a monitor and configure it appropriately. It is straightforward to read this configuration data using the I<sup>2</sup>C protocol and a board with an I<sup>2</sup>C port. While VGA is <a href="https://hackaday.com/2016/01/29/vga-in-memoriam/">mostly obsolete</a> now, the same data protocol is used with DVI and HDMI displays. My goal in reading the monitor's config data was so I could use the timing data in an FPGA to generate a VGA video signal. (That project is yet to come.) Follow me on <a href="https://twitter.com/kenshirriff">Twitter</a> or <a href="http://www.righto.com/feeds/posts/default">RSS</a> to find out about my latest blog posts.</p> <h2>Notes and references</h2> <div class="footnote"> <ol> <li id="fn:ddc"> <p>DDC (Display Data Channel) is used by VGA, DVI and HDMI connections, which transmit the data over two I<sup>2</sup>C pins. The data it sends is in the <a href="https://en.wikipedia.org/wiki/Extended_Display_Identification_Data">EDID</a> (Extended Display Identification Data) format. Everything changed with the <a href="https://en.wikipedia.org/wiki/DisplayPort">DisplayPort</a> interface. It transmits configuration data over a differential AUX channel using the <a href="https://en.wikipedia.org/wiki/DisplayID">DisplayID</a> format, which extends EDID to supports newer features such as 3D displays. Thus, the techniques I describe in this article should work with DVI or HDMI interfaces, but won't work with DisplayPort. <a class="footnote-backref" href="#fnref:ddc" rev="footnote" title="Jump back to footnote 1 in the text">↩</a></p> </li> <li id="fn:coax"> <p>Looking at other VGA cables on the web, most VGA cables don't have the fourth coax for horizontal sync that my cable does. So my cable seems a bit unusual. <a class="footnote-backref" href="#fnref:coax" rev="footnote" title="Jump back to footnote 2 in the text">↩</a></p> </li> <li id="fn:connector"> <p>Instead of cutting a VGA cable in half, I could have simply plugged a cable into a VGA connector, but that's less interesting. <a class="footnote-backref" href="#fnref:connector" rev="footnote" title="Jump back to footnote 3 in the text">↩</a></p> </li> <li id="fn:d65"> <p>The white point for my monitor matches a standard called <a href="https://en.wikipedia.org/wiki/Illuminant_D65">D65</a>. <a class="footnote-backref" href="#fnref:d65" rev="footnote" title="Jump back to footnote 4 in the text">↩</a></p> </li> <li id="fn:moreinfo"> <p>For more information on I<sup>2</sup>C, good explanations are on <a href="https://learn.sparkfun.com/tutorials/i2c">SparkFun</a> and <a href="https://en.wikipedia.org/wiki/I%C2%B2C">Wikipedia</a>. <a class="footnote-backref" href="#fnref:moreinfo" rev="footnote" title="Jump back to footnote 5 in the text">↩</a></p> </li> <li id="fn:complications"> <p>I'm leaving out some of the complications of I<sup>2</sup>C. For example, the master generates the clock, but the device can do "clock stretching" by holding the clock low until it is ready. Also, the device sends an ACK bit after each request. The device address is 7 bits, while the data is 8 bits. See <a href="http://www.ti.com/lit/an/slva704/slva704.pdf">protocol documentation</a> for details. <a class="footnote-backref" href="#fnref:complications" rev="footnote" title="Jump back to footnote 6 in the text">↩</a></p> </li> <li id="fn:pullup"> <p>Using a pull-up resistor on the I<sup>2</sup>C bus avoids the risk of short circuits. If, alternatively, devices could actively pull the line high, it would be a problem if one device tried to pull a line high at the same time another pulled it low. <a class="footnote-backref" href="#fnref:pullup" rev="footnote" title="Jump back to footnote 7 in the text">↩</a></p> </li> <li id="fn:rc"> <p>The oscilloscope traces show exponential R-C charging curves when the line is pulled high. This is due to the wire capacitance being charged through the pull-up resistor. The signals only reach about 3V, making them suitable for the PocketBeagle's 3.3V inputs. (If you try this with a different monitor, check the voltage levels to avoid damaging the PocketBeagle's inputs.) <a class="footnote-backref" href="#fnref:rc" rev="footnote" title="Jump back to footnote 8 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/9125414566564773488' onclick=''> 7 comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=9125414566564773488' 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=9125414566564773488&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=9125414566564773488&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=9125414566564773488&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=9125414566564773488&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=9125414566564773488&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=9125414566564773488&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/beaglebone' rel='tag'>beaglebone</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='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOp5b76CpWTRn2CIdgbch7po9zeBn5AjVihaCyQZrIR2LPTKzuZXy9eH5mcTEMMinquPpH3e0Ip1kM08MetgNmZk6bhD_e1T7d9eP4OFPS_wjur5EvG1jvomKewk_yW-tctDZWnIzuRNjr/w400/inside-transceiver.jpg' itemprop='image_url'/> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='1182972412801248728' itemprop='postId'/> <a name='1182972412801248728'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2018/01/xerox-altos-3-mbs-ethernet-building.html'>Xerox Alto's 3 Mb/s Ethernet: Building a gateway with a BeagleBone</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-1182972412801248728' itemprop='description articleBody'> <style> code {background-color:#eee;font-size: 80%;} .gist table.lines { font-size: 12px; line-height: 10px; } .gist-meta { font-size: 80% !important; } .gist .blob-num { line-height: 10px !important;} .gist .blob-code { line-height: 10px !important;} </style> <p>The Alto was a revolutionary computer designed at Xerox PARC in 1973. It introduced the GUI, high-resolution bitmapped displays, the optical mouse and laser printers to the world. But one of its most important contributions was Ethernet, the local area network that is still heavily used today. While modern Ethernets handle up to 100 gigabits per second, the Alto's Ethernet was much slower, just 3 megabits per second over coaxial cable. Even so, the Alto used the Ethernet for file servers, email, distributed games, network boot, and even voice over Ethernet.</p> <p>The Alto's 3 Mb/s Ethernet isn't compatible with modern Ethernet, making it difficult to transfer data between an Alto and the outside world. To solve this, I built a gateway using the BeagleBone single-board computer to communicate with the Alto's Ethernet. In this article I discuss how the Alto's Ethernet works and how I implemented the gateway.</p> <h2>The Alto's Ethernet hardware</h2> <p>The Alto's Ethernet used a coaxial cable, rather than modern twisted-pair cable. A transceiver box was the interface between the Alto and the cable, converting the Alto's logic signals to the signals on the cable. In the photo below, you can see a transceiver clamped onto the coaxial cable; a "vampire tap" punctures the cable making contact with the central conductor.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOp5b76CpWTRn2CIdgbch7po9zeBn5AjVihaCyQZrIR2LPTKzuZXy9eH5mcTEMMinquPpH3e0Ip1kM08MetgNmZk6bhD_e1T7d9eP4OFPS_wjur5EvG1jvomKewk_yW-tctDZWnIzuRNjr/w9999/inside-transceiver.jpg"><img alt="Inside a transceiver box. The "vampire tap" on the right connects the transceiver to the Ethernet cable. The connector on the left goes to the Alto." class="hilite" height="299" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOp5b76CpWTRn2CIdgbch7po9zeBn5AjVihaCyQZrIR2LPTKzuZXy9eH5mcTEMMinquPpH3e0Ip1kM08MetgNmZk6bhD_e1T7d9eP4OFPS_wjur5EvG1jvomKewk_yW-tctDZWnIzuRNjr/w400/inside-transceiver.jpg" title="Inside a transceiver box. The "vampire tap" on the right connects the transceiver to the Ethernet cable. The connector on the left goes to the Alto." width="400" /></a><div class="cite">Inside a transceiver box. The "vampire tap" on the right connects the transceiver to the Ethernet cable. The connector on the left goes to the Alto.</div></p> <p>The Alto's Ethernet uses Manchester encoding of the bits. That is, a "1" is sent as "10" and a "0" is sent as "01". The reason to do this instead of just sending the raw bits is the Manchester encoding is self-clocking—there's a transition for every bit. If instead you just sent a raw stream of bits, e.g. "00000000000", the receiver would have a hard time knowing where the bits start and end. The figure below shows how <code>0110</code> is transmitted with Manchester encoding.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhX4sQTPOebOOZRdAKDLExsktro7tIA0Debxr1v3DOwggUBjLxvPMLwIqElwuMbgOvhAdaAPWPqvCRtyK4NGPEiQqgtt7b9hfO-RtQjeGH_jmNmo_BUNS1m_UletfrSWCZYZMbBzwfOD4mN/w9999/waveform1.png"><img alt="An example of Manchester encoding, for the bits 0110." class="hilite" height="92" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhX4sQTPOebOOZRdAKDLExsktro7tIA0Debxr1v3DOwggUBjLxvPMLwIqElwuMbgOvhAdaAPWPqvCRtyK4NGPEiQqgtt7b9hfO-RtQjeGH_jmNmo_BUNS1m_UletfrSWCZYZMbBzwfOD4mN/w250/waveform1.png" title="An example of Manchester encoding, for the bits 0110." width="250" /></a><div class="cite">An example of Manchester encoding, for the bits 0110.</div></p> <h2>The Alto's network protocols</h2> <p>The Alto predates TCP/IP, instead using a protocol called Pup (the PARC Universal Packet).<span id="fnref:pup"><a class="ref" href="#fn:pup" rel="footnote">1</a></span> The protocol has many similarities with TCP/IP, since the Pup designers influenced the TCP design based on their experience. The basic Pup Internet Datagram is analogous to an IP packet. A packet contains a destination address for the packet consisting of a network id (1 byte), a host id on the network (1 byte), and a 4-byte socket. A machine's host id is specified by jumper wires on the backplane (below). Thus, packets can be routed through a large network to the right machine.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOxgT41YfDtmkPvgi7J5DAuVtEm2umvs0GiSewUZYAYUdEsGu4YzYcgTThfT_ik9ThMpAuIcORdvHYf_wsZBtCCQD4V2fVTnCDpmtHIO1BjnmN4K7iKlnzvpJBrf0Nw8Bu5Lsa6cK7Ctf1/w9999/backplane-jumpers.jpg"><img alt="Long blue jumper wires on the Alto's backplane specify the system's Ethernet address." class="hilite" height="288" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOxgT41YfDtmkPvgi7J5DAuVtEm2umvs0GiSewUZYAYUdEsGu4YzYcgTThfT_ik9ThMpAuIcORdvHYf_wsZBtCCQD4V2fVTnCDpmtHIO1BjnmN4K7iKlnzvpJBrf0Nw8Bu5Lsa6cK7Ctf1/w250/backplane-jumpers.jpg" title="Long blue jumper wires on the Alto's backplane specify the system's Ethernet address." width="250" /></a><div class="cite">Long blue jumper wires on the Alto's backplane specify the system's Ethernet address.</div></p> <p>Some simple network operations just exchanged Pup packets, for example requesting the time from a network server. But for more complex operations, Xerox built layers on top of Pup. For a long-lived connection between two machines, Xerox built RTP (Rendezvous/Termination Protocol), a protocol to establish connections between two ports. This is analogous to a TCP socket connection. Once the connection is established, the computers can communicate using Byte Steam Protocol (BSP). This protocol handles error correction and flow control, very similar to TCP.</p> <p>On top of these protocols, Xerox implemented email, FTP (File Transfer Protocol), network boot, networked games such as <a href="https://en.wikipedia.org/wiki/Maze_War">Maze War</a>, network error reporting, network disk backups and the first <a href="https://people.eecs.berkeley.edu/~prabal/resources/osprelim/SH82.pdf">computer worm</a>.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOXyCHkYQwDeilqYN_nhnJH8ZymxqRaU0OmeBc0_WE2babYaxiNLstH_HOPm9vvY9uawBh0LNrNtnFnf4F0q5i36wMlG2V9aNMOYPlmIx3cDCpUUzs7Rc9HtV8L7TvZiZXid3LLiYsN0xw/w9999/network-map.png"><img alt="Map of the Xerox PARC network, showing important servers. May 1978. From Alto User's Primer." class="hilite" height="504" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOXyCHkYQwDeilqYN_nhnJH8ZymxqRaU0OmeBc0_WE2babYaxiNLstH_HOPm9vvY9uawBh0LNrNtnFnf4F0q5i36wMlG2V9aNMOYPlmIx3cDCpUUzs7Rc9HtV8L7TvZiZXid3LLiYsN0xw/w500/network-map.png" title="Map of the Xerox PARC network, showing important servers. May 1978. From Alto User's Primer." width="500" /></a><div class="cite">Map of the Xerox PARC network, showing important servers. May 1978. From <a href="http://xeroxalto.computerhistory.org/_cd8_/altodocs/.altousersprimer.press!2.pdf">Alto User's Primer</a>.</div></p> <h2>Designing an Ethernet gateway</h2> <p>I decided to build a gateway that would allow the Alto to communicate with a modern system. The gateway would communicate with the Alto using its obsolete 3Mb/s Ethernet, but could also communicate with the outside world. This would let us network boot the Alto, transfer files to and from the Alto and backup disks. I expected this project to take a few weeks, but it ended up taking a year.</p> <p>The first decision was what hardware platform to use. My plan was to use a microcontroller to generate the 3Mb/s signals by "bit banging", i.e. directly generating the 1's and 0's on the wire. (A regular processor couldn't handle this in real time, due to interrupts and task switching.) But a microcontroller wouldn't be suitable for running the network stack and communicating with the outside world; I'd need a "real computer" for that. Someone suggested the BeagleBone: a credit-card sized Linux computer with an ARM processor that also incorporated two microcontrollers. This would provide a compact, low-cost implementation, so I started investigating the BeagleBone.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4WXXb41L8tjhoNT5Hci6ATZYsJXDfljUpNHvc5_-9c5kxEFraSC6BqcGlTDcG5eU7fNPp1xpJwznLxhLuBpB3bE-VSK6Kgne2bCBfEOJeDlErzN4ZUZM4xs1Jg8-qLyg35lUCDlZpUNS8/w9999/altoids2.jpg"><img alt="The BeagleBone single-board Linux computer is small enough to fit in an Altoids tin. It has many general/purpose I/O pins, accessible through the connectors along the top and bottom of the board." class="hilite" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4WXXb41L8tjhoNT5Hci6ATZYsJXDfljUpNHvc5_-9c5kxEFraSC6BqcGlTDcG5eU7fNPp1xpJwznLxhLuBpB3bE-VSK6Kgne2bCBfEOJeDlErzN4ZUZM4xs1Jg8-qLyg35lUCDlZpUNS8/w300/altoids2.jpg" title="The BeagleBone single-board Linux computer is small enough to fit in an Altoids tin. It has many general/purpose I/O pins, accessible through the connectors along the top and bottom of the board." width="300" /></a><div class="cite">The BeagleBone single-board Linux computer is small enough to fit in an Altoids tin. It has many general/purpose I/O pins, accessible through the connectors along the top and bottom of the board.</div></p> <p>The BeagleBone's microcontrollers, called PRUs,<span id="fnref:pru"><a class="ref" href="#fn:pru" rel="footnote">2</a></span> are designed to run each instruction in a single 5ns cycle. Since the Ethernet pulses are 170ns wide, I figured I had plenty of time to send and receive signals. (It turned out that getting everything done in 170ns was challenging, but it worked out in the end.) In my gateway, the PRU reads the Ethernet signal coming from the Alto, and generate the Ethernet signal going to the Alto, as well as sending a network collision signal to the Alto.</p> <p>In case you're wondering what PRU code looks like, the C code fragment below shows how a byte is encoded and sent. The PRU code outputs the right sequence of HIGH/LOW or LOW/HIGH pulses (the Manchester encoding), making sure each part is 170ns wide. Each bit of register <code>R30</code> controls an output pin, so the bit for the Ethernet write pin is set and cleared as needed. <code>wait_for_pwm_timer()</code> provides the 170ns timing for each pulse. The full code is <a href="https://github.com/shirriff/alto-ethernet-interface/blob/master/src/main.c">here</a>.</p> <script src="https://gist.github.com/shirriff/05d8a44ab844f959db86b28d8d27fb28.js"></script> <p>To receive data from Ethernet, my PRU code doesn't do any decoding; it just measures the time between input transitions and sends these timings to the BeagleBone's ARM processor. Originally my code decoded the Manchester encoding into bits and assembled the bits into words, but 170ns wasn't enough time to do this reliably. Instead, since this decoding doesn't need to be done in real time, I moved the decoding to the more powerful ARM processor. The ARM processor also does the higher-level Ethernet protocol handling, such as generating and checking packet checksums.</p> <p>Rather than deal with transceivers and coaxial cable, I connected the BeagleBone to the Alto's Ethernet port directly, omitting the transceiver that normally connects to this port. This port provides standard 5V TTL signals to the transceiver, but the BeagleBone inconveniently uses 3.3V signals. I needed a circuit to translate the voltage levels between the BeagleBone and the Alto. This should have been easy, but I ran into various problems along the way.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjv4qwJbuEiBHuf-2VVMiCIv02L3ae_ndQibsslN2Ct4O_ruHWGzyNDLvGU8DRZ-otXjPgzQs6N4bcaN905RPQI3IRXHzh0kX16U6-Cn7R-r1DuJpfmipbtj_v4goc1ULfXXKA3X-NwbWjG/w9999/ethernet-connector.jpg"><img alt="On the back of the Alto, Ethernet is accessed via a DB-25 connector that connects to a transceiver box." class="hilite" height="205" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjv4qwJbuEiBHuf-2VVMiCIv02L3ae_ndQibsslN2Ct4O_ruHWGzyNDLvGU8DRZ-otXjPgzQs6N4bcaN905RPQI3IRXHzh0kX16U6-Cn7R-r1DuJpfmipbtj_v4goc1ULfXXKA3X-NwbWjG/w300/ethernet-connector.jpg" title="On the back of the Alto, Ethernet is accessed via a DB-25 connector that connects to a transceiver box." width="300" /></a><div class="cite">On the back of the Alto, Ethernet is accessed via a DB-25 connector that connects to a transceiver box.</div></p> <p>I built a prototype voltage translation circuit on a breadboard, using a <a href="https://www.adafruit.com/product/1787">74AHCT125</a> level shifter chip (<a href="https://github.com/shirriff/alto-ethernet-interface/blob/master/board/schematic.pdf">schematic</a>). However, I was getting no Ethernet signal at all from the Alto, so I started probing the Alto's board for a malfunction. I discovered that although the Alto's schematic showed pull-up resistors, these resistors didn't exist on the Alto's Ethernet board (see photo below). Without a resistor, the open-collector signal stayed at ground. Adding the resistors to my circuit fixed that problem.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf0ILnTNce4n-29hG2eMod5IH_adVtrJmmvGEPtZY-sVEtXAljBS3uFxqX8dkDsfWlXkRoKiiTlaHTWJAy4Cl0tnE0dRfjdbQDGCanaxAzb2FNko5cuCMnsmEbf0vOUv_wznXdnzNG-oIn/w9999/missing-resistors.jpg"><img alt="One problem I encountered was termination resistors R8 and R9 appeared on the schematic but were missing from the board (above the word "ETHERNET")." class="hilite" height="257" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf0ILnTNce4n-29hG2eMod5IH_adVtrJmmvGEPtZY-sVEtXAljBS3uFxqX8dkDsfWlXkRoKiiTlaHTWJAy4Cl0tnE0dRfjdbQDGCanaxAzb2FNko5cuCMnsmEbf0vOUv_wznXdnzNG-oIn/w400/missing-resistors.jpg" title="One problem I encountered was termination resistors R8 and R9 appeared on the schematic but were missing from the board (above the word "ETHERNET")." width="400" /></a><div class="cite">One problem I encountered was termination resistors R8 and R9 appeared on the schematic but were missing from the board (above the word "ETHERNET").</div></p> <p>The next step was to write the PRU microcontroller code to send and receive Ethernet packets. After a lot of testing with the Alto's <em>Ethernet Diagnostic Program</em> (EDP), I was able to echo packets back and forth between the BeagleBone gateway and the Alto.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUKO0rboCyUWZqP7RG09OFy7ke-2vqo-YDdxbAuAwo_to3fhHA6vQsgK7S9q5B752IlnY71KG2CuTSPFhPFIiybt_QJLmxiCg3TQsf81SEBZyEHfdONK-nY7I3R_gtNYSHijhBXpeaMZqb/w9999/edp.jpg"><img alt="The Ethernet Diagnostic Program can be used to test the Ethernet. It has a simple GUI." class="hilite" height="390" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUKO0rboCyUWZqP7RG09OFy7ke-2vqo-YDdxbAuAwo_to3fhHA6vQsgK7S9q5B752IlnY71KG2CuTSPFhPFIiybt_QJLmxiCg3TQsf81SEBZyEHfdONK-nY7I3R_gtNYSHijhBXpeaMZqb/w400/edp.jpg" title="The Ethernet Diagnostic Program can be used to test the Ethernet. It has a simple GUI." width="400" /></a><div class="cite">The Ethernet Diagnostic Program can be used to test the Ethernet. It has a simple GUI.</div></p> <p>To be useful, the gateway must support the network stack: Pup packets, network booting, Alto-style FTP and so forth. I started by rewriting the Alto's network code, making a direct port of the BCPL implementation<span id="fnref:bcpl"><a class="ref" href="#fn:bcpl" rel="footnote">3</a></span> to Python. This turned out to be a mess, because the original implementation depended heavily on the Alto's operating system, which provided multiple threads, so the application could run in one thread and the network code in other threads. I managed to get the stateless low-level Pup packets to work okay, but the higher-level Byte Stream Protocol was a tangle of busy-waiting loops and timeouts.</p> <p>Fortunately the <a href="http://www.livingcomputers.org/">Living Computers Museum+Lab</a> (LCM+L) came to rescue. Josh Dersch at the museum had written a C# implementation of the Alto's network stack, so I decided to discard my implementation of the network stack. This implementation, called IFS,<span id="fnref:ifs"><a class="ref" href="#fn:ifs" rel="footnote">4</a></span> supported the low-level protocols, as well as servers for network operations, FTP, and Copydisk. IFS was a new implementation rather than a direct port like my attempt, and that approach worked much better.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1ZggYDWcax1sAgcWntaM829lh3B3BRQLYZWx9wzj9wkuyHOzw-UJr5-Mn6CIou1PHYOW3eUj0EhDNJUiSSdJmgeqH9gCfoIpwdgwhpFwAmvmqOXqjOpurijuPgXlexMZ0VhymrifZrmfx/w9999/lcm-interface.jpg"><img alt="The Living Computers Museum built a 3 Mb/s Ethernet interface using an FPGA chip." class="hilite" height="290" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1ZggYDWcax1sAgcWntaM829lh3B3BRQLYZWx9wzj9wkuyHOzw-UJr5-Mn6CIou1PHYOW3eUj0EhDNJUiSSdJmgeqH9gCfoIpwdgwhpFwAmvmqOXqjOpurijuPgXlexMZ0VhymrifZrmfx/w400/lcm-interface.jpg" title="The Living Computers Museum built a 3 Mb/s Ethernet interface using an FPGA chip." width="400" /></a><div class="cite">The Living Computers Museum built a 3 Mb/s Ethernet interface using an FPGA chip.</div></p> <p>The LCM+L also built an Ethernet interface to the Alto. Theirs was much more complex than mine, consisting of an FPGA chip on a custom PCI card plugged into a PC. Unlike my interface, theirs communicated with a transceiver box, rather than connecting to the Alto directly. Even though the LCM+L's FPGA interface worked for us, I decided to complete my interface board since I liked the idea of a low-cost, compact Ethernet gateway. Their interface is more "realistic", since it connects to a real transceiver and network cable and can work with multiple Altos on a network. (The photo below shows the mini-network connecting the LCM+L interface and an Alto.) On the other hand not everyone has Ethernet transceivers lying around, so mine is more widely usable.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYjelG_O3YQwENe_9a4YL9lZo7G5opPU0hO5HM8f0HsKGDNCVwPaOWGg4cg6NGH_UmTuBNbLuEM7y32XNBH8MAaENBO3v6Knvrx77PhHziO68V-09tZQyLRW-RJe5Wuyb29vnoEa_ts01e/w9999/network.jpg"><img alt="A very short 3 Mb/s Ethernet network, showing two transceivers attached to the coaxial cable. One transceiver is connected to the Alto and the other is connected to the LCM+L gateway card." class="hilite" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYjelG_O3YQwENe_9a4YL9lZo7G5opPU0hO5HM8f0HsKGDNCVwPaOWGg4cg6NGH_UmTuBNbLuEM7y32XNBH8MAaENBO3v6Knvrx77PhHziO68V-09tZQyLRW-RJe5Wuyb29vnoEa_ts01e/w400/network.jpg" title="A very short 3 Mb/s Ethernet network, showing two transceivers attached to the coaxial cable. One transceiver is connected to the Alto and the other is connected to the LCM+L gateway card." width="400" /></a><div class="cite">A very short 3 Mb/s Ethernet network, showing two transceivers attached to the coaxial cable. One transceiver is connected to the Alto and the other is connected to the LCM+L gateway card.</div></p> <p>I made a simple printed circuit board to replace my breadboarded prototype. This was the first circuit board I had designed in about 35 years and technology has certainly changed. Back in the 1980s, I drew circuit board traces with a resist pen on a copper-clad board, and then etched the board in ferric chloride solution from Radio Shack. Now, I designed my board using Eagle, uploaded the file to OSH Park, and received a beautiful circuit board a few days later.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7x85kdU5HNNO-pBdGOHSbcwx8XOIK7RyumbCodX5b6ZdDUNIhX-5PpDMAGbXCdNQH0nl0De5lSzUKn9HHTuGQGCroKasHhzaVH7gZQGRj36OtkVqksHEGkfGjPIP8DUSjR8ZujeZ5f3I2/w9999/beaglebone-alto-interface.jpg"><img alt="My 3 Mb/s Ethernet interface is a level-shifter card on a BeagleBone. Note the capacitor soldered directly to the driver IC to fix a ringing signal problem." class="hilite" height="231" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7x85kdU5HNNO-pBdGOHSbcwx8XOIK7RyumbCodX5b6ZdDUNIhX-5PpDMAGbXCdNQH0nl0De5lSzUKn9HHTuGQGCroKasHhzaVH7gZQGRj36OtkVqksHEGkfGjPIP8DUSjR8ZujeZ5f3I2/w400/beaglebone-alto-interface.jpg" title="My 3 Mb/s Ethernet interface is a level-shifter card on a BeagleBone. Note the capacitor soldered directly to the driver IC to fix a ringing signal problem." width="400" /></a><div class="cite">My 3 Mb/s Ethernet interface is a level-shifter card on a BeagleBone. Note the capacitor soldered directly to the driver IC to fix a ringing signal problem.</div></p> <p>Running the LCM+L's IFS software on the BeagleBone took some work since the BeagleBone runs Linux and IFS was written in C# for Windows. By using the <a href="http://www.mono-project.com/">Mono</a> platform, I could run most of the C# code on the BeagleBone. However, the LCM+L software stack communicated with the gateway by encapsulating Alto Ethernet packets in a modern Ethernet packet, using a .Net Pcap library to access the raw Ethernet. Unfortunately, this library didn't work with Mono, so I rewrote the IFS encapsulation to use UDP.</p> <p>At this point the Alto and my BeagleBone implementation communicated most of the time, but there were a few tricky bugs to track down. The first problem was FTP would get sometimes bad packets. Eventually I discovered that I had mixed up byte and word counts in one place, and the large packets from FTP were overflowing the PRU's buffer.</p> <p>The next problem was that when I used <em>Copydisk</em> to copy a disk pack from the Alto to the BeagleBone, a dropped packet caused the network to lock up after a couple minutes. This was puzzling since the sender should retransmit the lost packet after a timeout and everything should recover (like TCP). After tedious debugging, I found that if the Alto and the BeagleBone transmitted packets close together, a race condition in my code caused a dropped packet.<span id="fnref:breath"><a class="ref" href="#fn:breath" rel="footnote">5</a></span><span id="fnref:race"><a class="ref" href="#fn:race" rel="footnote">6</a></span> Then IFS neglected to send a necessary ack when it received an unexpected packet, so the Alto kept resending the wrong packet. After fixing both my gateway code and the IFS ack, the network ran without problems.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhx5wSADF3M4fEIn_p9O5I1GJlz3wmeRTGrYbD2ggsJzgiyZNTHroVEBh4ZvJkPJg9RX8h1EIU0PjPLX8lJg2xaeX_XV4byhdX4k1G4iUDNrR9RYLh5iya72Hju01_A47VSaIN7rA0SlecV/w9999/gateway-v2.jpg"><img alt="Second version of the interface. Note the blue jumper wire to replace the missing trace." class="hilite" height="237" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhx5wSADF3M4fEIn_p9O5I1GJlz3wmeRTGrYbD2ggsJzgiyZNTHroVEBh4ZvJkPJg9RX8h1EIU0PjPLX8lJg2xaeX_XV4byhdX4k1G4iUDNrR9RYLh5iya72Hju01_A47VSaIN7rA0SlecV/w400/gateway-v2.jpg" title="Second version of the interface. Note the blue jumper wire to replace the missing trace." width="400" /></a><div class="cite">Second version of the interface. Note the blue jumper wire to replace the missing trace.</div></p> <p>My first version of the PCB had a few issues<span id="fnref:problems"><a class="ref" href="#fn:problems" rel="footnote">8</a></span> so I made a second version (above). I found that the driver chip didn't sink enough current for a long cable, so I replaced it with the chip used by the transceivers (a 7438 open collector NAND gate). I also decided to try KiCad instead of Eagle for the second board. Unfortunately, I made a mistake in KiCad<span id="fnref:kicad"><a class="ref" href="#fn:kicad" rel="footnote">7</a></span> and the new board was missing a trace, so I had to solder in a jumper (which you can seen in the photo above).</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiI3m8xzBR4R4V6mvQ_Vaock42mviMH0Fd-VJpd0cH218gXHYhwrdBMpmRUVCSbgx7VuFuS-I9SFin-1HBJa5adl9BcC2K3DNSzZ5uZWqbdDGIAUzwp05DisvaHNO5v-606CSLdwM7ZA3Sp/w9999/probing-board.jpg"><img alt="I probed the Alto's Ethernet card with an oscilloscope to check the signals it was receiving. An extender card from the LCM+L allowed us to access the card." class="hilite" height="422" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiI3m8xzBR4R4V6mvQ_Vaock42mviMH0Fd-VJpd0cH218gXHYhwrdBMpmRUVCSbgx7VuFuS-I9SFin-1HBJa5adl9BcC2K3DNSzZ5uZWqbdDGIAUzwp05DisvaHNO5v-606CSLdwM7ZA3Sp/w400/probing-board.jpg" title="I probed the Alto's Ethernet card with an oscilloscope to check the signals it was receiving. An extender card from the LCM+L allowed us to access the card." width="400" /></a><div class="cite">I probed the Alto's Ethernet card with an oscilloscope to check the signals it was receiving. An extender card from the LCM+L allowed us to access the card.</div></p> <p>I tested the new board but it didn't work at all: the Alto wasn't receiving data or sending data. I realized that the new driver chip was a NAND gate so the signals were now inverted. I updated the PRU code to flip LOW and HIGH on the data out signal. The board still didn't work, so I probed the Alto's Ethernet board with an oscilloscope, comparing the signals from the old working board to the new failing board. Strangely, both signals were identical in the Alto and looked fine.</p> <p>Eventually Marc asked me if there could be something wrong with the collision detection. I realized that the the new NAND driver was also inverting the collision detection signal. Thus, the Alto was seeing constant network collisions and refused to send or receive anything. After fixing this in my PRU software, the new board worked fine. I'm making a third revision of the board to fix the missing trace; hopefully this won't break something else.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguiZlbhr_SntyGdBLo6vY0HWzUtRKEPeY3GopacpJNyXrKABm7ffdanbSo36HAnT6b3R3pVU1T8MRdaIxYUjGIKS7_m6XRD1JQ9sYKNef1d4qR1PxSh7td3Ah0xEdmRKocgTwnmRyXvQ99/w9999/transceivers.jpg"><img alt="An assortment of vintage Ethernet transceivers, along with the tap tools used to drill holes in the Ethernet cable for the vampire tap connection." class="hilite" height="276" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguiZlbhr_SntyGdBLo6vY0HWzUtRKEPeY3GopacpJNyXrKABm7ffdanbSo36HAnT6b3R3pVU1T8MRdaIxYUjGIKS7_m6XRD1JQ9sYKNef1d4qR1PxSh7td3Ah0xEdmRKocgTwnmRyXvQ99/w400/transceivers.jpg" title="An assortment of vintage Ethernet transceivers, along with the tap tools used to drill holes in the Ethernet cable for the vampire tap connection." width="400" /></a><div class="cite">An assortment of vintage Ethernet transceivers, along with the tap tools used to drill holes in the Ethernet cable for the vampire tap connection.</div></p> <h2>Conclusion</h2> <p>The Ethernet gateway project took much more time and encountered more problems than I expected. But it worked in the end, and several Alto owners are now using my gateway. I've open-sourced this interface (the board layout and the gateway software); it's available on <a href="https://github.com/shirriff/alto-ethernet-interface">github</a>.</p> <p>The Alto I've been restoring came from YCombinator; the restoration team includes Marc Verdiell, <a href="https://rescue1130.blogspot.com/">Carl Claunch</a> and Luca Severini. My full set of Alto posts is <a href="http://www.righto.com/search/label/alto">here</a> and Marc's extensive videos of the restoration are <a href="https://www.youtube.com/user/mverdiell/videos">here</a>. Thanks to the <a href="http://www.livingcomputers.org/">Living Computers Museum+Labs</a> for the <a href="https://github.com/livingcomputermuseum/IFS">IFS software</a>.</p> <p>Follow me on <a href="https://twitter.com/kenshirriff">Twitter</a> or <a href="http://www.righto.com/feeds/posts/default">RSS</a> to find out about my latest blog posts.</p> <h2>Notes and references</h2> <div class="footnote"> <ol> <li id="fn:pup"> <p>For more information on the Pup protocol, see <a href="http://bitsavers.trailing-edge.com/pdf/xerox/alto/ethernet/pupArch.pdf">Pup: An Internetwork Architecture</a> and the <a href="http://www.textfiles.com/bitsavers/pdf/xerox/alto/pupSpec.pdf">Pup Specifications</a> memo.  <a class="footnote-backref" href="#fnref:pup" rev="footnote" title="Jump back to footnote 1 in the text">↩</a></p> </li> <li id="fn:pru"> <p>Programming the PRU microcontrollers has a difficult learning curve, and it's not nearly as well documented as, say, the Arduino. Based on my experience with the PRU, I wrote some programming tips <a href="http://www.righto.com/2016/08/pru-tips-understanding-beaglebones.html">here</a> and <a href="http://www.righto.com/2016/09/how-to-run-c-programs-on-beaglebones.html">here</a>. <a class="footnote-backref" href="#fnref:pru" rev="footnote" title="Jump back to footnote 2 in the text">↩</a></p> </li> <li id="fn:bcpl"> <p>The Alto's network code is <a href="http://xeroxalto.computerhistory.org/Indigo/AltoSource/PUPSOURCES.DM!3_">online</a>; you can look at one of the Pup files <a href="http://xeroxalto.computerhistory.org/Indigo/AltoSource/PUPSOURCES.DM!3_/.PupBSPOpenClose.bcpl.html">here</a>. The code is written in BCPL, which was a predecssor to C. It is very similar to C, but with different syntactic choices. For instance, <code>>></code> is not a shift but accesses a field in a structure. <a class="footnote-backref" href="#fnref:bcpl" rev="footnote" title="Jump back to footnote 3 in the text">↩</a></p> </li> <li id="fn:ifs"> <p>At PARC, IFS was an acronym for <em>Interim File System</em>, an Alto-based distributed file server. It was called <em>interim</em> because an improved system was being developed, but somehow a new system never replaced IFS. <a class="footnote-backref" href="#fnref:ifs" rev="footnote" title="Jump back to footnote 4 in the text">↩</a></p> </li> <li id="fn:breath"> <p>Most of the time, the BeagleBone and the Alto alternated sending packets. But every second, IFS sent a "breath of life" packet, the packet executed by the Alto to start a network boot. The breath of life packet was part of the original Alto—it simplified the network boot code since the Alto didn't need to request a network boot, but just listen for a second or two. Since the breath of life packet was asynchronous with respect to the other network traffic, eventually it would happen at a bad time for my code, triggering the dropped packet problem. <a class="footnote-backref" href="#fnref:breath" rev="footnote" title="Jump back to footnote 5 in the text">↩</a></p> </li> <li id="fn:race"> <p>The problem with the PRU and the "breath of life" packet was due to how I was sending signals between the PRU and the main BeagleBone processor. When sending a packet, the main processor would signal the PRU, and then wait for a signal back when the packet was sent. When a packet was received, the PRU would send a signal to the main processor. The problem was that the PRU sent the same signal in both cases. So a "packet received" signal at the wrong time could wake up the packet sending code, losing the received packet. Fundamentally, I was treating the signals between the main processor and the PRU as synchronous, when everything was really asynchronous. I rewrote the gateway code so ownership of the send and receive buffers was explicitly transferred between the main processor and the PRU. A signal just indicated that ownership had changed somehow; checking the buffer status showed what exactly had changed. See <a href="https://groups.google.com/forum/#!msg/beagleboard/3sre2nT-dAc/YWXWFFXOBQAJ">this discussion</a> for details. <a class="footnote-backref" href="#fnref:race" rev="footnote" title="Jump back to footnote 6 in the text">↩</a></p> </li> <li id="fn:kicad"> <p>My error in KiCad was I placed a net label just a bit too far from the wire on the schematic, so the wire wasn't connected to the net. <a class="footnote-backref" href="#fnref:kicad" rev="footnote" title="Jump back to footnote 7 in the text">↩</a></p> </li> <li id="fn:problems"> <p>My first PCB had a couple issues that I had to hack around. Ringing in the signal to the Alto corrupted it, so I added a damping capacitor. The driver didn't have enough current for an Ethernet cable longer than 10 feet, so I added a pull-down resistor. There were also a couple mechanical issues. The location of the Ethernet jack made it hard to remove the cable, and the board blocked one of the BeagleBone buttons. I also discovered that using a 74HC125 driver chip didn't work at all; just the 74AHCT125 worked. <a class="footnote-backref" href="#fnref:problems" rev="footnote" title="Jump back to footnote 8 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/1182972412801248728' onclick=''> 7 comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=1182972412801248728' 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=1182972412801248728&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=1182972412801248728&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=1182972412801248728&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=1182972412801248728&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=1182972412801248728&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=1182972412801248728&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/alto' rel='tag'>alto</a>, <a href='http://www.righto.com/search/label/beaglebone' rel='tag'>beaglebone</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://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7aHIJiPmXfKW5eBOQkExu57Ti0h67DpNT1wNlj0FZCJqkcoc1bwRC1ozQfJqXZMs-CLvqrrMDfXu8xzY2YKu6aFoV3Fp3oa6j8rj76D8SSkTLMcYk0juiWt0mDWR2WIsP4O77Juvp7Xkw/w500/pocketbeagle.jpg' itemprop='image_url'/> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='973294018243505448' itemprop='postId'/> <a name='973294018243505448'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2017/12/hands-on-with-pocketbeagle-tiny-25.html'>Hands-on with the PocketBeagle: a $25 Linux computer with lots of I/O pins</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-973294018243505448' itemprop='description articleBody'> <style> pre {border:none;background-color:#eee;max-width:40em;padding:4px;font-size:80%;} code {background-color:#eee;font-size:80%;} </style> <p>The PocketBeagle is a tiny but powerful <a href="https://www.digikey.com/product-detail/en/ghi-electronics-llc/POCKETBEAGLE-SC-569/POCKETBEAGLE-SC-569-ND/7603326">inexpensive</a> key-fob-sized <a href="https://github.com/beagleboard/pocketbeagle">open source</a> Linux computer. It has 44 digital I/O pins, 8 analog inputs, and supports multiple serial I/O protocols, making it very useful as a controller. In addition, its processor includes two 200-MHz microcontrollers that allow you to implement low-latency, real-time functions while still having the capabilities of a Linux system This article discusses my experience trying out different features of the PocketBeagle, along with some technical details.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7aHIJiPmXfKW5eBOQkExu57Ti0h67DpNT1wNlj0FZCJqkcoc1bwRC1ozQfJqXZMs-CLvqrrMDfXu8xzY2YKu6aFoV3Fp3oa6j8rj76D8SSkTLMcYk0juiWt0mDWR2WIsP4O77Juvp7Xkw/w9999/pocketbeagle.jpg"><img alt="The PocketBeagle is a compact Linux computer, somewhat bigger than a quarter." class="hilite" height="352" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7aHIJiPmXfKW5eBOQkExu57Ti0h67DpNT1wNlj0FZCJqkcoc1bwRC1ozQfJqXZMs-CLvqrrMDfXu8xzY2YKu6aFoV3Fp3oa6j8rj76D8SSkTLMcYk0juiWt0mDWR2WIsP4O77Juvp7Xkw/w500/pocketbeagle.jpg" title="The PocketBeagle is a compact Linux computer, somewhat bigger than a quarter." width="500" /></a><div class="cite">The PocketBeagle is a compact Linux computer, somewhat bigger than a quarter.</div></p> <p>You may be familiar with the BeagleBone, a credit-card sized computer. The PocketBeagle is very similar to the BeagleBone, but smaller and cheaper. Both systems use TI's 1GHz "Sitara" ARM Cortex-A8 processor, but the PocketBeagle's I/O is stripped-down with 72 header pins compared to 92 on the BeagleBone. The PocketBeagle doesn't have the BeagleBone's 4GB on-board flash; all storage is on a micro-SD card. The BeagleBone's Ethernet and HDMI ports are also dropped.</p> <p>The PocketBeagle uses an interesting technology to achieve its compact size—it is built around a System-In-Package (SIP) device that has multiple dies and components in one package (see diagram below). The <a href="https://octavosystems.com/octavo_products/osd335x-sm/">Octavo Systems OSD3358-SM</a> combines the TI 3358 Sitara processor, 512MB of RAM, power management and EEPROM. <span id="fnref:slt"><a class="ref" href="#fn:slt" rel="footnote">1</a></span> In the photo above, this package has a white label and dominates the circuit board.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitg9nUxkypBIfXNsdMJXG3ENfLuvramEqC-6fLq1vv82As5WreYfXICjbNz6ONMexwPIZNnN6ri9qMrwt4Yr_ODAn43p2IWOv3uPmZJDHjIewQ_LwX2tctO4q7SFRz4_MayYvU1Y2dZGzt/w9999/Stack-Up-Description.png"><img alt="The PocketBeagle is powered by the OSD335x, which combines a processor die, memory and other components into a single package." class="hilite" height="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitg9nUxkypBIfXNsdMJXG3ENfLuvramEqC-6fLq1vv82As5WreYfXICjbNz6ONMexwPIZNnN6ri9qMrwt4Yr_ODAn43p2IWOv3uPmZJDHjIewQ_LwX2tctO4q7SFRz4_MayYvU1Y2dZGzt/w400/Stack-Up-Description.png" title="The PocketBeagle is powered by the OSD335x, which combines a processor die, memory and other components into a single package." width="400" /></a><div class="cite">The PocketBeagle is powered by the OSD335x, which combines a processor die, memory and other components into a single package.</div></p> <h2>Initializing the SD card</h2> <p>To use the PocketBeagle, you must write a Linux file system to a micro-SD card. The easiest way to do this is to download an image, write it to the SD card from your computer, and then pop the SD card into the PocketBeagle. Details are in the footnotes.<span id="fnref:sdcard"><a class="ref" href="#fn:sdcard" rel="footnote">2</a></span></p> <p>You can also compile a kernel from scratch, set up U-boot, and build a file system on the SD card. the PocketBeagle. There's a bunch of information on this process at Digikey's <a href="https://forum.digikey.com/t/pocketbeagle-getting-started/567">PocketBeagle getting started</a> page. This is the way to go if you want flexibility, but it's overkill if you just want to try out the PocketBeagle.</p> <h2>Starting up the PocketBeagle</h2> <p>Unlike the BeagleBone, which supports a keyboard and an HDMI output, the PocketBeagle is designed as a "headless" device that you ssh into. You can plug the PocketBeagle into your computer's USB port, and the PocketBeagle should appear as a network device: 192.168.6.2 on Mac/Linux and 192.168.7.2 on Windows (<a href="http://beagleboard.org/getting-started">details</a>). You should also see a flash-drive style file system appear on your computer under the name "BEAGLEBONE". If the PocketBeagle has the default Debian OS<span id="fnref:kernel"><a class="ref" href="#fn:kernel" rel="footnote">3</a></span>, you can log in with: <pre> ssh <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="325657505b535c72030b001c03040a1c041c00">[email protected]</a> Password: temppwd </pre></p> <h2>Connecting to the PocketBeagle's serial console</h2> <p>While <code>ssh</code> is the simplest way to connect to the PocketBeagle, if anything goes wrong with the boot or networking, you'll need to look at the serial console to debug the problem. The easiest solution is a UART Click board<span id="fnref:mikrobus"><a class="ref" href="#fn:mikrobus" rel="footnote">4</a></span>, which gives you a serial connection over USB. You can then connect with "screen" or other terminal software: <code>screen /dev/cu.usbserial\* 115200</code></p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1zByliGiHF5PyGIRgBAX7Hob3WMY27dVpUGjV_U0qPdtI0chDBYLL5-cdN7732CdmTxt8Ha5mbKH62Ve-D6jm1vPnYdyzsz7zbdp7uPDXf2vhIe64YMN9uH9VTTxVMRFiyaHb7Q1-TnBh/w9999/pocketbeagle-uart.jpg"><img alt="Plugging a UART click board into the PocketBeagle gives access to the serial console." class="hilite" height="224" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1zByliGiHF5PyGIRgBAX7Hob3WMY27dVpUGjV_U0qPdtI0chDBYLL5-cdN7732CdmTxt8Ha5mbKH62Ve-D6jm1vPnYdyzsz7zbdp7uPDXf2vhIe64YMN9uH9VTTxVMRFiyaHb7Q1-TnBh/w450/pocketbeagle-uart.jpg" title="Plugging a UART click board into the PocketBeagle gives access to the serial console." width="450" /></a><div class="cite">Plugging a UART click board into the PocketBeagle gives access to the serial console.</div></p> <p>You can also use a FTDI serial adapter such as the <a href="https://www.adafruit.com/product/284">Adafruit FTDI Friend</a>. (If you've worked with the BeagleBone, you may have one of these already.) You'll need three wires to hook it up to the PocketBeagle; it won't plug in directly as with the BeagleBone. Just connect ground, Rx and Tx between the PocketBeagle and the adapter (making sure to cross Rx to Tx).<span id="fnref:serial"><a class="ref" href="#fn:serial" rel="footnote">5</a></span></p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpcf2CFmWqBnI-XsVBYZHT9Bahyk1yVHJZuMhERS9pARdj7UJA4OXBHjHU0QnrO8L8San6K-ONY4uHqeZ0m3bRJpRFaLJeyR8koU68ruJeud32q2MQWP8rHmMRi1ohhaghvkjDNUj-lhOI/w9999/ftdi.jpg"><img alt="Accessing the PocketBeagle's serial console through an FTDI interface." class="hilite" height="158" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpcf2CFmWqBnI-XsVBYZHT9Bahyk1yVHJZuMhERS9pARdj7UJA4OXBHjHU0QnrO8L8San6K-ONY4uHqeZ0m3bRJpRFaLJeyR8koU68ruJeud32q2MQWP8rHmMRi1ohhaghvkjDNUj-lhOI/w450/ftdi.jpg" title="Accessing the PocketBeagle's serial console through an FTDI interface." width="450" /></a><div class="cite">Accessing the PocketBeagle's serial console through an FTDI interface.</div></p> <h2>Pinout</h2> <p>The PocketBeagle has two headers that provide access to I/O functions. (These headers are different from the BeagleBone's headers, so BeagleBone "capes" won't work with the PocketBeagle.) The <a href="https://raw.githubusercontent.com/beagleboard/pocketbeagle/master/docs/PocketBeagle_pinout.png">PocketBeagle pinout diagram</a> (below) shows what the header pins do. The diagram may seem confusing at first, since each pin has up to three different functions shown. (Most pins actually support 8 functions, so more obscure functions have been omitted.) The diagram is color coded. Power and system pins are labeled in red. GPIO (general-purpose I/O) pins are white. USB pins are blue. Analog inputs are yellow. UART serial pins are brown. PRU microcontroller pins are cyan. Battery pins are magenta. I2C bus is purple. PWM (pulse width modulation) outputs are light green. SPI (Serial Peripheral Interface) is brown. CAN (Controller Area Network) is dark green. QEP (quadrature encoder pulse) inputs are gray.<span id="fnref:trm"><a class="ref" href="#fn:trm" rel="footnote">9</a></span> The dotted lines in the diagram indicate the default pin functions (except for the PRU pins, which default to GPIO).<span id="fnref:pinmapdetails"><a class="ref" href="#fn:pinmapdetails" rel="footnote">6</a></span></p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5MLU-QDV1XLvmX-aD-RK5KehojITgO_zNPjG2-_mcQ9gfe1l_LeqW0aD1rJUdSg6V2hNzL1fER_JaRgmSRgPHqsaGz_qPEVgIE2iMLWUTRuBfUKnEIyBmIzSEDgRDp_rlCGYYlOOcTRFO/w9999/PocketBeagle_pinout.png"><img alt="Pinout diagram of the PocketBeagle's headers. USB=blue, Power=yellow, GPIO=white, PRU=cyan, SPI=orange, UART=brown, and other colors are miscellaneous." class="hilite" height="351" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5MLU-QDV1XLvmX-aD-RK5KehojITgO_zNPjG2-_mcQ9gfe1l_LeqW0aD1rJUdSg6V2hNzL1fER_JaRgmSRgPHqsaGz_qPEVgIE2iMLWUTRuBfUKnEIyBmIzSEDgRDp_rlCGYYlOOcTRFO/w800/PocketBeagle_pinout.png" title="Pinout diagram of the PocketBeagle's headers. USB=blue, Power=yellow, GPIO=white, PRU=cyan, SPI=orange, UART=brown, and other colors are miscellaneous." width="800" /></a><div class="cite">Pinout diagram of the PocketBeagle's headers. USB=blue, Power=yellow, GPIO=white, PRU=cyan, SPI=orange, UART=brown, and other colors are miscellaneous.</div></p> <p>Note that the diagram shows the headers from the component side of the board, not the silkscreened side of the board. Comparing the pin diagram with the board (below), you will notice everything is flipped horizontally. E.g. GPIO 59 is on the right in the diagram and on the left below. So make sure you're using the right header!</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgO4hyaCi3ds5gUsDkiiTEvaQf7kz-KaAzlxZ_NoTaE6ycQUbJbAAK0o1RUW6zWJKRQBnSQU-TCYdC6BxAORbb9OxvXu1UtUExua3ssfw_8_RaqPoy424NU9Gt1O-WMl0tdV5cSNokPtvM/w9999/bboard_pocketbeagle_back.jpg"><img alt="Silkscreen labeling the PocketBeagle's header pins." class="hilite" height="389" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgO4hyaCi3ds5gUsDkiiTEvaQf7kz-KaAzlxZ_NoTaE6ycQUbJbAAK0o1RUW6zWJKRQBnSQU-TCYdC6BxAORbb9OxvXu1UtUExua3ssfw_8_RaqPoy424NU9Gt1O-WMl0tdV5cSNokPtvM/w250/bboard_pocketbeagle_back.jpg" title="Silkscreen labeling the PocketBeagle's header pins." width="250" /></a><div class="cite">Silkscreen labeling the PocketBeagle's header pins.</div></p> <p>One tricky feature of the Sitara processor is that each pin has up to eight different functions. The motivation is that the chip supports a huge number of different I/O functions, so there aren't enough physical pins for every desired I/O. The solution is a pin mapping system that lets the user choose which functions are available on each pin. <span id="fnref:pinmap"><a class="ref" href="#fn:pinmap" rel="footnote">7</a></span> If you need to change a pin assignment from the default, the <a href="https://github.com/beagleboard/pocketbeagle/wiki/Peripherals">config-pin</a> command will modify pin mappings. (Some examples will be given below.) Pins can also be configured at boot time using a "U-Boot overlay".<span id="fnref:devicetree"><a class="ref" href="#fn:devicetree" rel="footnote">8</a></span></p> <h2>GPIO</h2> <p>The PocketBeagle exposes 45 GPIO (general purpose I/O) pins on the headers. The pins can be easily controlled by writing to pseudo-files. For example, the following shell code repeatedly blinks an LED connected to GPIO 111<span id="fnref:gpio-numbering"><a class="ref" href="#fn:gpio-numbering" rel="footnote">10</a></span> (which is accessed through header pin P1_33).</p> <pre> echo out > /sys/class/gpio/gpio111/direction while :; do > echo 1 > /sys/class/gpio/gpio111/value; sleep 1 > echo 0 > /sys/class/gpio/gpio111/value; sleep 1 > done </pre> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhflFBA8e68utUfCW_WCT2RBGgjIDtVH04IM-7ub5AgQlKFV7V2FjJRTFhzhQH-Q0LmwCao1XBwEhaldfnMYFtAEEdqCytX6do_tnzTM9b9bAxa5iBdDsBnD3aA9mThzQr0tcem_MC8_qbD/w9999/pocketbeagle-gpio.jpg"><img alt="An LED connected to header P1 pin 33 can be controlled through GPIO 111." class="hilite" height="295" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhflFBA8e68utUfCW_WCT2RBGgjIDtVH04IM-7ub5AgQlKFV7V2FjJRTFhzhQH-Q0LmwCao1XBwEhaldfnMYFtAEEdqCytX6do_tnzTM9b9bAxa5iBdDsBnD3aA9mThzQr0tcem_MC8_qbD/w400/pocketbeagle-gpio.jpg" title="An LED connected to header P1 pin 33 can be controlled through GPIO 111." width="400" /></a><div class="cite">An LED connected to header P1 pin 33 can be controlled through GPIO 111.</div></p> <h2>PRU</h2> <p>One of the most interesting features of the PocketBeagle is its PRUs, two 32-bit RISC microcontrollers that are built into the Sitara processor chip. These microcontrollers let you perform time-critical operations (such as "bit-banging" a protocol), without worrying about context switches, interrupts, or anything else interfering with your code. At the same time, the ARM processor gives high performance and a complete Linux environment. (I've made use of the BeagleBone's PRU to interface to a vintage Xerox Alto's 3 Mb/s Ethernet.)</p> <p>Although the PRUs are not as easy to use as an Arduino, they can be programmed in C, using the command line or Texas Instruments' CCS development environment. I've written about PRU programming in C before (<a href="http://www.righto.com/2016/09/how-to-run-c-programs-on-beaglebones.html">link</a>) and the underlying library framework (<a href="http://www.righto.com/2016/08/pru-tips-understanding-beaglebones.html">link</a>) for the 3.8.13 kernel, but since then much has changed with the way the PRUs are accessed. The PRUs are now controlled through the <a href="http://processors.wiki.ti.com/index.php/PRU-ICSS_Remoteproc_and_RPMsg">remoteproc</a> framework. In addition, a messaging library (<a href="http://processors.wiki.ti.com/index.php/RPMsg_Quick_Start_Guide">RPMsg</a>) makes it simpler to communicate between the PRUs and the ARM processor. A "resource_table.h" file provides setup information (such as the interrupts used).</p> <p>The following code will turn the LED on (by setting a bit in control register 30), wait one cycle (5ns), turn the LED off, and wait again. Note that the PRU output is controlled by modifying a bit in register R30. This will blink the LED at 40Mhz, unaffected by any other tasks, context switches or interrupts. (For the full code and details of how to run it, see <a href="https://github.com/shirriff/pru-blink">my github repository</a>.)</p> <pre> void main(void) { while (1) { __R30 = __R30 | (1<<1); // Turn on output 1 __delay_cycles(1); __R30 = __R30 & ~(1<<1); // Turn off output 1 __delay_cycles(1); } } </pre> <p>This code uses PRU0 output 1, which is accessed through header pin P1_33 (the same pin as the earlier GPIO example). Since this pin defaults to the GPIO, it must be switched to a PRU output:<span id="fnref:configpin"><a class="ref" href="#fn:configpin" rel="footnote">11</a></span> <pre> config-pin P1_33 pruout </pre></p> <p>This LED example illustrates two key advantages of using the PRU versus controlling a GPIO pin from Linux.<span id="fnref:gpio"><a class="ref" href="#fn:gpio" rel="footnote">12</a></span> First, the PRU code can operate much faster. Second, the GPIO code will produce an uneven signal if the CPU is performing some other Linux task. If you can handle milliseconds of interruption, controlling GPIO pins from Linux is fine. But if you need exact cycle-by-cycle accuracy, the PRU is the way to go.</p> <h2>Networking</h2> <p>Unlike the BeagleBone, the PocketBeagle doesn't have a built-in Ethernet port. However, there are several options for connecting the PocketBeagle to the Internet, described in <a href="https://github.com/beagleboard/pocketbeagle/wiki/FAQ#How_do_I_get_connected_to_the_Internet">the PocketBeagle FAQ</a>. I found the easiest was to use WiFi via a WiFi adapter plugged into USB, as shown below. An alternative is to share your host computer's Ethernet, which I found more difficult to get working.<span id="fnref:ethernet"><a class="ref" href="#fn:ethernet" rel="footnote">14</a></span> Finally, you can add an Ethernet interface to the PocketBeagle using the expansion headers.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh76Fml_Mjzd1zFfjLfi39SqtC4T4WdrcdeD1JqKIRBqVgE_Dh45mQbWdSB0W1zbzebVnTsUXR1gHstM1zUl7gC4f1lP4r5ctaufBd6kiJLyuOP3Aqs3R1NI-2-XrwQWSRgwFavngI6o4tc/w9999/pocketbeagle-wifi.jpg"><img alt="A USB WiFi adapter can easily be connected to the PocketBeagle." class="hilite" height="355" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh76Fml_Mjzd1zFfjLfi39SqtC4T4WdrcdeD1JqKIRBqVgE_Dh45mQbWdSB0W1zbzebVnTsUXR1gHstM1zUl7gC4f1lP4r5ctaufBd6kiJLyuOP3Aqs3R1NI-2-XrwQWSRgwFavngI6o4tc/w350/pocketbeagle-wifi.jpg" title="A USB WiFi adapter can easily be connected to the PocketBeagle." width="350" /></a><div class="cite">A USB WiFi adapter can easily be connected to the PocketBeagle.</div></p> <h2>USB</h2> <p>You can easily connect USB devices to the PocketBeagle since the PocketBeagle has pins assigned for a second USB port. Plug a <a href="https://www.adafruit.com/product/1833">USB Micro-B breakout board</a> into the Pocket Beagle as shown below, connect a <a href="https://www.adafruit.com/product/1099">USB OTG host cable</a> and your USB port should be ready to go. Note that this USB port is a host (i.e. a USB device is connected to the PocketBeagle) opposite from the onboard USB port which works as a client (the PocketBeagle is connected as a device to another computer).</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhO3vk7jp90JtbCoNsdOFKwfdqBRCNF75ttyim42VFlszMveI0OUrnbxsolixiWeAQB7cs1hgn1s4YeLQu7VtVEHCZ29jwW_SwMiJvdvabJdhX7TaWZh2kMxGGaWY0c4M3njFH9TePVguA/w9999/usb-closeup.jpg"><img alt="A closeup of how to plug the USB breakout board into the PocketBeagle. It is connected to pins P1_7 through P1_15." class="hilite" height="205" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhO3vk7jp90JtbCoNsdOFKwfdqBRCNF75ttyim42VFlszMveI0OUrnbxsolixiWeAQB7cs1hgn1s4YeLQu7VtVEHCZ29jwW_SwMiJvdvabJdhX7TaWZh2kMxGGaWY0c4M3njFH9TePVguA/w150/usb-closeup.jpg" title="A closeup of how to plug the USB breakout board into the PocketBeagle. It is connected to pins P1_7 through P1_15." width="150" /></a><div class="cite">A closeup of how to plug the USB breakout board into the PocketBeagle. It is connected to pins P1_7 through P1_15.</div></p> <p>For instance, you can plug in a flash drive. (In the picture below, note that the flash drive is almost as big as the PocketBeagle.) The <code>lsusb</code> command will show your device, and then you can mount it with <code>sudo mount /dev/sda1 /mnt</code>.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiStwJXZWFnwYb62pMvPjn-1FovGQC6TeQh5oWO0Rm-2tUbXbWGB3yMuuiei97aRmIGKzMTOHjSOGl1lesozN_enaqvdpdY34JY25nItecc0Tvm8ijx78m7xyzsrFkDLb-dlxMSiy2Oh8J/w9999/usb-flash.jpg"><img alt="Connecting a USB device (flash drive) to the PocketBeagle." class="hilite" height="282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiStwJXZWFnwYb62pMvPjn-1FovGQC6TeQh5oWO0Rm-2tUbXbWGB3yMuuiei97aRmIGKzMTOHjSOGl1lesozN_enaqvdpdY34JY25nItecc0Tvm8ijx78m7xyzsrFkDLb-dlxMSiy2Oh8J/w350/usb-flash.jpg" title="Connecting a USB device (flash drive) to the PocketBeagle." width="350" /></a><div class="cite">Connecting a USB device (flash drive) to the PocketBeagle.</div></p> <h2>Analog inputs</h2> <p>The PocketBeagle has 8 analog input pins. Six of them take an input from 0 to 1.8V, while two take an input from 0 to 3.3V. (Be careful that you don't overload the input.) The analog input value (between 0 and 4095) can be read from the file system as shown below. Change the number in <code>voltage0</code> to select the input. (Inputs 5 through 7 require special handling.<span id="fnref:analog"><a class="ref" href="#fn:analog" rel="footnote">15</a></span>)</p> <pre> $ cat /sys/bus/iio/devices/iio:device0/in_voltage0_raw 2510 </pre> <p>In the photo below, I hooked up a light sensor (CdS photocell in a voltage divider) to provide a voltage to analog input 0 (header pin P1_19). The reference voltages come from header pins P1_17 (analog ground) and P1_18 (analog reference 1.8V). More light on the sensor produces a higher voltage, yielding a higher value from the input.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4GXLJQg3GAol-ti8r-RDTYWJZ19hYWtBLR0Euw1m7Eze1juJFNQg0PqPDxrHXMiIZNXsYLh1IrDQ3Ql1zL7dtqSW75aV45UnIdbf1pAG4nCeljHexp0KZNxVT9I1eS-vZU3AX_8jZ2RGn/w9999/pocketbeagle-analog.jpg"><img alt="A photocell can be hooked up to the PocketBeagle's analog input to provide a light sensor." class="hilite" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4GXLJQg3GAol-ti8r-RDTYWJZ19hYWtBLR0Euw1m7Eze1juJFNQg0PqPDxrHXMiIZNXsYLh1IrDQ3Ql1zL7dtqSW75aV45UnIdbf1pAG4nCeljHexp0KZNxVT9I1eS-vZU3AX_8jZ2RGn/w350/pocketbeagle-analog.jpg" title="A photocell can be hooked up to the PocketBeagle's analog input to provide a light sensor." width="350" /></a><div class="cite">A photocell can be hooked up to the PocketBeagle's analog input to provide a light sensor.</div></p> <h2>I2C / SPI</h2> <p>The PocketBeagle supports two SPI ports and two I2C ports. These serial protocols are popular for controlling chips and other devices.</p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpw3nqa1qYEcTVE1y-YoigelF7WGDDggcY4XfFQ822ZyVKRajY4tR-QmU3OLBOUPUwQlaG_zIBOGcKlCXFAJRfZGkNb4O500TpSwJzmVjERzHccIyQvC_D3BCnz0cAm9rTWs7GcQh0K-Jb/w9999/pocketbeagle-i2c-accelerometer.jpg"><img alt="An accelerometer board (left) can be connected to the PocketBeagle's I2C port with four wires." class="hilite" height="283" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpw3nqa1qYEcTVE1y-YoigelF7WGDDggcY4XfFQ822ZyVKRajY4tR-QmU3OLBOUPUwQlaG_zIBOGcKlCXFAJRfZGkNb4O500TpSwJzmVjERzHccIyQvC_D3BCnz0cAm9rTWs7GcQh0K-Jb/w350/pocketbeagle-i2c-accelerometer.jpg" title="An accelerometer board (left) can be connected to the PocketBeagle's I2C port with four wires." width="350" /></a><div class="cite">An accelerometer board (left) can be connected to the PocketBeagle's I2C port with four wires.</div></p> <p>For example, the photo above shows a cheap <a href="http://amzn.to/2Bt2uia">I2C accelerometer board</a> connected to the PocketBeagle's SPI port. Simply wire the power, ground, SCL (clock) and SDA (data) between the accelerometer and the PocketBeagle's I2C1 port (i.e. header P2 pins 13, 15, 9, 11). Probing for I2C devices with <code>i2cdetect</code> will show that the device uses address 68. The device can be turned on with <code>i2cset</code> and the registers dumped out with <code>i2cdump</code> to obtain acceleration values.<span id="fnref:i2c"><a class="ref" href="#fn:i2c" rel="footnote">16</a></span></p> <p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCckA-I1O9esKpe9WSw0tD_QCAApkbMwUdWowqJ0XwGMJuwnFz_6IywdEeDHO5vfLi0GL0tEBuCFYjUUcLcY9S-NZUZkY1bnryk9GCZY8lLNcNBgfSDXadlY-RmzsgaFzoecaN0rfWTt5s/w9999/pocketbeagle-i2c.png"><img alt="Using an I2C-based accelerometer board with the PocketBeagle." class="hilite" height="244" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCckA-I1O9esKpe9WSw0tD_QCAApkbMwUdWowqJ0XwGMJuwnFz_6IywdEeDHO5vfLi0GL0tEBuCFYjUUcLcY9S-NZUZkY1bnryk9GCZY8lLNcNBgfSDXadlY-RmzsgaFzoecaN0rfWTt5s/w350/pocketbeagle-i2c.png" title="Using an I2C-based accelerometer board with the PocketBeagle." width="350" /></a><div class="cite">Using an I2C-based accelerometer board with the PocketBeagle.</div></p> <h2>Conclusion</h2> <p>The PocketBeagle is a low-cost, compact Linux computer, able to control external devices with its I/O ports and GPIO pins. Since the PocketBeagle was released recently, there isn't a whole lot of documentation on it. Hopefully this article has shown you how to get started with the PocketBeagle and use some of its features.</p> <p><span style="background-color:yellow;">New (12/2017): The <a href="https://github.com/beagleboard/pocketbeagle/wiki/System-Reference-Manual">PocketBeagle System Reference Manual</a> has lots of useful information, so take a look.</span></p> <p>For more information, see the <a href="https://github.com/beagleboard/pocketbeagle/wiki/FAQ">PocketBeagle FAQ</a> and <a href="https://forum.digikey.com/t/pocketbeagle-getting-started/567">Getting Started</a> pages. Also remember that the PocketBeagle uses the same processor and Linux kernel as the BeagleBone, so most of the information on the BeagleBone will carry over to the PocketBeagle. I've found the book <a href="http://amzn.to/2zKQjQC">Exploring BeagleBone</a> to be especially helpful. Thanks to Robert Nelson and DigiKey for giving a PocketBeagle tutorial at Hackaday Superconference.</p> <p>Follow me on <a href="https://twitter.com/kenshirriff">Twitter</a> or <a href="http://www.righto.com/feeds/posts/default">RSS</a> to find out about my latest blog posts.</p> <h2>Notes and references</h2> <div class="footnote"> <ol> <li id="fn:slt"> <p>The Octavo package reminds me a bit of the <a href="https://en.wikipedia.org/wiki/IBM_Solid_Logic_Technology">Solid Logic Technology</a> (SLT) modules that IBM used in the 1960s instead of integrated circuits. They consisted of small metal packages containing semiconductor dies and resistors connected together on a ceramic wafer, and were used in computers such as the IBM 360.</p> <p><a class="footnote-backref" href="#fnref:slt" rev="footnote" title="Jump back to footnote 1 in the text">↩</a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7f_z8by4qbFlT7OQcAwH8rfOMuoYrVrtkubHWJaasV8yq7DKRR9fI1hPZffHT9PrgDYgyk61k202EMBM5Q20Sj5KvwHgHqHMYkN3d9od_c4Eiy-NH3H32BrTi9vC1MZ4Vbmvroo0mb-cA/w9999/ibm-slt.jpg"><img alt="Two IBM SLT modules, with a penny for scale. Each module contains semiconductors (transistors or diodes) and printed resistors wired together, an alternative to integrated circuits." class="hilite" height="169" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7f_z8by4qbFlT7OQcAwH8rfOMuoYrVrtkubHWJaasV8yq7DKRR9fI1hPZffHT9PrgDYgyk61k202EMBM5Q20Sj5KvwHgHqHMYkN3d9od_c4Eiy-NH3H32BrTi9vC1MZ4Vbmvroo0mb-cA/w400/ibm-slt.jpg" title="Two IBM SLT modules, with a penny for scale. Each module contains semiconductors (transistors or diodes) and printed resistors wired together, an alternative to integrated circuits." width="400" /></a><div class="cite">Two IBM SLT modules, with a penny for scale. Each module contains semiconductors (transistors or diodes) and printed resistors wired together, an alternative to integrated circuits.</div></p> </li> <li id="fn:sdcard"> <p>On a Mac, I used the following procedure to write the SD card. First, download an image from <a href="http://beagleboard.org/latest-images">beagleboard.org</a>. I use "Stretch IoT (non-GUI) for BeagleBone and PocketBeagle via microSD card". Then unmount the SD drive and format it as FAT-32. (Replace XXX below with the right drive number; don't format your hard disk!) <pre> diskutil list diskutil umountdisk /dev/diskXXX sudo diskutil eraseDisk FAT32 BEAGLE MBRFormat /dev/diskXXX sudo diskutil unmount /dev/diskXXXs1 </pre> Then write the disk image to the SD card: <pre> zcat /tmp/pocketbeagle.img | sudo dd of=/dev/diskXXX bs=2m xzcat *.xz | sudo dd of=/dev/diskXXX </pre> Writing the image took about 10 minutes with a USB to micro-SD adapter. (If it's taking hours, I recommend a different USB adapter.) When done, install the SD card in the PocketBeagle. <a class="footnote-backref" href="#fnref:sdcard" rev="footnote" title="Jump back to footnote 2 in the text">↩</a></p> </li> <li id="fn:kernel"> <p>I'm using Debian with kernel <code>Linux beaglebone 4.14.0-rc8 #1 Mon Nov 6 15:46:44 UTC 2017 armv7l GNU/Linux</code>. If you use a different kernel (such as 3.8.13), many of the software features will be different. <a class="footnote-backref" href="#fnref:kernel" rev="footnote" title="Jump back to footnote 3 in the text">↩</a></p> </li> <li id="fn:mikrobus"> <p>One interesting feature of the PocketBeagle is its headers have the right pinout to support many <a href="https://www.mikroe.com/mikrobus/">mikroBUS</a> boards. This is an open standard for small boards (similar to capes/shields), using a 16-pin connector. Hundreds of "click boards" are available for connectivity (e.g. Bluetooth, WiFi, Ethernet, NFC), sensors (e.g. pressure, temperature, proximity, accelerometer, seismic), security coprocessors, GPS, electronic paper, storage, and many more functions. The PocketBeagle doesn't officially support mikroBUS, but many boards "just work" (<a href="https://github.com/beagleboard/pocketbeagle/wiki/mikroBus%E2%84%A2-Click-Boards">details</a>). <a class="footnote-backref" href="#fnref:mikrobus" rev="footnote" title="Jump back to footnote 4 in the text">↩</a></p> </li> <li id="fn:serial"> <p>For the FTDI serial connection, connect Gnd to P1_22, Rx to P1_30 (UART0 Tx) and Tx to P1_32 (UART0 Rx). <a class="footnote-backref" href="#fnref:serial" rev="footnote" title="Jump back to footnote 5 in the text">↩</a></p> </li> <li id="fn:pinmapdetails"> <p>The <a href="https://github.com/beagleboard/linux/blob/4.14/arch/arm/boot/dts/am335x-pocketbeagle.dts">PocketBeagle device tree file</a> specifies the default pin mappings and names other pin mappings. But if you want to track down the actual hardware meaning of each header pin, it's complicated. The <a href="https://github.com/beagleboard/pocketbeagle/blob/master/PocketBeagle_sch.pdf">PocketBeagle schematic</a> shows the mapping from header pins to balls on the Octavo chip package. The <a href="https://octavosystems.com/octavosystems.com/wp-content/uploads/2015/09/OSD335x-Datasheet.pdf">Octavo OSD335x documentation</a> gives ball map to the Sitara chip. The <a href="http://www.ti.com/lit/pdf/sprs717">Sitara AM335x datasheet</a> lists the up to eight functions assigned to each pin. The <a href="http://www.ti.com/lit/pdf/spruh73">Technical Reference Manual</a> Section 9.3.1.49 describes the control register for each pin. Thus, it's possible but tedious to determine from "first principles" exactly what each PocketBeagle header pin does. <a class="footnote-backref" href="#fnref:pinmapdetails" rev="footnote" title="Jump back to footnote 6 in the text">↩</a></p> </li> <li id="fn:pinmap"> <p>There are a couple problems you can encounter with pin mapping. First, since not all chip pins are exposed on PocketBeagle headers, you're out of luck if you want a function that isn't wired to a header. Second, if you need two functions that both use the same pin, you're also out of luck. Fortunately there's enough redundancy that you can usually get what you need. <a class="footnote-backref" href="#fnref:pinmap" rev="footnote" title="Jump back to footnote 7 in the text">↩</a></p> </li> <li id="fn:devicetree"> <p>The PocketBeagle uses U-Boot The U-Boot overlay is discussed <a href="https://elinux.org/Beagleboard:BeagleBoneBlack_Debian#U-Boot_Overlays">here</a>. For more information on device trees, see <a href="https://learn.adafruit.com/introduction-to-the-beaglebone-black-device-tree">Introduction to the BeagleBone Black device tree</a>. <a class="footnote-backref" href="#fnref:devicetree" rev="footnote" title="Jump back to footnote 8 in the text">↩</a></p> </li> <li id="fn:trm"> <p>The <a href="http://www.ti.com/lit/pdf/spruh73">Technical Reference Manual</a> is a 5041 page document describing all the feature of the Sitara architecture and how to control them. But for specifics on the AM3358 chip used in the BeagleBone, you also need to check the 253 page <a href="http://www.ti.com/lit/pdf/sprs717">datasheet</a>. <a class="footnote-backref" href="#fnref:trm" rev="footnote" title="Jump back to footnote 9 in the text">↩</a></p> </li> <li id="fn:gpio-numbering"> <p>Note that there are two GPIO numbering schemes; either a plain number or register and number. Each GPIO register has 32 GPIOs. For example, GPIO 111 is in register 3 and also known as GPIO 3.15. (3*32+15 = 111) <a class="footnote-backref" href="#fnref:gpio-numbering" rev="footnote" title="Jump back to footnote 10 in the text">↩</a></p> </li> <li id="fn:configpin"> <p>To switch P1_33 back to a GPIO, use <code>config-pin P1_33 gpio</code>.</p> <p>Internally, <code>config-pin</code> writes to a pseudo-file such as <code>/sys/devices/platform/ocp/ocp:P1_33_pinmux/state</code> to cause the kernel to change the pin's configuration. <a class="footnote-backref" href="#fnref:configpin" rev="footnote" title="Jump back to footnote 11 in the text">↩</a></p> </li> <li id="fn:gpio"> <p>You can control GPIO pins from a PRU. However, there will be several cycles of latency as the control signal is delivered from the PRU to the GPIO. A PRU pin on the other hand can be read or written immediately. <a class="footnote-backref" href="#fnref:gpio" rev="footnote" title="Jump back to footnote 12 in the text">↩</a></p> </li> <li id="fn:wifi"> <p>WiFi on the PocketBeagle is easy to set up using a command line program called <code>connmanctl</code>. Instructions on configuring WiFi with <code>connmanctl</code> are <a href="https://www.digikey.com/en/maker/blogs/how-to-setup-wifi-on-the-beaglebone-black-wireless/f6452fa17bd24347a59f306355ebfef8">here</a> and also are listed in the /etc/network/interfaces file. (Don't edit that file.) When I started up <code>connmanctl</code>, it gave an error about VPN connections; I ignored the error. I tested WiFi with a <a href="https://www.adafruit.com/product/814">Mini USB WiFi module</a> and an <a href="https://www.adafruit.com/product/1012">Ourlink USB WiFi module</a>. <a class="footnote-backref" href="#fnref:wifi" rev="footnote" title="Jump back to footnote 13 in the text">↩</a></p> </li> <li id="fn:ethernet"> <p>Sharing an Internet connection with the PocketBeagle isn't as simple as I'd like. To share with Windows, I followed the instructions <a href="https://billwaa.wordpress.com/2014/08/03/beaglebone-black-enable-usb-internet-sharing-from-windows/">here</a> and <a href="http://derekmolloy.ie/beaglebone/getting-started-usb-network-adapter-on-the-beaglebone/">here</a>. (Note that BeagleBone instructions should work for the PocketBeagle.) I haven't had much luck with MacOS. In any case, I recommend connecting to the serial console first since there's a good chance you'll lose any SSH connection while reconfiguring the networking. <a class="footnote-backref" href="#fnref:ethernet" rev="footnote" title="Jump back to footnote 14 in the text">↩</a></p> </li> <li id="fn:analog"> <p>Analog input pins 5 and 6 are shared with a GPIO pin via a voltage divider. To use one of these inputs, you must configure the shared GPIO as an input with no pullup/down so it won't affect the analog value. In addition, the input voltage is divided by 2 (so these pins can support up to 3.3V instead of 1.8V). <pre> # Analog input 5 (P2_35) $ config-pin P2_35 gpio $ echo in > /sys/class/gpio/gpio86/direction $ cat /sys/bus/iio/devices/iio:device0/in_voltage5_raw # Analog input 6 (P1_2) $ config-pin P1_2 gpio $ echo in > /sys/class/gpio/gpio87/direction $ cat /sys/bus/iio/devices/iio:device0/in_voltage6_raw </pre></p> <p>Analog input 7 (P2_36) is multiplexed by the power management IC (PMIC). It supports a maximum voltage of 1.8V. To read the value, you must first configure the PMIC: <pre> $ sudo i2cset -y -f 0 0x24 9 5 $ cat /sys/bus/iio/devices/iio:device0/in_voltage7_raw </pre> <a class="footnote-backref" href="#fnref:analog" rev="footnote" title="Jump back to footnote 15 in the text">↩</a></p> </li> <li id="fn:i2c"> <p>In the accelerometer example, the board is approximately vertical with the chip's X axis pointing up. The X, Y, and Z accelerations returned by <code>i2cdump</code> in the screenshot were 0x42a8, 0x02dc, and 0x1348. These are signed values, scaled so 16384 is 1G. Thus, the X acceleration was approximately 1 G (due to Earth's gravity) while the other accelerations were small. These values change if the board's orientation changes or the board is accelerated. The temperature is 0xed10, which according to the formula in the <a href="https://www.invensense.com/wp-content/uploads/2015/02/MPU-6000-Register-Map1.pdf">register map</a> yields 22.3°C or 72°F. The last three words are the gyroscope values, which are approximately 0 since the board isn't rotating. For more details on the accelerometer board see the <a href="https://www.invensense.com/wp-content/uploads/2015/02/MPU-6000-Register-Map1.pdf">register map</a>, the <a href="https://www.invensense.com/wp-content/uploads/2015/02/MPU-6000-Datasheet1.pdf">datasheet</a> and <a href="https://playground.arduino.cc/Main/MPU-6050">this Arduino post</a>. <a class="footnote-backref" href="#fnref:i2c" rev="footnote" title="Jump back to footnote 16 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/973294018243505448' onclick=''> 9 comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=973294018243505448' 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=973294018243505448&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=973294018243505448&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=973294018243505448&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=973294018243505448&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=973294018243505448&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=973294018243505448&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/beaglebone' rel='tag'>beaglebone</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://i.imgur.com/uvJaIIN.gif' itemprop='image_url'/> <meta content='6264947694886887540' itemprop='blogId'/> <meta content='4592117220894903853' itemprop='postId'/> <a name='4592117220894903853'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='http://www.righto.com/2016/09/how-to-run-c-programs-on-beaglebones.html'>How to run C programs on the BeagleBone's PRU microcontrollers</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-4592117220894903853' itemprop='description articleBody'> <style> .gist { max-width: 40em; } .gist .blob-num { font-size: 85% !important; line-height: 85% !important; } .gist .blob-code-inner { font-size: 85% !important; line-height: 85% !important; } .gist-meta { font-size: 46% !important; padding: 2px !important; } pre.command { font-size: 80%; border: none; background-color: #eee; white-space: pre-wrap; } </style> <meta property="og:image" content="//static.righto.com/images/beaglebone/altoids.jpg" /> This article describes how to write C programs for the BeagleBone's microcontrollers. The BeagleBone Black is an inexpensive, credit-card sized computer that has two built-in microcontrollers called PRUs. By using the PRUs, you can implement real-time functionality that isn't possible in Linux. The PRU microcontrollers can be programmed in C using an IDE, which is much easier than low-level assembler programming. I recently wrote <a href="http://www.righto.com/2016/08/pru-tips-understanding-beaglebones.html">an article</a> about the PRU microcontrollers, explaining how to program them in assembler and describing how they interact with the main ARM processor; so read it for more background. Warning: this post uses the 3.8.13-bone79 kernel; many things have changed since then. <p> <h2>A "blink" program in C</h2> To motivate the discussion, I'll use a simple program that uses the PRU to flash an LED ten times. This example is based on <a href="https://credentiality2.blogspot.com/2015/09/beaglebone-pru-gpio-example.html">PRU GPIO example</a> but using C instead of assembly code. <p> <a href="http://imgur.com/uvJaIIN"><img alt="Blinking an LED using the BeagleBone's PRU microcontroller." height="422" src="http://i.imgur.com/uvJaIIN.gif" title="Blinking an LED using the BeagleBone's PRU microcontroller." width="400"/></a> <p> <div class="cite"> Blinking an LED using the BeagleBone's PRU microcontroller. </div> <p> The C code, below, flashes the LED ten times. The LED is controlled by setting or clearing a bit in register R30, which controls the GPIO pins. The code demonstrates two ways of performing delays. The first delay uses a <i>for</i> loop, leaving the LED on for 400 ms. The second delay uses the special compiler function <i>__delay_cycles()</i>, which delays for the specified number of cycles. Since the PRUs run at 200 MHz, each cycle is 5 nanoseconds, yielding an off time of 300 ms. At the end, the code sends an interrupt to the host code via register R31 to let it know the PRU has finished.<a class="ref" href="#ref1">[1]</a> <p> <script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script><script src="https://gist.github.com/shirriff/92b9b71159dc2e3835dedf2368f0071b.js"></script> <p> <h2>How to compile C programs with Code Composer Studio</h2> Although you can compile C programs directly on the BeagleBone,<a class="ref" href="#ref2">[2]</a> it's more convenient to use an IDE. Texas Instruments provides Code Composer Studio (CCS), an integrated development environment on Windows and Linux that you can use to compile C programs for the PRU.<a class="ref" href="#ref3">[3]</a> To install CCS, use the following steps: <ul> <li>Download CCS <a href="http://www.ti.com/tool/ccstudio-sitara">here</a>. (You'll need to create a TI account and then fill out an export approval form before downloading, which seems so 1990s but isn't too difficult.) <li>Follow the instructions <a href="http://processors.wiki.ti.com/index.php/Linux_Host_Support_CCSv6">here</a> to make sure you have the necessary dependencies or CCS installation will mysteriously fail. <li>In the installer, select Sitara 32-bit ARM Processors: GCC ARM Compiler and TI ARM Compiler. <li>In the add-ons dialog, selects PRU Compiler. <li>After installation, run CCS, select Help -> CCS App Center, and install the additional add-ons (i.e. the PRU compiler). </ul> <p> <p> To create a C program in CCS, use the following steps. The image highlights the fields to update in the dialog. <ul> <li>Start CCS. <li>Click New Project. <li>Change target to AM3358. <li>Change tab to PRU. <li>Enter a project name, e.g. "test". <li>Open "Project templates and examples" and select "Basic PRU Project". <li>Click Finish. <li>Enter the code. </ul> <p> <a href="//static.righto.com/images/beaglebone/ccs_setup.png"><img alt="How to set up Code Composer Studio to compile a PRU program for the BeagleBone." class="hilite" height="376" src="//static.righto.com/images/beaglebone/ccs_setup-w300.png" title="How to set up Code Composer Studio to compile a PRU program for the BeagleBone." width="300"> </a> <p> <div class="cite"> How to set up Code Composer Studio to compile a PRU program for the BeagleBone. </div> <p> To set up the BeagleBone for the example: <ul> <li> Download the device tree file: /lib/firmware/<a href="https://gist.github.com/shirriff/11d3e9b550b6c33040548403750ea0e4#file-pru-gpio-example-00a0-dts">PRU-GPIO-EXAMPLE-00A0.dts</a>. <li>Compile and install the device tree file to enable the PRU: <pre class="command"> # dtc -O dtb -I dts -o /lib/firmware/PRU-GPIO-EXAMPLE-00A0.dtbo -b 0 -@ PRU-GPIO-EXAMPLE-00A0.dts # echo PRU-GPIO-EXAMPLE > /sys/devices/bone_capemgr.?/slots # cat /sys/devices/bone_capemgr.?/slots </pre> <li> Download the linker command file <a href="https://gist.github.com/shirriff/d0bdfc412de02b6c68b804e22874c65a">bin.cmd</a>. <li> Download the host file that loads and runs the PRU code (<a href="https://gist.github.com/shirriff/c33376f989b8e512f4fb3226560d6e6b#file-loader-c">loader.c</a>) and compile it: <pre class="command"> # gcc -o loader loader.c -lprussdrv </pre> </ul> To compile and run the C program: <ul> <li>In CCS, select Project -> Build All (control-B) to compile the program.<a class="ref" href="#ref4">[4]</a> <li>Copy the binary (test/Debug/test.out) to BeagleBone (e.g. with scp) <li>On the BeagleBone, link and run the program:<a class="ref" href="#ref5">[5]</a> <pre class="command"> # hexpru bin.cmd test.out # ./loader text.bin data.bin </pre> </ul> <p> If everything went correctly, the LED should flash. (See my <a href="http://www.righto.com/2016/08/pru-tips-understanding-beaglebones.html">previous article</a> for debugging help.) <p> In this example, <i>loader</i> simply loads and runs the executable on the PRU.<a class="ref" href="#ref6">[6]</a> In a more advanced application, it would communicate with the PRU. For example, it could get commands from a web page, send them to the PRU, get results, and display them on the web. The point is that you can use the Linux-side code to do complex network or computational tasks, in combination with the PRU doing low-level, real-time hardware operations. It's kind of like having an Arduino together with a "real computer", in a tiny package. <p> <a href="//static.righto.com/images/beaglebone/altoids3.jpg"><img alt="The BeagleBone Black is a tiny computer that fits inside an Altoids mint tin. It is powered by the TI Sitara™ AM3358 processor, the large square chip in the center." class="hilite" height="232" src="//static.righto.com/images/beaglebone/altoids3-w400.jpg" title="The BeagleBone Black is a tiny computer that fits inside an Altoids mint tin. It is powered by the TI Sitara™ AM3358 processor, the large square chip in the center." width="400"> </a> <p> <div class="cite"> The BeagleBone Black is a tiny computer that fits inside an Altoids mint tin. It is powered by the TI Sitara™ AM3358 processor, the large square chip in the center. </div> <h2>Documentation</h2> The PRUs are very complex and don't have nice APIs, so you'll probably end up reading a lot of documentation to use them. The most important document that describes the Sitara chip is the 5041-page <a href="http://www.ti.com/lit/pdf/spruh73">Technical Reference Manual</a> (TRM for short). This article references the TRM where appropriate, if you want more information. Information on the PRU is inconveniently split between the TRM and the <a href="http://elinux.org/Ti_AM33XX_PRUSSv2#Resources">AM335x PRU-ICSS Reference Guide</a>. For specifics on the AM3358 chip used in the BeagleBone, see the 253 page <a href="http://www.ti.com/lit/pdf/sprs717">datasheet</a>. Texas Instruments' has the <a href="http://processors.wiki.ti.com/index.php/PRU-ICSS">PRU wiki</a> with more information. More information on using CCS is <a href="https://www.embeddedrelated.com/showarticle/603.php">here</a>. <p> If you're looking to use the BeagleBone and/or PRU I highly recommend the detailed and informative book <a href="https://www.amazon.com/Exploring-BeagleBone-Techniques-Building-Embedded/product-reviews/1118935128/ref=as_li_ss_tl?ie=UTF8&filterByStar=four_star&showViewpoints=0&pageNumber=1&linkCode=ll2&tag=rightocom&linkId=38cbfe74587d3c928a24f725f39e521e">Exploring BeagleBone</a>. Helpful web pages on the PRU include <a href="http://mythopoeic.org/bbb-pru-minimal/">BeagleBone Black PRU: Hello World</a>, <a href="https://www.element14.com/community/community/designcenter/single-board-computers/next-gen_beaglebone//blog/2013/05/22/bbb--working-with-the-pru-icssprussv2">Working with the PRU</a> and <a href="https://credentiality2.blogspot.com/2015/09/beaglebone-pru-gpio-example.html">BeagleBone PRU GPIO example</a>. Some PRU example code is in the <a href="http://processors.wiki.ti.com/index.php/PRU_Training:_Hands-on_Labs">TI PRU training course</a>. <p> <a href="//static.righto.com/images/beaglebone/beaglebone_closeup.jpg"><img alt="The BeagleBone Black, with the AM3358 processor in the center. The 512MB DRAM chip is below, with the HDMI framer chip to the right of it. The 4GB flash chip is in the upper right." class="hilite" height="307" src="//static.righto.com/images/beaglebone/beaglebone_closeup-w300.jpg" title="The BeagleBone Black, with the AM3358 processor in the center. The 512MB DRAM chip is below, with the HDMI framer chip to the right of it. The 4GB flash chip is in the upper right." width="300"> </a> <p> <div class="cite"> The BeagleBone Black, with the AM3358 processor in the center. The 512MB DRAM chip is below, with the HDMI framer chip to the right of it. The 4GB flash chip is in the upper right. </div> <h2>Using a timer and interrupts</h2> For a more complex example, I'll show how to use the PRU with a timer and interrupts.<a class="ref" href="#ref7">[7]</a> The basic idea is the timer will trigger an interrupt at a set frequency. The PRU code in this example will toggle the GPIO pin when an interrupt occurs, generating a sequence of 5 pulses.<a class="ref" href="#ref8">[8]</a> <p> It is important to understand that PRU interrupts are not "real" interrupts that interrupt execution, but are signaled through polling.<a class="ref" href="#ref9">[9]</a> A PRU interrupt sets bit 30 or bit 31 in register R31.<a class="ref" href="#ref10">[10]</a> The PRU code can busy-wait on this bit to determine if an interrupt has happened. This is fast and very low latency, compared to context-switching interrupt, but it puts more demands on the program structure. <p> The first step is to add the plumbing for the timer's interrupt, so the PRU will receive the interrupt. The PRUs can handle 64 different interrupt types from various subcomponents of the system. The timer interrupt is assigned system event number 15 and has the cryptic name <i>pr1_ecap_intr_req</i>. (See TRM table 4-22.) Interrupts are configured in the host side code (loader.c) using the PRUSSDRV library API call <a href="http://processors.wiki.ti.com/index.php/PRU_Linux_Application_Loader_API_Guide#prussdrv_pruintc_init">prussdrv_pruintc_init</a>. To support the timer interrupt, The diagram below shows the complex PRU interrupt configuration on the BeagleBone (<a href="http://www.righto.com/2016/08/pru-tips-understanding-beaglebones.html">details</a>). The new interrupt path, highlighted in red, connects the timer interrupt (15) to CHANNEL0 and in turn to register R31, the register for polling. <p> <a href="//static.righto.com/images/beaglebone/prussdrv_interrupt_handling.png"><img alt="Interrupt handling on the BeagleBone for the PRU microcontrollers. The timer interrupt (15) is shown in red. The default interrupt configuration is extended so the timer interrupt will trigger bit 30 of R31." class="hilite" height="303" src="//static.righto.com/images/beaglebone/prussdrv_interrupt_handling-w600.png" title="Interrupt handling on the BeagleBone for the PRU microcontrollers. The timer interrupt (15) is shown in red. The default interrupt configuration is extended so the timer interrupt will trigger bit 30 of R31." width="600"> </a> <p> <div class="cite"> Interrupt handling on the BeagleBone for the PRU microcontrollers. The timer interrupt (15) is shown in red. The default interrupt configuration is extended so the timer interrupt will trigger bit 30 of R31. </div> <p> To add interrupt 15 to the configuration as shown above, the configuration struct in loader.c must be modified. The following structure is passed to prussdrv_pruintc_init to set up the interrupt handling. The changes are highlighted in red. Without this change, timer interrupts will be ignored and the example code will not work. <p> <pre class="command" style="font-size:65%"> #define PRUSS_INTC_CUSTOM { \ { PRU0_PRU1_INTERRUPT, PRU1_PRU0_INTERRUPT, PRU0_ARM_INTERRUPT, PRU1_ARM_INTERRUPT, \ ARM_PRU0_INTERRUPT, ARM_PRU1_INTERRUPT, <span style="color: red">15,</span> (char)-1 }, \ { {PRU0_PRU1_INTERRUPT,CHANNEL1}, {PRU1_PRU0_INTERRUPT, CHANNEL0}, {PRU0_ARM_INTERRUPT,CHANNEL2}, {PRU1_ARM_INTERRUPT, CHANNEL3}, \ {ARM_PRU0_INTERRUPT, CHANNEL0}, {ARM_PRU1_INTERRUPT, CHANNEL1}, <span style="color: red">{15, CHANNEL0},</span> {-1,-1}}, \ { {CHANNEL0,PRU0}, {CHANNEL1, PRU1}, {CHANNEL2, PRU_EVTOUT0}, {CHANNEL3, PRU_EVTOUT1}, {-1,-1} }, \ (PRU0_HOSTEN_MASK | PRU1_HOSTEN_MASK | PRU_EVTOUT0_HOSTEN_MASK | PRU_EVTOUT1_HOSTEN_MASK) \ } </pre> <p> The second step to using the timer is to initialize the timer to create interrupts at the desired frequency, as shown in the following code. Using PRU features is fairly difficult since you are controlling them through low-level registers, not a convenient API, so you'll probably need to study TRM section 15.3 to fully understand this. The basic idea is the timer counts up by 1 every cycle (PWM mode is enabled in ECCTL2). When the counter reaches the value in the APRD (period) register, it resets and triggers a "compare equal" interrupt (as controlled by ECEINT). Thus, interrupts will be generated with the period specified by <i>DELAY_NS</i>. <pre class="command"> inline void init_pwm() { *PRU_INTC_GER = 1; // Enable global interrupts *ECAP_APRD = DELAY_NS / 5 - 1; // Set the period in cycles of 5 ns *ECAP_ECCTL2 = (1<<9) /* APWM */ | (1<<4) /* counting */; *ECAP_TSCTR = 0; // Clear counter *ECAP_ECEINT = 0x80; // Enable compare equal interrupt *ECAP_ECCLR = 0xff; // Clear interrupt flags } </pre> <p> The final step is to wait for the interrupt to happen with a busy-wait. The while loop polls register R31 until the timer interrupt fires and sets bit 30. Then the interrupt is cleared in the PRU interrupt subsystem and in the timer subsystem. <pre class="command"> inline void wait_for_pwm_timer() { while (!(__R31 & (1 << 30))) {} // Wait for timer compare interrupt *PRU_INTC_SICR = 15; // Clear interrupt *ECAP_ECCLR = 0xff; // Clear interrupt flags } </pre> <p> The oscilloscope trace below shows the result of the timer example program: five precision pulses with a width of 100 nanoseconds on and 100 nanoseconds off. The important advantage of using the PRU microcontroller rather than the regular ARM processor is the output is stable and free of jitter. You don't need to worry about nondeterminism such as context switches or cache misses. If your application won't be affected by milliseconds of random delay, the regular processor is much easier to program, but if you require precision timing, you should use the PRU. <p> <a href="//static.righto.com/images/beaglebone/pru_100ns.bmp"><img alt="Using the BeagleBone Black's PRU microcontroller to generate pulses with a width of 100 nanoseconds." class="hilite" height="219" src="//static.righto.com/images/beaglebone/pru_100ns-w300.bmp" title="Using the BeagleBone Black's PRU microcontroller to generate pulses with a width of 100 nanoseconds." width="300"> </a> <p> <div class="cite"> Using the BeagleBone Black's PRU microcontroller to generate pulses with a width of 100 nanoseconds. </div> <p> The full source code for the timer example is <a href="https://gist.github.com/shirriff/2a7cf2f1adb37011da827f1c7f47b992">here</a>.<a class="ref" href="#ref11">[11]</a> To run the timer example, you'll also need to use the updated <a href="https://gist.github.com/shirriff/8be2a50d802dcf255e0f23a30a56079f">loader.c</a> that enables interrupt 15 (or else nothing will happen). <h2>Conclusion</h2> The PRU microcontrollers give the BeagleBone real-time, deterministic processing, but with a substantial learning curve. Programming the PRUs in C using the IDE is much easier than programming in assembler. (And you can embed assembler code in C if necessary.) <p> Combining the BeagleBone's full Linux environment with the PRU microcontrollers yields a very powerful system since the microcontrollers provide low-level real-time control, while the main processor gives you network connectivity, web serving, and all the other power of a "real" computer. (My current project using the PRU is a 3 megabit/second Ethernet emulator/gateway to connect to a <a href="http://www.righto.com/2016/06/y-combinators-xerox-alto-restoring.html">Xerox Alto</a>.) <h2>Notes and references</h2> <a name="ref1"></a>[1] Delivering the interrupt to the host code is more complex than you'd expect. I wrote a longer description <a href="http://www.righto.com/2016/08/pru-tips-understanding-beaglebones.html">here</a>, explaining details such as how event 3 on the PRU turns into event 0 on the host. <p> <a name="ref2"></a>[2] To compile a C program on the BeagleBone, use the <a href="http://www.ti.com/lit/pdf/spruhv7">clpru</a> command. See <a href="https://www.embeddedrelated.com/showarticle/603.php">this article</a> for details on clpru. <p> <a name="ref3"></a>[3] Code Composer Studio isn't available for Mac, but CCS works well if you run Linux on your Mac using <a href="https://www.amazon.com/Parallels-Desktop-11-for-Mac/dp/B013XFGA6G/ref=as_li_ss_tl?ie=UTF8&qid=1474325835&sr=8-1&keywords=parallels&linkCode=ll1&tag=rightocom&linkId=f2907f88d7dcdfa3accadb20f996f7f1">Parallels</a>. I also tried running Linux in VirtualBox, but ran into too many problems. <p> <a name="ref4"></a>[4] If you want to see the assembly code generated by the C compiler, use the following steps: <ul> <li>Go to Project -> Properties <li>Select the configuration you're building (Debug or Release) <li>Check Advanced Options -> Assembler Options: Keep the generated assembly language file. This adds the <i>--keep_asm</i> flag to the compile. </ul> <p> The resulting assembly file will be in <i>Debug/main.asm</i>. Although the file is hundreds of lines long, the actual generated code is much shorter, starting a few dozen lines into the file. Comments indicate which source lines correspond to the assembly lines. <p> <a name="ref5"></a>[5] The <i>hexpru</i> utility converts the ELF-format file generated by the compiler into a raw image file that can be loaded onto the PRU. The <i>bin.cmd</i> file holds the command-line options for hexpru. See the <a href="http://www.ti.com/lit/pdf/spruhv6">PRU Assembly Language Tools</a> manual for details. <p> You can configure Code Composer Studio to run hexpru automatically as part of compilation, by doing a bit of configuration. Follow the steps at <a href="https://e2e.ti.com/support/development_tools/code_composer_studio/f/81/t/403440">here</a> to enable and configure PRU Hex Utility. <p> <a name="ref6"></a>[6] The loader.c code uses the <a href="http://processors.wiki.ti.com/index.php/PRU_Linux_Application_Loader_API_Guide">PRU Linux Application Loader API</a> (PRUSSDRV) to interact with the PRU. I'm told that the cool new framework is <a href="http://processors.wiki.ti.com/index.php/PRU-ICSS_Remoteproc_and_RPMsg">remoteproc</a>, but I'll stick with PRUSSDRV for now. (There seems to be a great deal of churn in the BeagleBone world, with huge API changes in every kernel.) <p> <a name="ref7"></a>[7] For a timer, I'll use the PRU's ECAP module, which can be configured for PWM and then used as a 32-bit timer. (Yes, this is confusing; see TRM section 15.3 for details.) <p> <a name="ref8"></a>[8] This code is intended to demonstrate the timer, not show the best way to generate pulses. If you just want to generate pulses, use the PWM or even a simple delay loop. <p> <a name="ref9"></a>[9] You might wonder why you'd use the PRU polling interrupts rather than just polling a device register directly. The reason is you can test the R31 register in one cycle, but reading a device register takes about 3 or 4 cycles (<a href="http://processors.wiki.ti.com/index.php/AM335x_PRU_Read_Latencies">read latency details</a>). <p> <a name="ref10"></a>[10] The library uses the convention that PRU0 polls on bit 30 and PRU1 polls on bit 31, but this is arbitrary. You could use both bits to signal one PRU, for instance. <p> <a name="ref11"></a>[11] One complexity in the timer source code is the need to define all the register addresses. To figure out a register address, find the address of the register block in the PRU Local Data Memory Map (TRM 4.3.1.2). Then add the offset of the register (TRM 4.5). Note that you can also access these registers from the Linux host side, but the addresses are different. (The PRU is mapped into the host's address space starting at 0x4a300000, TRM table 2.4.) <p> <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/4592117220894903853' onclick=''> 23 comments: </a> </span> <span class='post-icons'> <span class='item-action'> <a href='https://www.blogger.com/email-post.g?blogID=6264947694886887540&postID=4592117220894903853' 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=4592117220894903853&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=4592117220894903853&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=4592117220894903853&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=4592117220894903853&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=4592117220894903853&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=4592117220894903853&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/beaglebone' rel='tag'>beaglebone</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> <div class='blog-pager' id='blog-pager'> <span id='blog-pager-older-link'> <a class='blog-pager-older-link' href='http://www.righto.com/search/label/beaglebone?updated-max=2016-09-20T09:03:00-07:00&max-results=20&start=4&by-date=false' 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/2024/11/antenna-diodes-in-pentium-processor.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_v8QdRqi55J7a5GCse7dxm01fvN2bIYyi2T8AZCM-PUO8O0cpRgVKXiCy2F6DXRrHBPPK2hBgi8reuBebjysNN7IxwpFvdS1FqOZTyVLkBoFrfRfEhZGA34PiJ1Dw_KFmwPZ3I=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2024/11/antenna-diodes-in-pentium-processor.html'>Antenna diodes in the Pentium processor</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_uePTj2gML4BPofHEpXarzulTe7Xs2Xv9vHXa1aiEjwXp7Z5vVHmTw1yETDjLi4mgnNXfH_RVveRhnb0SLU58OQX8j05NNK_lOocC7RvgWCj_sPJ_Bhdujt2XHVTECSvuTmMEVs7kb7g3764rbHtHXJeec=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/2024/05/blog-post.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_tK3tSM6_EW912AJVoyZHW9W_mmLEM598TC5KT5NPvQKoGXB1e4waSPEaTwc4DPcAncCFheMWi1B3ckzNhU2QMoSOxF8gYHspMgZonEHuWRwk5rsRtY5zIpwiFyynn0EbqbOMZn-_ELG5_8xiSO4ymB=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_uheTY5VDIptRdq_lnm9lx1FfIo8vJ88qo1gpmGTgxnNRudwHZ_lEB7_Ywu_kJ2eZHSTFCZW8erJVp33KYAwWkFgnMzfyYzpmCQdQD4qLQPNww=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/2014/09/mining-bitcoin-with-pencil-and-paper.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_t6ojE057Dz_Xhb3pm1pkW80Ep78NXSzG-55G1SViZ12VGDO_98Hc2TW_JX983QcG1ZxjGzwadt7OIox0uDk5sVnXBK5l3gE3WoEdCMmaqrmb41Ox_YZM1cBUZJwNKvADbB=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> <li> <div class='item-thumbnail-only'> <div class='item-thumbnail'> <a href='http://www.righto.com/2024/08/pentium-navajo-fairchild-shiprock.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_tMNGr60i_8WU3BirDL2vALIN97KI1aXbENFNxd2NRb5J403D_lPzVEw0SXX3CVO1xZBdn6uGKT5clLXNErAGql7SFSG6bei9P5YGY4YE-gXpsUY0ceV3i9j4rblN9cZ_uWUQrD=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2024/08/pentium-navajo-fairchild-shiprock.html'>The Pentium as a Navajo weaving</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/2013/06/teardown-and-exploration-of-magsafe.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_tUSlMOFjxCMh-uSycZrlhuxxE0KxBJyyHfLOqVifx52mQaOkgKkZEOZD2PWcEQBjebNZKTu3H9WMgiefFvYEef15Hb_axrS-bPi9Kb0AycTF6NBim9lvMt0TyIkHakgbUUiKjH2VcRurRsdjs=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2013/06/teardown-and-exploration-of-magsafe.html'>Teardown and exploration of Apple's Magsafe connector</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/2023/01/inside-globus-ink-mechanical-navigation.html' target='_blank'> <img alt='' border='0' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_vzCst8Cyw22Kl_PRXqZfiN_4F16NRQL08gWpVxGE5w97Q1lAnqvdRXm6ecuhexD6skryGLNwDLaOLRnxSh98cfQek0MdX6WMlK6K9TTXqj5oaTMKssQM9Rosw4oMPUGRg5Wu0=w72-h72-p-k-no-nu'/> </a> </div> <div class='item-title'><a href='http://www.righto.com/2023/01/inside-globus-ink-mechanical-navigation.html'>Inside the Globus INK: a mechanical navigation computer for Soviet spaceflight</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'> <span dir='ltr'>beaglebone</span> </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-2'> <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 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/2024/'> 2024 </a> <span class='post-count' dir='ltr'>(20)</span> <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/2024/11/'> November </a> <span class='post-count' dir='ltr'>(1)</span> <ul class='posts'> <li><a href='http://www.righto.com/2024/11/antenna-diodes-in-pentium-processor.html'>Antenna diodes in the Pentium processor</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/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 collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </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 collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='http://www.righto.com/2019/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/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/984859869-widgets.js"></script> <script type='text/javascript'> window['__wavt'] = 'AOuZoY5tIh9XXXQVTDridd1AmThk38PA1w:1732816487498';_WidgetManager._Init('//www.blogger.com/rearrange?blogID\x3d6264947694886887540','//www.righto.com/search/label/beaglebone','6264947694886887540'); _WidgetManager._SetDataContext([{'name': 'blog', 'data': {'blogId': '6264947694886887540', 'title': 'Ken Shirriff\x27s blog', 'url': 'http://www.righto.com/search/label/beaglebone', 'canonicalUrl': 'http://www.righto.com/search/label/beaglebone', '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': '\x3clink rel\x3d\x22me\x22 href\x3d\x22https://www.blogger.com/profile/08097301407311055124\x22 /\x3e\n', '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/2fafd358a4bcb2b4', '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': 'index', 'searchLabel': 'beaglebone', 'pageName': 'beaglebone', 'pageTitle': 'Ken Shirriff\x27s blog: beaglebone'}}, {'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/search/label/beaglebone', 'type': 'feed', 'isSingleItem': false, 'isMultipleItems': true, 'isError': false, 'isPage': false, 'isPost': false, 'isHomepage': false, 'isArchive': false, 'isSearch': true, 'isLabelSearch': true, 'search': {'label': 'beaglebone', 'resultsMessage': 'Showing posts with the label beaglebone', 'resultsMessageHtml': 'Showing posts with the label \x3cspan class\x3d\x27search-label\x27\x3ebeaglebone\x3c/span\x3e'}}}]); _WidgetManager._RegisterWidget('_HeaderView', new _WidgetInfo('Header1', 'header', document.getElementById('Header1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogView', new _WidgetInfo('Blog1', 'main', document.getElementById('Blog1'), {'cmtInteractionsEnabled': false, 'navMessage': 'Showing posts with label \x3cb\x3ebeaglebone\x3c/b\x3e. \x3ca href\x3d\x22http://www.righto.com/\x22\x3eShow all posts\x3c/a\x3e'}, '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>