http://www.evanjbrunner.info/ evanjbrunner 2014-10-29T07:00:00Z Evan Brunner http://www.ejbrunner.info/contact tag:www.evanjbrunner.info,2014-10-29:/posts/raspberry-pi-and-the-silicon-labs-c2-programming-interface/ Raspberry-pi and the Silicon Labs C2 Programming Interface 2014-10-29T07:00:00Z 2014-10-29T07:00:00Z <h2 style="text-align:right;">what? why would anyone do this? <hr> <h3>cause I&#x2019;m cheap and it seemed marginally possible</h3> <p>I recently started a project, and decided that it necessitated connecting a collection of <a href="https://www.silabs.com/Support%20Documents/TechnicalDocs/c8051f30x.pdf">C8051F30x</a> devices to a raspberry-pi. I don&#x2019;t own a device capable of programming the 8-bit micros. Ultimately what I (<em>::cough::cough:: google</em>) discovered was that the <a href="https://lkml.org/lkml/2008/10/3/158">kernel has had support</a> for the C2 interface since 2008 for various <a href="https://github.com/raspberrypi/linux/blob/rpi-3.12.y/drivers/misc/c2port/c2port-duramar2150.c">reasons</a>.</p> <p><a href="http://www.silabs.com/pages/default.aspx">Silicon labs</a> has a wide array of micro controllers that support a programming interface simply refered to as <a href="http://www.silabs.com/Support%20Documents/TechnicalDocs/an127.pdf">C2</a>:</p> <blockquote> <p><em>..a two wire serial communication protocol designed to enable in-system programming and debugging on low pin-count [devices].</em><sup class="footnote" id="fnr1"><a href="#fn1">1</a></sup></p> </blockquote> <p>The <strong>C8051F30 <a href="http://en.wikipedia.org/wiki/Quad_Flat_No-leads_package"><span class="caps">QFN</span></a></strong> has a 4&#xD7;4mm footprint combined with a seemingly impossible number of peripherals. The combination of small size, low pin count, a fast multiplexed <span class="caps">ADC</span>, and at least 3 <span class="caps">PWM</span> outputs couldn&#x2019;t be matched (as far as I found) from the likes of Microchip, Amtel, or Fairchild.</p> <h2 style="text-align:right;">how I did it <hr> <h3>summary</h3> <p>It took some further probing around to figure out that the <code>c2port-core.ko</code> (as it used to be called) <a href="https://lkml.org/lkml/2008/10/7/63">needed an associated client</a>. The included <code>c2port-durmar2150.c</code> is one such example, but is not useful for the <a href="http://elinux.org/RPi_Hardware">Broadcom BCM2835</a> (raspberry pi).</p> <p>Coincidentally I&#x2019;d found a <a href="https://github.com/GBert/openwrt-misc/tree/master/c2port-gpio">gpio-bit-banging implementation</a> in a random openwrt github repo. I&#x2019;m not really sure why it&#x2019;s there (and it&#x2019;s not very well documented) but I was able to splice all this into the official <a href="https://github.com/raspberrypi/linux">raspberry-pi linux repo</a> &#x2013; and create a functional set of modules.</p> <p>I&#x2019;ve setup <a href="https://github.com/ej3/rpi-linux">a fork of the r-pi linux</a> repo that contains my changes. <a href="https://gist.github.com/ej3/f7c56965e6b21f7a9877">This patch</a> created from <a href="https://github.com/ej3/rpi-linux/commit/c588a38519e40284de9aa980131930236e14b07c">commit c588a3851</a> is the quickest way of adding the necessary changes to an arbitrary repo or branch of your own preference.</p> <h3>exercise</h3> <p><strong><span class="caps">NOTE</span></strong>: if you&#x2019;re serious about going down this road, do yourself a favor and proceed in a Linux environment (specifically I used Ubuntu 12.04.5). I&#x2019;ve got a mac, and I&#x2019;ve tried the do-everything-in-<span class="caps">OSX</span> (you can find help all over the web), but <span class="caps">OSX</span> is not Linux. Every step you take, <span class="caps">OSX</span> will remind you of that &#x2013; and you&#x2019;ll need help. Run a VM.</p> <p>Start with a vanilla Raspbian (<em>Debian Wheezy</em>) image from <a href="http://www.raspberrypi.org/downloads/">raspberrypi.org</a>.</p> <p>Boot it up, <a href="https://help.ubuntu.com/community/SSH/OpenSSH/Keys">setup <span class="caps">SSH</span> with some keys</a> (or not).. etc.</p> <p>Clone a linux repo (for the demo I&#x2019;ll use the original the <a href="https://github.com/raspberrypi/linux">raspberrypi/linux repo</a>):</p> <pre> <code class="language-console"> user@host:~/prj$ git clone https://github.com/raspberrypi/linux.git </code> </pre> <p>Apply the patch:</p> <pre> <code class="language-console"> user@host:~/prj/linux$ git clone https://gist.github.com/f7c56965e6b21f7a9877.git user@host:~/prj/linux$ git am --signoff c2port-gpio.patch </code> </pre> <p>Get a cross-compile toolchain<sup class="footnote" id="fnr2"><a href="#fn2">2</a></sup>:</p> <pre> <code class="language-console"> user@host:~/prj$ git clone https://github.com/raspberrypi/tools.git user@host:~/prj$ export CCPREFIX=~/prj/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf- user@host:~/prj$ ${CCPREFIX}gcc --version arm-linux-gnueabihf-gcc (crosstool-NG linaro-1.13.1-4.8-2014.01 - Linaro GCC 2013.11) 4.8.3 20140106 (prerelease) Copyright (C) 2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. </code> </pre> <p>build a configuration that inherits from the rpi:</p> <pre> <code class="language-console"> user@host:~/prj/linux$ #fetch the config from the raspbian build user@host:~/prj/linux$ scp pi@raspberrypi:/proc/config.gz . user@host:~/prj/linux$ gunzip -c config.gz .config user@host:~/prj/linux$ #update it user@host:~/prj/linux$ ARCH=arm CROSS_COMPILE=${CCPREFIX} make oldconfig scripts/kconfig/conf --oldconfig Kconfig * * Restart config... * * * C2PORT * Silicon Labs C2 port support (C2PORT_CORE) [N/m/y/?] (NEW) m C2 port support generic GPIO (C2PORT_GPIO) [N/m/y/?] (NEW) m # # configuration written to .config # </code> </pre> <p>Build the kernel</p> <pre> <code class="language-console"> user@host:~/prj/linux$ #build the kernel with n threads where n=[number of cores]+1 user@host:~/prj/linux$ ARCH=arm CROSS_COMPILE=${CCPREFIX} make -jn </code> </pre> <p>Mount the pi filesystem at root, with root permissions<sup class="footnote" id="fnr3"><a href="#fn3">3</a></sup></p> <pre> <code class="language-console"> user@host:~/prj/linux$ sudo mkdir /mnt/pi user@host:~/prj/linux$ sshfs root@raspberrypi:/ /mnt/pi root@raspberrypi's password: </code> </pre> <p>Build and install the new modules</p> <pre> <code class="language-console"> user@host:~/prj/linux$ ARCH=arm CROSS_COMPILE=${CCPREFIX} \ INSTALL_MOD_PATH=/mnt/pi DEPMOD=/bin/true make -jn modules_install </code> </pre> <p>Slap the new kernel into place</p> <pre> <code class="language-console"> user@host:~/prj/tools/mkimage$ #decompress the image user@host:~/prj/tools/mkimage$ ./imagetool-uncompressed.py ../../linux/arch/arm/boot/zImage user@host:~/prj/tools/mkimage$ #move it to the pi user@host:~/prj/tools/mkimage$ mv kernel.img /mnt/pi/boot/ </code> </pre> <p>Restart the pi<sup class="footnote" id="fnr4"><a href="#fn4">4</a></sup></p> <pre> <code class="language-console"> user@host:~/prj/$ ssh pi@raspberrypi pi@raspberrypi:~/$ sudo reboot </code> </pre> <p>Insert the new modules<sup class="footnote" id="fnr5"><a href="#fn5">5</a></sup><sup class="footnote" id="fnr6"><a href="#fn6">6</a></sup></p> <pre> <code class="language-console"> pi@raspberrypi:~/$ #This enables the c2port on brdcm GPIO ports 17 and 18 pi@raspberrypi:~/$ #which are rpi-GPIO ports 11 and 12 respectively. pi@raspberrypi:~/$ sudo modprobe c2port-gpio c2d=17 c2ck=18 pi@raspberrypi:~/$ #for a quick debug output, mount the debugfs pi@raspberrypi:~/$ #enabled in the default .config: CONFIG_DEBUG_FS=y pi@raspberrypi:~/$ sudo mount -t debugfs none /sys/kernel/debug pi@raspberrypi:~/$ sudo cat /sys/kernel/debug/gpio GPIOs 0-53, bcm2708_gpio: gpio-16 (led0 ) out hi gpio-17 (c2port data ) in lo gpio-18 (c2port clock ) in lo pi@raspberrypi:~/$ </code> </pre> <p>Reach out and touch a microcontroller</p> <pre> <code class="language-console"> pi@raspberrypi:~/$ su root Password: root@raspberrypi:/home/pi# echo 1 /sys/class/c2port/c2port0/access root@raspberrypi:/home/pi# cat /sys/class/c2port/c2port0/dev_id 10 root@raspberrypi:/home/pi# cat /sys/class/c2port/c2port0/rev_id 0 </code> </pre> <p>finishing touches</p> <pre> <code class="language-console"> pi@raspberrypi:~/$ #insert udev rule to mod ownership of c2port dev pi@raspberrypi:~/$ sudo echo "SUBSYSTEM=="c2port", ACTION=="add", PROGRAM="/bin/sh -c 'chown -R pi:pi /sys%p'"" /etc/udev/rules.d/98-c2port.rules pi@raspberrypi:~/$ #automatically load module on boot pi@raspberrypi:~/$ sudo echo "c2port-gpio c2d=17 c2ck=18" /etc/modules </code> </pre> <h2 style="text-align:right;margin-top:50px;">that-last-thing-that-should-probably-be-the-first-thing <hr> <h3>specify device flash size</h3> <p>It&#x2019;s important to note that the <code>c2port-gpio</code> has the flash block size, and number of blocks hard-coded into the driver. To make your specific device work correctly, you&#x2019;ll have to get the flash size from the device specifications and edit the driver before you build. Specifically I did the following for the C8051F30:</p> <pre> <code class="language-diff"> --- a/drivers/misc/c2port/c2port-gpio.c +++ b/drivers/misc/c2port/c2port-gpio.c @@ -67,7 +67,7 @@ static void gpio_c2port_c2ck_set(struct c2port_device *dev, int status) static struct c2port_ops gpio_c2port_ops = { block_size :512, /* bytes */ - blocks_num :30, /* total flash size: 15360 bytes */ + blocks_num :15, /* total flash size: 7680 bytes */ access :gpio_c2port_access, c2d_dir :gpio_c2port_c2d_dir, c2d_get :gpio_c2port_c2d_get, </code> </pre> <p style="margin-top:100px;" class="footnote" id="fn1"><a href="#fnr1"><sup>1</sup></a> <a href="http://www.silabs.com/Support%20Documents/TechnicalDocs/an127.pdf"><strong>AN127</strong></a> <em>Flash Programming via the C2 Interface</em></p> <p class="footnote" id="fn2"><a href="#fnr2"><sup>2</sup></a> The easiest way to get a toolchain is to clone it from <a href="https://github.com/raspberrypi/tools">the raspberrypi github account</a> (as I did in the demo). There are more formal instructions on <a href="http://elinux.org/Raspberry_Pi_Kernel_Compilation#Use_the_provided_compiler">how to use the provided binary</a> or <a href="http://elinux.org/RPi_Linaro_GCC_Compilation">build your own toolchain</a> using crosstool-ng in the <a href="http://elinux.org/Main_Page">Embedded Linux Wiki</a>. Also, there are instructions on how to <a href="http://sysprogs.com/VisualKernel/tutorials/raspberry/buildkernel/">enable kernel debug</a>.</p> <p style="margin-bottom:0px;" class="footnote" id="fn3"><a href="#fnr3"><sup>3</sup></a> The pi doesn&#x2019;t have a root password set by default. To create one: <pre style="margin-top:0px;margin-left:8px"><code class="language-console">pi@raspberrypi:~/$ sudo passwd root</code></pre></p> <p class="footnote" id="fn4"><a href="#fnr4"><sup>4</sup></a> If the pi refuses to boot, your kernel image is bad. Start over.</p> <p class="footnote" id="fn5"><a href="#fnr5"><sup>5</sup></a> If depmod didn&#x2019;t run on reboot, modprobe may claim the module was <code>not found</code>. To fix this quick run <code>depmod --all</code>.</p> <p class="footnote" id="fn6"><a href="#fnr6"><sup>6</sup></a> Actual port mappings can be read from the <a href="http://www.raspberrypi.org/wp-content/uploads/2012/10/Raspberry-Pi-R2.0-Schematics-Issue2.2_027.pdf">schematic</a> (found <a href="http://www.raspberrypi.org/model-b-revision-2-0-schematics/">here</a>), or from <a href="http://elinux.org/RPi_BCM2835_GPIOs#GPIO17">the world&#x2019;s most insane table</a>.</p> </h2> </h2> </h2> <p>I recently started a project, and decided that it necessitated connecting a collection of <a href="https://www.silabs.com/Support%20Documents/TechnicalDocs/c8051f30x.pdf">C8051F30x</a> devices to a raspberry-pi. I don&#8217;t own a device capable of programming the 8-bit micros. Ultimately what I (<em>coughgooglecough</em>) discovered was that the <a href="https://lkml.org/lkml/2008/10/3/158">kernel has had support</a> for the C2 interface since 2008 for various <a href="https://github.com/raspberrypi/linux/blob/rpi-3.12.y/drivers/misc/c2port/c2port-duramar2150.c">reasons</a>.</p> tag:www.evanjbrunner.info,2013-01-10:/posts/layers-for-pdfs-in-r/ Layers for PDFs in R 2013-01-10T08:00:00Z 2013-01-10T08:00:00Z <h2 style="text-align:right;"> <a href="#top" style="color:#555;" id="top">useless</a> personal anecdote re: why layers <hr style="margin-bottom:0px"> <a href="#tldr" style="font-size:.6em;color:#555;margin-top:0px;">tldr</a> </h2> <h3><em>R: an implementation of the S language</em></h3> <p>My fiance was recently working on her thesis (a survey of <a href="http://en.wikipedia.org/wiki/Crangon_crangon">Crangon crangon</a> in the <a href="https://www.google.com/search?q=westfjords&amp;oq=westfjords">Westfjords</a>) and wanted to use R do do some statistical analysis, [and / or] some spatial mapping.</p> <p>Once she got into it, she quickly became frustrated. I dismissed her frustration as the expression of a standard learning curve, and would help her overcome particularly sticky spots now and again when I had the time. Never having used R myself, but hearing so much about it my curiosity was piqued. After I finished what I&#x2019;d most urgently been trying to complete: I started to till into spatial mapping with R; to lend a hand.</p> <p>Having made it this far what I&#x2019;ve learned is that:</p> <ol> <li>R is a quagmire of unintuitive arguments and functions that <strong>don&#x2019;t operate in any uniform or expected way</strong>. There is no idiomatic R.</li> <li>These unpredictable functions with any number of arbitrary arguments in whatever format are actually altogether <strong>poorly documented</strong>. The most practical way to get answers on obscure problems is to search <a href="http://r.789695.n4.nabble.com/">mailing lists</a>, or <a href="http://stackoverflow.com/questions/tagged/r">stackoverflow</a>.</li> <li> <strong>R is not inherently good with resources</strong>: big datasets will consume enough to slow down everything your doing</li> <li> <strong>R is not fast</strong>:<sup class="footnote" id="fnr1"><a href="#fn1">1</a></sup> there is often nothing to gain from having multiple processors &#x2013; <em>R Base</em> is not threaded (you can add packages, and will it to be so: <a href="http://www.rparallel.org/">parallel</a>, <a href="http://cran.r-project.org/web/packages/multicore/index.html">multicore</a>, <a href="http://cran.r-project.org/web/views/HighPerformanceComputing.html">etc</a>). Providing software for parallel or high performance computing (<span class="caps">HPC</span>) with R was not a development goal<sup class="footnote" id="fnr2"><a href="#fn2">2</a></sup>, but rather something that it was born into.</li> </ol> <p>Nevertheless, by the time you&#x2019;ve fully realized the drawbacks: you&#x2019;ll be so far into your first project with R that you can&#x2019;t turn back. You&#x2019;ll proceed diligently to cobble together your own little [fiefdom / house of cards / specific selection of tools] to do exactly what you want &#x2013; and nothing else.</p> <p>And it&#x2019;s just about then that you come back to: hey &#x2013; this R thing <em>is</em> happening.</p> <h3>geospatial mapping in R</h3> <p>She had given me some shapefiles, and I quickly figured out I could load shapefiles from the web (<a href="http://www.gadm.org/"><span class="caps">GADM</span></a>) simple enough</p> <pre> <code class="language-r"> #load map from GADM load_iceland=function() { #setup connection iceland map if (!("iM" %in% ls())) { con - url( "http://www.filefactory.com/file/6dhsa8xf9mpz/n/ISL_adm2_RData") } #load map from GADM # NOTE: if variable name changes, and this function # no longer works print(load(con)) to find new variable name load(con) close(con) return(gadm) } </code> </pre> <p>and plot them using <code>spplot()</code>, part of the <a href="http://cran.r-project.org/web/packages/sp/index.html">sp</a> package. I could even overlay them (by way of <code>spplot()+spplot()</code>) if I used another package <a href="http://cran.r-project.org/web/packages/latticeExtra/index.html">latticeExtra</a>.</p> <p>Then I got that bug that everyone gets &#x2013; I want [more / better] data. Fortunately (or not) I was able to find it. I found more detailed coastline and demographic shapefiles from <a href="http://www.openstreetmap.org/">OpenStreetMap.org</a> via the <a href="http://cran.r-project.org/web/packages/OpenStreetMap/">OpenStreetMap package</a> (credit to <a href="http://www.r-bloggers.com/plot-maps-like-a-boss/">this guy</a>), and then <code>?.dem</code> files from the <em>Advanced Spaceborn Thermal Emission and Reflection Radiometer</em> <a href="http://asterweb.jpl.nasa.gov/">(<span class="caps">ASTER</span>)</a> a Japanese <a href="http://en.wikipedia.org/wiki/Advanced_Spaceborne_Thermal_Emission_and_Reflection_Radiometer">device</a> on the <a href="http://en.wikipedia.org/wiki/Terra_(satellite)">Terra</a> Satellite.</p> <p>It was about this time that I discovered <a href="http://cran.r-project.org/web/packages/rgdal/index.html">rgdal</a> (a set of bindings in R for the Geospatial Data Abstraction Library <a href="http://gdal.org/"><span class="caps">GDAL</span></a>). To load rgdal, first you have to build <span class="caps">GDAL</span> &#x2013; which is a tool external to R that allows the manipulation of &#x201C;raster geospatial datasets&#x201D;, like <code>?.dem</code> files. <span class="caps">GDAL</span> in and of itself turned out to be an enormously useful tool for manipulation of the data external to R. Once I thought I had something pretty swell I&#x2019;d load it up:</p> <pre> <code class="language-r"> if (!("iWater" %in% ls()) LOAD_FULL) { iWater - readOGR(dsn="./iceland_shapefiles", layer="iceland_water") } if (!("iCoast" %in% ls()) LOAD_FULL) { iCoast - readOGR(dsn="./iceland_shapefiles", layer="iceland_coastline") } if (!("iEle" %in% ls()) LOAD_FULL ){ iEle - readOGR(dsn="./iceland_shapefiles", layer="iceland_elevation") iEle$uniform - as.factor(rep(c(1), length(iEle$elev))) } </code> </pre> <p>which is pretty straight forward but for the last line there where I create a column in <code>iEle</code> (<code>uniform</code>) that lets me plot all the elevation lines as one color (as all the rows have the same value==1). If the variables are already in the workspace, I don&#x2019;t load them, and if I want to force them to not load I toggle <code>LOAD_FULL</code>. Loading this data set takes a noticeable few seconds.</p> <p>I fooled around for quite some time with plotting rasterized spatial data in R, and none of it came off all that pretty. I never really got that right.</p> <p>But once you do get something right, you&#x2019;re going to want to export it in a way that&#x2019;ll look pretty on your webpage &#x2013; or in a word file, or (heavens forbid) a PowerPoint presentation, etc. The best way to export plots from R is in a vectorized format (as apposed to raster) such as <span class="caps">SVG</span>, or <span class="caps">PDF</span>. In these formats the display device will be able to recreate the figure dynamically at whatever resolution is required because the file specifies shapes, instead of pixels.</p> <p>But you knew that.</p> <p>So I proceeded to export my whole new nifty stack of spatial plots to a <span class="caps">PDF</span>. Popping it open I was sort of unsurprised to find that the layers I&#x2019;d constructed with the use of latticeExtra weren&#x2019;t preserved. So I googled aimlessly on, and eventually found the <a href="http://r.789695.n4.nabble.com/Creating-a-pdf-with-layers-td4637183.html">following exchange</a>:</p> <blockquote style="margin-bottom:0px;"> <p style="margin-bottom:0px;"><em>Dear all, Is it possible to create a pdf file with layers using the pdf() device in R? Many thanks for your help!</em></p> </blockquote> <p style="text-align:right;margin-top:0px;">-n00b: <strong>Christoph</strong></p> <blockquote style="margin-bottom:0px;"> <p style="margin-bottom:0px;"><em>No. Is it possible to specify layers in the R graphics language or any device? (From what I understand by &#x2018;layers&#x2019;, no.)</em></p> </blockquote> <p style="text-align:right;margin-top:0px;">-humbly: <strong>The author of pdf()</strong></p> <p>This is (I have found) a pretty standard open source guru-type response: the &#x201C;it&#x2019;s not a bug &#x2013; it&#x2019;s a feature&#x201D; response. Nothing is more infuriating. What it really means is one of the following in order of ascending likelihood:</p> <ol> <li>I have no interest in implementing that feature for you.</li> <li>I have no idea how to do that, but I&#x2019;m not going to admit that to you.</li> <li>I have no interest in even trying to figure out if I know how to do that (ie I have too much else to do to get to that)</li> </ol> <p>Quite sure there was no solution in the works, nor would anyone with more experience or insight pursue such nonsense: I got on it directly.</p> <h2 style="text-align:right;">Layers in <code>pdf()</code>? easy-peasy. <hr> </h2> <h3>anatomy</h3> <p><code>pdf()</code> is implemented as what I would eventually come to interpret as an extension. There&#x2019;s a R function that references a quick one-off C library that implements an interface to the graphical device library. It&#x2019;s a quazi <span class="caps">API</span> for graphical devices, but it&#x2019;s purely sequential &#x2013; and omits what could have been executed more intuitively by passing a <span class="caps">XML</span>-like tree object. They went they way they did for the reasons they had at the time, but it makes implementing the interface a bit like trying to make a finger-painting while your hand is asleep.</p> <p>Whatever comes out of the interface has to be dealt with, and even within the calling structure there are arbitrary attempts to clean up repetitive output. But this is that sort of thing where you get the repetitive output anyway. It&#x2019;s mucked up so well that you can&#x2019;t even tell what you&#x2019;re supposed to be able to dismiss.</p> <p>Anyhow, the implementation of <code>pdf()</code> works well enough. Many of the essential objects and their dictionaries are actually statically assigned ids and so forth &#x2013; which tumbles things around again in a sort of bothersome way, but alas &#x2013; I succeeded. <span class="caps">PDF</span> layers (as per the <a href="http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/PDF32000_2008.pdf"><span class="caps">ISO</span> 32000-1 specification</a>) are implemented as &#x201C;Optional Content Groups&#x201D;. I finagled a way within the scope of the original implementation to shuffle the tags and objects into a suitable conformation. Took me a bit longer than I would have expected (as I should have expected) as certain dictionaries that were marked &#x2018;optional&#x2019; in the spec absolutely weren&#x2019;t.</p> <p>In the midst of wrestling with this I found a simple, free (favorite kind) tool that helped me greatly:</p> <ol> <li> <a href="http://www.evanjbrunner.info/files/2013/01/23/application-swing.jnlp"><strong><span class="caps">PDF</span> Object Browser</strong></a> <a href="http://riasuite.canoo.com/?l=en"><em>by canoo</em></a> : A java webstart type application that lets you browse a <span class="caps">PDF</span> tree. The Canoo webisite has since been completely re-done, and the original link to the page for the applicaiton no longer works. For now though, (by downloading and running the file via the provided link) it seems the application is still available with an expired security certificate. It was good while it lasted.</li> </ol> <h3>then I tested it.</h3> <p>The layering I&#x2019;d implemented into <code>pdf()</code> seemed to work with readers like Adobe Acrobat, and Ubuntu&#x2019;s default Document Viewer &#x2013; but not with the CS5 suite I had access too. I was gunning for layers not because I wanted to print PDFs with optional layers (although that&#x2019;s nice), but I wanted PDFs that I could load into Illustrator (Ai) and have all the objects for each figure organized by layer. Then I could do wonderful-cool things like join all the segments that described the coastline and create clipping layers and shadow effects&#x2026; really useful and practical stuff!</p> <p><img src="http://www.evanjbrunner.info/img/2013/01/adobe_pdf_layers_extra.png" class="shadow round right" title="propietary layers, brilliant." alt="propietary layers, brilliant."></p> <p>It turned out, I was exactly half way to nowhere. Ai and the other Adobe CS5 products are stubbornly and knowingly not complaint to the <span class="caps">PDF</span> specification: they don&#x2019;t honor Optional content as layers. Instead, as I would learn, when you build layers in Ai, and then save to a <span class="caps">PDF</span> &#x2013; the <span class="caps">PDF</span> specification is so pliant to an excess of data within the structure that they embed an Illustrator <code>?.ai</code> file right there within it. Wikipedia refers to it as a <a href="http://en.wikipedia.org/wiki/Adobe_Illustrator_Artwork">dual-path</a> approach. <em>Awesome</em>. Why write one file, when you can write two, one within another?! As far as I could figure out it&#x2019;s a compressed postscript format that at one time was probably the grandfather of the <span class="caps">PDF</span> format itself.</p> <p>There was no way I was going to convince the sloppy little <code>pdf()</code> to write a format I had no formal description of.</p> <p>At this point I sadly tried to do something with <code>?.svg</code>, but &#x2013; very sad. Not even workable.</p> <p><img src="http://www.evanjbrunner.info/img/2013/01/ai_groups.png" class="shadow right" title="R groups" alt="R groups"></p> <p>Then I had an epiphany: I realized that Ai <em>had to</em> honor clipping layers. In order to create a clipping layer you need two objects (an object to clip, and an object to specify the clipping) and in Illustrator those objects have to be <em>grouped</em>. <code>pdf()</code> was hierarchy agnostic up and to this point &#x2013; every clipping layer was promptly created, and then closed as soon as possible to retain a constant object depth. Sometimes it would try to exit a dozen times or so &#x2013; sometimes it would create the clipping layers multiple times over: once with something necessary inside, the next time with nothing. It was all rather noisy &#x2013; but fortunately it had no care for the depth of the tree &#x2013; it always wanted to be creating at the root.</p> <p>So I tricked it &#x2013; every time I open an Optional Content group I bump the tree up one layer, and every time I leave a group I bump down one. I force the clip at the media size to so it has absolutely no effect on the content.</p> <h2 style="text-align:right;"> <a href="#tldr" style="color:#555;" id="tldr">end</a> <hr style="margin-bottom:0px"> <a href="#top" style="font-size:.6em;color:#555;margin-top:0px;">top</a> </h2> <h3>what to expect</h3> <p>Adobe CS# products load the new layers from <code>pdf()</code> as superfluous clipping groups. They&#x2019;re unnecessary, but the objects being grouped within them makes it easy enough to reorganize the content to the intended state within 2 minutes. Otherwise, in viewers such as Acrobat and Document Viewer (in Ubuntu) the layers will just load up naturally: as layers. I haven&#x2019;t set it up so you can appropriately name the layers, but that could be done if I get a sense that people are really that excited about it.</p> <p><img src="http://www.evanjbrunner.info/img/2013/01/iceland_fin_00.png" class="shadow round" title="weeeEEEEeee.." alt="weeeEEEEeee.."></p> <h3>usage</h3> <p>All I can provide right now is a <a href="https://github.com/3jb/R_layers">patch</a> for (<a href="http://cran.r-project.org/sources.html"><code>2.16.0</code> <em>Unsuffered Consequences</em></a>). If you know what to do with that: good on you (you have to download the R source, patch it, build it, and install it). If you know what you&#x2019;re doing it&#x2019;s not all that difficult, <a href="http://cran.r-project.org/doc/manuals/R-admin.html#Building-from-source">if you don&#x2019;t</a> &#x2013; maybe throw some comments down below so we can help everyone out &#x2013; so I know where people commonly have problems.. (if you&#x2019;re that motivated). I&#x2019;ve used it on 32 and 64 bit linux machines &#x2013; I doubt that it will work much differently on any other architecture. Nothing I changed was architecture specific, but what I&#x2019;m not sure of is if there are other <span class="caps">PDF</span> engines in there. The extension that I edited was a rudimentary reinvent-the-wheel type of deal, and I was surprised to find that it wasn&#x2019;t just a library. Some systems may load a library(?) if it&#x2019;s available at compile time &#x2013; maybe I just didn&#x2019;t have that configured. I don&#x2019;t really know &#x2013; I&#x2019;m not overly familiar with the grDevices available in R, I just thought I&#x2019;d hack this together and see if it made a stir. If it does and there&#x2019;s legitimate interest in putting it into the next release &#x2013; well, we&#x2019;ll just figure that out as it comes.</p> <p>Pretty straight forward to use:</p> <pre> <code class="language-r"> pdf("file/name",onepage=TRUE) [ PLOT STUFF ] dev.off() </code> </pre> <p>It won&#x2019;t much like you if you try to set the version 1.5 (optional content is only valid 1.5 and after), nor if you try to set <code>onefile=FALSE</code> at the same time. Otherwise it doesn&#x2019;t bite.</p> <p class="footnote" id="fn1"><a href="#fnr1"><sup>1</sup></a> <a href="http://julialang.org/">julialang.org</a></p> <p class="footnote" id="fn2"><a href="#fnr2"><sup>2</sup></a> <a href="http://www.jstatsoft.org/v31/i01/">M. Schmidberger, M. Morgan, D. Eddelbuettel, H. Yu, L. Tierney, U. Mansmann (2009) &#x201C;State of the Art in Parallel Computing with R&#x201D; <em>Journal of Statistical Software</em></a></p> <p>My fiance&eacute; was recently working on her thesis (a survey of <a href="http://en.wikipedia.org/wiki/Crangon_crangon">Crangon crangon</a> in the <a href="https://www.google.com/search?q=westfjords&amp;oq=westfjords">Westfjords</a>) and wanted to use R do do some statistical analysis, [and / or] some spatial mapping. I found that R&#8217;s <code>pdf()</code> lacked the ability to print layers within a document, so I made a patch.</p> tag:www.evanjbrunner.info,2012-07-17:/posts/json-requests-with-httpurlconnection-in-android/ JSON requests with HttpURLConnection in Android 2012-07-17T07:00:00Z 2012-07-17T07:00:00Z <p>In the midst of doing something quazi-irrational, I stumbled over the need to create and send <span class="caps">JSON</span> requests to a web-server in an android context. Software should be oriented towards the inevitable dominance of a better future, and thus I built the mechanics of this new toy to be dependent on <a href="http://developer.android.com/reference/java/net/HttpURLConnection.html">HttpURLConnection</a>, as advised in the Android developer <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">blog</a>:</p> <blockquote> <p><em>For Gingerbread and better, HttpURLConnection is the best choice. Its simple <span class="caps">API</span> and small size makes it great fit for Android. Transparent compression and response caching reduce network use, improve speed and save battery. New applications should use HttpURLConnection; it is where we will be spending our energy going forward.</em></p> </blockquote> <p style="text-align:right;">-<a href="https://plus.google.com/106557483623231970995/about">Jesse Wilson</a> <em>(of Dalvik team, but now square)</em></p> <p>HttpURLConnection has no nifty little <span class="caps">JSON</span> request function, and <a href="http://lmgtfy.com/?q=JSON+HttpURLConnection+request">googling</a> around for a bit didn&#x2019;t turn up anything too exciting or functional.</p> <p>The solution is simply to incrementally build a tailored request:</p> <pre> <code class="language-java"> //can catch a variety of wonderful things try { //constants URL url = new URL("http://myhost.com/ajax"); String message = new JSONObject().toString(); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setReadTimeout( 10000 /*milliseconds*/ ); conn.setConnectTimeout( 15000 /* milliseconds */ ); conn.setRequestMethod("POST"); conn.setDoInput(true); conn.setDoOutput(true); conn.setFixedLengthStreamingMode(message.getBytes().length); //make some HTTP header nicety conn.setRequestProperty("Content-Type", "application/json;charset=utf-8"); conn.setRequestProperty("X-Requested-With", "XMLHttpRequest"); //open conn.connect(); //setup send OutputStream os = new BufferedOutputStream(conn.getOutputStream()); os.write(message.getBytes()); //clean up os.flush(); //do somehting with response is = conn.getInputStream(); String contentAsString = readIt(is,len); } finally { //clean up os.close(); is.close(); conn.disconnect(); } </code> </pre> <p><em>note: the streams don&#x2019;t need to be buffered if they are generally expected to be dealt with in one go, but large messages should be buffered to alleviate device memory load.</em></p> <p>The aim is to build something similar to the following <a href="http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol"><span class="caps">HTTP</span> request</a> <sup class="footnote" id="fnr1"><a href="#fn1">1</a></sup>:</p> <pre> POST /ajax HTTP/1.1 Accept: */* Content-Type: application/json;charset=utf-8 X-Requested-With: XMLHttpRequest User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.0.4; sdk Build/MR1) Host: myhost.com Connection: Keep-Alive Accept-Encoding: gzip Content-Length: 123 {"hash":{"attribute":"123"},"attribute":"value", &#x2026;} </pre> <p>The important attributes are:</p> <dl> <dt><code>content-Type: application/json;charset=utf-8</code></dt> <dd>tell the server to expect a <a href="http://tools.ietf.org/html/rfc4627"><span class="caps">JSON</span> Object</a> </dd> </dl> <dl> <dt><code>X-Requested-With: XMLHttpRequest</code></dt> <dd>pretend this request was created with an <span class="caps">AJAX</span> appropriate <a href="http://en.wikipedia.org/wiki/XMLHttpRequest"><span class="caps">API</span></a> </dd> </dl> <dl> <dt><code>Content-Length: 123</code></dt> <dd>the byte length of the message</dd> </dl> <dl> <dt><code>{"hash":{"attribute":"123"},"attribute":"value", &#x2026;}</code></dt> <dd>the body of the request is a <em>properly formatted</em> <a href="http://tools.ietf.org/html/rfc4627"><span class="caps">JSON</span> Object</a> </dd> </dl> <p>The content length figure may appear particularly innocuous, but it is a lurking evil. The tendency when setting up <code>HttpURLConnection</code> is to lean towards using <a href="http://developer.android.com/reference/java/net/HttpURLConnection.html#setChunkedStreamingMode(int)">setChunkedStreamingMode(int)</a> as you don&#x2019;t have to worry about figuring out the precise message length before you send it. This does <em>not</em> work because the <code>Transfer-Encoding: chunked</code> mechanism apparently inserts additional characters (non-<span class="caps">JSON</span> [formatting / parsing] friendly) into the message body which can cause the server to fail on interpreting the object &#x2013; resulting in failure, or even worse: inconsistent <span class="caps">JSON</span> interpretation. For example<sup class="footnote" id="fnr1"><a href="#fn1">1</a></sup>:</p> <pre> POST /ajax HTTP/1.1 Content-Type: application/json;charset=utf-8 X-Requested-With: XMLHttpRequest User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.0.4; sdk Build/MR1) Host: myhost.com Connection: Keep-Alive Accept-Encoding: gzip Transfer-Encoding: chunked 70 {"data":{"password":"123","email":"ejb"},"method":"account.sign_in",&#x2026; 0 </pre> <p>as interpreted on a rails test bench, has the parameters:</p> <pre> Started POST "/ajax" for localhost 2012-07-16 23:48:36 -0700 Processing by AjaxController#post as */* Parameters: {"ajax"=&gt;{"action"=&gt;"post", "controller"=&gt;"ajax"}} Completed 200 OK in 8ms (Views: 7.2ms | ActiveRecord: 0.0ms) </pre> <p>which is entirely incomplete relative to intention. When the request is assembled (as above) with <a href="http://developer.android.com/reference/java/net/HttpURLConnection.html#setFixedLengthStreamingMode(int)"><notextie>setFixedLengthStreamingMode(&#x2026;)</notextie></a> the result better fits expectations:</p> <pre> Started POST "/ajax" for localhost at 2012-07-17 01:15:45 -0700 Processing by AjaxController#post as */* Parameters: {"data"={"password"="[FILTERED]", "email"="ejb"}, "me&#x2026; Completed 200 OK in 6ms (Views: 4.8ms | ActiveRecord: 0.0ms) </pre> <p style="color: #999;margin-top:3em;" class="footnote" id="fn1"><a href="#fnr1"><sup>1</sup></a> Requests were captured by pointing an app at <a href="http://en.wikipedia.org/wiki/Netcat">nc -l</a></p> <p>In the midst of doing something quazi-irrational, I stumbled over the need to create and send <span class="caps">JSON</span> requests to a web-server in an android context. Software should be oriented towards the inevitable dominance of a better future, and thus I built the mechanics of this new toy to be dependent on <a href="http://developer.android.com/reference/java/net/HttpURLConnection.html">HttpURLConnection</a>, as advised in the Android developer <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">blog</a>:</p>