<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Coert Vonk</title>
	<atom:link href="http://www.coertvonk.com/feed" rel="self" type="application/rss+xml" />
	<link>http://www.coertvonk.com</link>
	<description>Open-Source Software Engineer</description>
	<lastBuildDate>Tue, 14 May 2013 17:19:13 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Camcorder Sound, reducing noise and controlling loudness</title>
		<link>http://www.coertvonk.com/technology/videoediting/dynamic-range-compression-in-ac3-audio-6325</link>
		<comments>http://www.coertvonk.com/technology/videoediting/dynamic-range-compression-in-ac3-audio-6325#comments</comments>
		<pubDate>Sat, 02 Mar 2013 04:35:11 +0000</pubDate>
		<dc:creator>Coert</dc:creator>
				<category><![CDATA[Video Editing]]></category>

		<guid isPermaLink="false">http://www.coertvonk.com/?p=6325</guid>
		<description><![CDATA[<div><img width="150" height="150" src="http://www.coertvonk.com/wp-content/uploads/videoediting-sound-150x150.png" class="attachment-post-thumbnail wp-post-image" alt="videoediting-sound" /></div><p>Over the past years, camcorders have excelled in capturing video, but the quality of the audio remains lagging.  Adding an external microphone is a must, but will only get you so far.  Quiet voices will barely rise above the noise floor, while it feels like the videographer yelling in your ear.</p><p>This article describes a three stroke approach to improve sound from camcorders.  The first step is to reduce the noise.  In the following steps the dialog loudness is set to a standard level and the dynamic range is reduced.  The last two steps are an integral part of AC-3 (A/52, Dolby Digital) but can also be applied to other streams such as Advanced Audio Codec (AAC) as shown in the last section.</p><h3><span style="font-size: 13px;">Noise reduction</span></h3><p>First things first.  Start with a good external microphone and a wind muff.  Personally, I use a Canon 5.1 microphone because it is small and mounts on the hot shoe.  The <a href="http://kbsupport.cusa.canon.com/system/selfservice.controller?CONFIGURATION=1011&amp;PARTITION_ID=1&amp;secureFlag=false&amp;TIMEZONE_OFFSET=&amp;CMD=VIEW_ARTICLE&amp;ARTICLE_ID=34983">specs</a> are not that impressive, but even an ideal microphone will pick up a significant amount of ambient noise.</p><p>The <em>noise level</em> is defined as the loudness perceived by the human ear.  The loudness is commonly measured using a frequency filter that mimics the human hearing and then measuring the energy as root-mean-square (LAeq).  Note that for a sine wave the RMS level is <em>√2 × peak level</em>.  Another popular measure is the K-scale for which there are several plugins such as <a href="http://code.mzuther.de/kmeter/">mzuther</a>'s, <a href="http://www.bluecataudio.com/Products/Product_DPeakMeterPro/">DPMP</a>, and <a href="http://www.meterplugs.com/kmeter">meterplugs</a>.</p><p>Personally, I take a shortcut by not applying the filter and simply measuring the RMS level of noise samples.  For this, I use the <em>stats</em> function from <a href="http://sox.sourceforge.net/">Sound Exchange</a>.  In practice this appears to be good enough.  My typical <em>indoor</em> measurements are shown in the table below.  The values in the table are expressed at decibels below digital full-scale.</p><table border="1"><tbody><tr><th colspan="2">source material</th></tr><tr><td>noise</td><td>-43 dBFS</td></tr><tr><td>quiet dialog</td><td>-41 dBFS</td></tr><tr><td>normal dialog</td><td>-31 dBFS</td></tr><tr><td>loud dialog</td><td>-21 dBFS</td></tr></tbody></table><p>With the quiet dialog level this close to the noise floor, we can't amplify this dialog without also significantly amplifying the noise.  As a first step we lower the noise floor in post using an audio editor such as Adobe Sound Booth.  This usually reduce the noise by about 8 dB without causing significant distortion.</p><table border="1"><tbody><tr><th colspan="2">reduced noise</th></tr><tr><td><i>noise</i></td><td><i>-51 dBFS</i></td></tr><tr><td>quiet dialog</td><td>-41 dBFS</td></tr><tr><td>normal dialog</td><td>-31 dBFS</td></tr><tr><td>loud dialog</td><td>-21 dBFS</td></tr></tbody></table><h3>Dialog Normalization</h3><p>The volume dial on AC-3 decoders controls the loudness of a normal dialog.  The listener is thus able to reliably set the volume level of the dialogue no matter what program is playing.  This does however require the audio to indicate the normal dialog level at which it is recorded.  In AC-3 this is accomplished using the metadata tag "dialnorm" as described in the <a href="http://www.atsc.org/cms/standards/a_52-2010.pdf">AC-3 specification</a> §5.4.2.8 and §7.6.  The decoder uses this parameter to automatically adjust the volume so that the dialog is always played at the same loudness.</p><p><em>Dialog loudness</em> expresses how an average person perceives the volume of a dialog [<a href="http://web.archive.org/web/20040716131627/http://www.dolby.com/tech/L.mn.0002.DDPEG1.pdf">DD1</a>; <a href="http://web.archive.org/web/20031206104650/http://dolby.com/pro/digaudio/pa.ma.1102.Standards.S.pdf">DD2</a>].  The film industry has long standardized the normal dialog level at -31 dBFS.  The corresponding Sound Pressure Level (SPL) for most movie theaters is 85 dB.</p><p>At home we have a volume dial that selects the SPL for normal dialog.  Assuming the volume dial is set to a sound pressure level of 67 dB for normal dialog.  When this decoder plays a stream with a normal dialog level of -31 dBFS, it will adjust the amplifier gain so that <em>0 dBFS ≡ 98 dB</em>, what causes the normal dialog to reproduce at <em>-31 dBFS ≡ 67 dB</em>.  If the listener switches to another program with a normal dialog at -25 dBFS, the amplifier gain will be reduced so that <em>0 dBFS ≡ 92 dB</em>, and the normal dialog stays at a 67 dB.</p><h3>Dynamic Range Compression</h3><p>The sound from camcorders often has an undesirable large dynamic range.  On one end, there may be people whispering in the distance, while on the other end we may have the videographer holding the camcorder.  The difference between these loudness levels in called <em>dynamic range</em>.  We can reduce the dynamic range by both amplifying the quiet sounds and attenuating the loud sounds.  Note that to successfully boost the quiet sounds, it is essential that they are well above the noise floor.</p><p>With AC-3 we can adjust the gain using the metadata tag "dynrng" as described in §7.7 of the <a href="http://www.atsc.org/cms/standards/a_52-2010.pdf">AC-3 specification</a>.   The AC-3 encoder generates these tags based on the loudness combined with a compression profile.  All standard profiles have a null-band that is centered around the normal dialog level.  Loudness levels within this null-band are left intact.  For the <em>film compression profile</em> at a <em>normal dialog level of -31 dBFS</em>, the transfer function can be visualized as shown below.</p><p><a href="http://www.coertvonk.com/technology/videoediting/dynamic-range-compression-in-ac3-audio-6325/attachment/film5" rel="attachment wp-att-6411"><img class="aligncenter size-full wp-image-6411" alt="film5" src="http://www.coertvonk.com/wp-content/uploads/film5.png" width="471" height="299" /></a></p><p>As shown in the graph above, signals from -33.5 to -28.5 dBFS stay the same.  The 12 dB below is boosted, while the 10 dB above is attenuated as also shown in the table below.</p><p><a href="http://www.coertvonk.com/technology/videoediting/dynamic-range-compression-in-ac3-audio-6325/attachment/filmtbl3" rel="attachment wp-att-6366"><img class="aligncenter size-full wp-image-6366" alt="filmtbl3" src="http://www.coertvonk.com/wp-content/uploads/filmtbl3.png" width="207" height="141" /></a></p><p>This <em>film </em>at<em> dialnorm -31dBFS</em> profile is a good fit for my camcorder recordings.  The quiet dialog is more or less in the middle of the boost range, the normal dialog is at the normal dialog level, while the loud dialog is in the early cut range.</p><table border="1"><tbody><tr><th> </th><th>source material</th><th>noise reduced</th><th>range compressed</th></tr><tr><td>noise</td><td>-43 dBFS</td><td>-51 dBFS</td><td>-45 dBFS</td></tr><tr><td>quiet dialog</td><td>-41 dBFS</td><td>-41 dBFS</td><td>-37 dBFS</td></tr><tr><td>normal dialog</td><td>-31 dBFS</td><td>-31 dBFS</td><td>-31 dBFS</td></tr><tr><td>loud dialog</td><td>-21 dBFS</td><td>-21 dBFS</td><td>-25 dBFS</td></tr></tbody></table><p>The table above shows that the soft dialog is amplified by 4 dB, but at the cost of raising the noise level 2 dB.  If we had a constant background noise level, we could consider alter the transfer function so that it attenuate all signals below -45.5 dBFS.</p><h3>Let's do it</h3><p>As shown above, applying dialog normalization and dynamic range is straightforward using the metadata in AC-3.  For other audio streams, we will need to alter the samples to get the same effect.</p><h4>AC-3</h4><p>For AC-3, we only need to extract the audio stream using <a href="http://www.ffmpeg.org/">FFmpeg</a> and compress it using <a href="http://aften.sourceforge.net/">Aften</a>.</p><pre>ffmpeg -y -vn -i in.avi out.wav
aften -v 0 -dnorm 31 -dynrng 1 out.wav out.ac3</pre><h4>AAC</h4><p>The Advanced Audio Codec (AAC) doesn't support the metadata for dialog normalization or dynamic range compression.  Instead, we modify the samples directly using <a href="http://sox.sourceforge.net/">SoX</a> as shown below.  Note that in this particular example it also applies a 13 dB overall gain.  The values printed in bold represent the compression curve.  The resulting stream is then compressed using Nero's <a href="http://www.nero.com/enu/company/about-nero/nero-aac-codec.php">AAC encoder</a>.</p><pre style="padding-left: 30px;">ffmpeg -y -vn -i <em>in.avi</em> <em>tmp.wav</em>
set CURVE=<em><strong>-90.0,-84.0,-45.5,-39.5,-33.5,-33.5,-28.5,-28.5,-18.5,-23.5,0.0,-22.6
</strong></em>sox <em>tmp.wav</em> <em>out.wav</em> compand 0.1,3.0 %CURVE% 13.0 -90 1.6 stats
neroaacenc -lc -br 226000 -if <em>out.wav</em> -of <em>out.aac</em></pre><p>Those who like to experiment themselves find the transfer curves for other profiles at various dialog levels.</p><ul><li>film light<pre>-31:   -90.0,-84.0, -53.0,-47.0, -41.0,-41.0, -21.0,-21.0, -11.0,-16.0, 0.0,-15.5
-28.5: -90.0,-84.0, -50.5,-44.5, -38.5,-38.5, -18.5,-18.5,  -8.5,-13.5, 0.0,-13.1
-27:   -90.0,-84.0, -49.0,-43.0, -37.0,-37.0, -17.0,-17.0,  -7.0,-12.0, 0.0,-11.7</pre></li><li>film<pre>-31:   -90.0,-84.0, -45.5,-39.5, -33.5,-33.5, -28.5,-28.5, -18.5,-23.5, 0.0,-22.6
-28.5: -90.0,-84.0, -43.0,-37.0, -31.0,-31.0, -26.0,-26.0, -16.0,-21.0, 0.0,-20.2
-27:   -90.0,-84.0, -41.5,-35.5, -29.5,-29.5, -24.5,-24.5, -14.5,-19.5, 0.0,-18.8</pre></li><li>speech<pre>-31:   -90.0,-74.8, -52.5,-37.3, -33.5,-33.5, -28.5,-28.5, -18.5,-23.5, 0.0,-22.6
-28.5: -90.0,-74.8, -50.0,-34.8, -31.0,-31.0, -26.0,-26.0, -16.0,-21.0, 0.0,-20.2
-27:   -90.0,-74.8, -48.5,-33.3, -29.5,-29.5, -24.5,-24.5, -14.5,-19.5, 0.0,-18.8</pre></li><li>music light<pre>-31:   -90.0,-78.0, -65.0,-53.0, -41.0,-41.0, -21.0,-21.0, -21.0,-21.0, 0.0,-20.0
-28.5: -90.0,-78.0, -62.5,-50.5, -38.5,-38.5, -18.5,-18.5, -18.5,-18.5, 0.0,-17.6
-27:   -90.0,-78.0, -61.0,-49.0, -37.0,-37.0, -17.0,-17.0, -17.0,-17.0, 0.0,-16.2</pre></li><li>music<pre>-31:   -90.0,-78.0, -57.5,-45.5, -33.5,-33.5, -28.5,-28.5, -18.5,-23.5, 0.0,-22.6
-28.5: -90.0,-78.0, -55.0,-43.0, -31.0,-31.0, -26.0,-26.0, -16.0,-21.0, 0.0,-20.2
-27:   -90.0,-78.0, -53.5,-41.5, -29.5,-29.5, -24.5,-24.5, -14.5,-19.5, 0.0,-18.8</pre></li></ul><h3>For more information</h3><ul><li><a href="http://forum.doom9.org/showthread.php?t=56020">Properly encoding AC-3</a></li><li><a href="http://catalogs.infocommiq.com/AVCat/images/documents/pdfs/MeasDialogLAeq.pdf">Measuring LAeq</a></li><li><a href="http://forum.blu-ray.com/showthread.php?t=38765">Callibrate SPL</a></li></ul>]]></description>
		<wfw:commentRss>http://www.coertvonk.com/technology/videoediting/dynamic-range-compression-in-ac3-audio-6325/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<enclosure url="http://www.coertvonk.com/wp-content/uploads/videoediting-sound.png" length="54801" type="image/jpg" />
<media:content xmlns:media="http://search.yahoo.com/mrss/" url="http://www.coertvonk.com/wp-content/uploads/videoediting-sound.png" width="300" height="300" medium="image" type="image/jpeg">
<media:copyright>Coert Vonk</media:copyright>
</media:content>
	</item>
		<item>
		<title>Lego Mindstorms Graphical Programming (NXT-G 2.0)</title>
		<link>http://www.coertvonk.com/family/school/lego-mindstorms-nxt-g-6107</link>
		<comments>http://www.coertvonk.com/family/school/lego-mindstorms-nxt-g-6107#comments</comments>
		<pubDate>Wed, 12 Dec 2012 20:12:30 +0000</pubDate>
		<dc:creator>Coert</dc:creator>
				<category><![CDATA[School]]></category>

		<guid isPermaLink="false">http://www.coertvonk.com/?p=6107</guid>
		<description><![CDATA[<div><img width="150" height="150" src="http://www.coertvonk.com/wp-content/uploads/school-lego-150x150.png" class="attachment-post-thumbnail wp-post-image" alt="school-lego" /></div><p><a href="http://www.coertvonk.com/family/school/notes-on-lego-mindstorms-nxt-6107/attachment/nxt" rel="attachment wp-att-6140"><img class="alignright  wp-image-6140" title="nxt" alt="" src="http://www.coertvonk.com/wp-content/uploads/nxt.jpg" width="150" height="121" /></a>The NXT-G graphical integrated development environment (IDE) provides the five basic elements of programming: input/output, conditionals, loops, variables and functions.  It combines research ideas from MIT, with a graphical IDE from National Instruments.</p><p>The graphical IDE reduces the initial learning curve.  Novices can start programming by combining Action blocks to make the motors move and generate light or sound.  Once these concepts they can introduce flow elements such as conditionals, loops and wait.  These flow elements can used embedded sensor readings.  More advanced programmers can read the sensors directly and process the outputs using math and logic functions.</p><p>Coming from a more traditional text based programming environment, and trying stay a step ahead of my children, I read Terry Griffin's excellent book [1] along with some other resources [2,3,4,5,6,7,8].  This is a write up for my future reference.</p><h2>Work Flow</h2><p>To create a program, you connect blocks.</p><ul><li>Drag and drop blocks from the palette onto the work space.  Each block performs an unique function such as turning the motors, or measuring a distance.</li><li>Use the tabs on the bottom of the palette to switch between sets of blocks.</li><li>To save your work as a package use Tools &gt; Create Pack and Go.</li><li>As always, keep it simple.  Divide up the problem in small steps, and test each step before combining them.</li></ul><p>To compile, download to the NXT robot and run, you use the controls in the bottom-right of the work space.<a href="http://www.coertvonk.com/family/school/notes-on-lego-mindstorms-nxt-6107/attachment/nxt-control" rel="attachment wp-att-6129"><img class="alignright  wp-image-6129" title="nxt-control" alt="" src="http://www.coertvonk.com/wp-content/uploads/nxt-control.png" width="76" height="77" /></a></p><ul><li><em>middle-button</em>, compiles the program, downloads and runs it to  the NXT</li><li><em>top-right button</em>, compiles selected blocks, downloads and runs it to  the NXT</li><li><em>bottom-left button</em>, compiles the program and downloads it to  the NXT</li><li><em>bottom-right button</em>, stops the program on the NXT.</li><li><em>top-left button</em>, manages the NXT memory space, click the top-left button; click on the bar graph on the left to select a memory.  This will also let you transfer files.</li></ul><div>Helpful</div><div><ul><li>Bluetooth dongle, such as the <a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16833340012">AZiO BTD-V201</a> (don't install the drivers from CD).  To configure the connection use the top-left button on the NXT controls shown above.</li><li>Gyro Sensor, such as the <a href="http://www.hitechnic.com/cgi-bin/commerce.cgi?preadd=action&amp;key=NGY1044">HiTechnic par</a>t to build a <a href="http://robotsquare.com/2012/03/13/tutorial-segway-with-nxt-g/">Segway</a>.</li><li>To change the default project directory: change settings.ini located in  "shell:UsersFilesFolder\Documents\LEGO Creations\MINDSTORMS Projects\Profiles\Default".  For example:<ul><li>Data Directory="//FILESERVER/Your Name/Lego Mindstorms/Default"</li></ul></li><li>Organizer to store the set, such as DeWalt Deep Pro Organizer.</li><li>Rechargeable batteries, max voltage is 1.75 V for each of the six AA batteries.  NiMH appears to be a good fit.</li></ul></div><h2>I/O blocks (equiv. to library functions in C)</h2><p><img class="alignright  wp-image-6184" title="block" alt="" src="http://www.coertvonk.com/wp-content/uploads/block.png" width="99" height="67" /></p><p>A program is composed by connecting blocks on a sequence beam.  Blocks are executed sequentially.</p><p><strong>Output</strong></p><p>Outputs functions are called "Action blocks" in NXT-G jargon.  The Motor block controls a <em>single</em> motor that for example moves a robot arm, or rotate a wheel.  The Move block, on the other hand, drives <em>two motors</em>, such as to rotate the wheels on a robot to make it go forward.  The Move block synchronizes the motors to keep the robot travelling in a straight line.  In all cases, you specify how far the motor turns, not how far an arm moves or a wheel travels.  For a wheel, the distance traveled depends on the number of motor rotations, optional gears and the circumference of the wheel (14 cm for the snap-on tires).</p><p>Other output blocks generate sound, light or write to the display or Bluetooth device.</p><ul><li>Motor action<ul><li><span style="text-decoration: underline;" data-mce-mark="1">Motor block</span><ul><li>Controls a single motor</li><li>Automatically corrects for rotation errors.</li><li>Parameters:<ul><li><em><em>action</em></em>, constant or ramp up/down until target is met.</li><li><em>power</em>, &lt;10 will not move; &gt;75 moves out of control.</li><li><em>control</em>, automatically adjust the power to correct for resistance or slipping.</li><li><em>duration</em>, unlimited = switches the motor on and continues with the next block on the Sequence beam.</li><li><em>wait</em>, when unchecked, it will move on to the next block on the Sequence beam while the motor meanwhile completes its action.</li></ul></li></ul></li><li><span style="text-decoration: underline;" data-mce-mark="1">Move block</span><ul><li>Controls two motors, synchronizing the B and C motors</li><li>Automatically corrects for rotation errors.</li><li>Parameters (also see the Motor block):<ul><li><em>steering</em>, middle = straight; far left/right = spin in place (motors turn opposite directions).</li><li><em>next action</em>, brake = provides accurate travel distance and then hold the motor in place; coast = stop the power to the motor so it rolls to a stop (Because the motor coasts to a stop, it will move a little further than the Duration setting. When a following Move or Motor block runs, it will automatically adjust for the rotation error.)</li></ul></li></ul></li><li><span style="text-decoration: underline;" data-mce-mark="1">Reset</span><ul><li>Resets the accumulated rotation error, causing the next Motor or Move block to disregard prior rotation errors.  The Reset block should precede the first Motor or Move block in a program.</li></ul></li></ul></li><li>Other action blocks<ul><li><span style="text-decoration: underline;" data-mce-mark="1">Sound</span><ul><li>Plays a sound file or a single tone</li><li>Parameters:<ul><li><em>wait</em>, when unchecked, the next block on the Sequence beam will start while the sound is playing.</li></ul></li></ul></li><li><span style="text-decoration: underline;" data-mce-mark="1">Display</span><ul><li>Writes a text string or shapes to the NXT display</li></ul></li><li><span style="text-decoration: underline;" data-mce-mark="1">Send message</span><ul><li>Transmits a wireless message to another NXT assuming it has been paired before.  Each NXT has 10 mailboxes each 5 messages deep.  Head-drop when mailbox is full.</li></ul></li><li><span style="text-decoration: underline;" data-mce-mark="1">Color lamp</span><ul><li>Turns a color lamp on or off.</li></ul></li></ul></li></ul><p><strong>Input</strong></p><p><a href="http://www.coertvonk.com/family/school/lego-mindstorms-nxt-g-6107/attachment/ultrasonic" rel="attachment wp-att-6215"><img class="alignright  wp-image-6215" alt="ultrasonic" src="http://www.coertvonk.com/wp-content/uploads/ultrasonic.png" width="79" height="86" /></a>Most input block read data from external sources and compare the data read to a preset value or range.  The results are made available at its data hub.  The data hub can be shown by clicking on the tab at the bottom of the block.  Data wires connect the outputs to other blocks.  Configuration parameters can also be set by incoming wires.</p><ul><li>Sensor blocks<ul><li><span style="text-decoration: underline;" data-mce-mark="1">Ultrasonic Sensor block</span><ul><li>Measures the distance to an object and compares it to a criterion.</li><li>Outputs:<ul><li><em>yes/no</em>, true if criterion is met, false otherwise</li><li><em>distance</em>, scaled value from sensor [0..255 cm | 0..100 inches].</li></ul></li></ul></li><li><span style="text-decoration: underline;" data-mce-mark="1">Touch Sensor block</span><ul><li>Reads the touch sensor's state and compares it to a criterion (pressed, released, bumped). Note that a program may not be fast enough to detect the "bumped" state.</li><li>Outputs:<ul><li><em>yes/no</em>, true if criterion is met, false otherwise</li><li><em>raw value</em>, unscaled value from sensor [0..1024]</li><li><em>logic number</em>, 0=released; 1=pressed.</li></ul></li></ul></li><li><span style="text-decoration: underline;" data-mce-mark="1">NXT Buttons block</span><ul><li>Reads a NXT button state and compares it to a criterion (pressed, released, bumped). Note that your program may not be fast enough to detect a condition as "bumped".</li><li>Output:<ul><li><em>yes/no</em>, true if criterion is met, false otherwise.</li></ul></li></ul></li><li><span style="text-decoration: underline;" data-mce-mark="1">Color Sensor block</span><ul><li>Measures color or light intensity and compares it to a criterion.  When the parameter "light" is checked it generates its own light and measure the reflected light.</li><li>Outputs:<ul><li><em>yes/no</em>, true if criterion is met, false otherwise</li><li><em>detected color</em>, light intensity [0..100] or detected color (1=black; 2=blue; 3=green; 4=yellow; 5=red; 6=white).</li></ul></li></ul></li><li><span style="text-decoration: underline;" data-mce-mark="1">Rotation sensor block</span><ul><li>Measures the number of degrees that the motor turned and compares it to a criterion.  The same block can also be used to reset the rotation counter.</li><li>Output:<ul><li><em>yes/no</em>, true if criterion is met, false otherwise</li><li><em>direction</em>, true=forwards; false=backwards</li><li><em>degrees</em>, scaled value from sensor [0..2147483647].</li></ul></li></ul></li></ul></li><li>Other blocks<ul><li><span style="text-decoration: underline;" data-mce-mark="1">Timer block</span><ul><li>Reads one of the tree timers and compares it against a criterion.  Time is specified in seconds on the configuration panel, but in milliseconds when using input data wires.  The block can also be used to reset a timer.</li><li>Output:<ul><li><em>yes/no</em>, true if criterion is met, false otherwise</li></ul></li></ul></li><li><span style="text-decoration: underline;" data-mce-mark="1">Receive Message block</span><ul><li>Receives a Bluetooth message and compare it against a criterion.</li><li>Outputs:<ul><li><em><em>yes/no</em></em>, true if criterion is met, false otherwise</li><li><em>message received</em>, true when a message has been received, false otherwise</li><li><em>{text|number|logic} out</em>, message data.</li></ul></li></ul></li><li><span style="text-decoration: underline;" data-mce-mark="1">Random block</span><ul><li>Generates a random number within a range.  Can be used to make the robot a little unpredictable and thus more interesting.</li><li>Output:<ul><li><em>number</em>, random value between specified lower and upper bounds.</li></ul></li></ul></li></ul></li></ul><p><strong>Data manipulation</strong></p><p><a href="http://www.coertvonk.com/family/school/lego-mindstorms-nxt-g-6107/attachment/math" rel="attachment wp-att-6195"><img class="alignright  wp-image-6195" title="math" alt="" src="http://www.coertvonk.com/wp-content/uploads/math.png" width="83" height="117" /></a>Sophisticated data manipulations are supported through combining several number and text blocks.</p><ul><li>Numbers<ul><li><span style="text-decoration: underline;" data-mce-mark="1">Math Block</span><ul><li>Performs basic math operations (addition, subtraction, multiplication, division, square root, absolute value).</li><li>Output:<ul><li><em>result</em>, result of the operation [-2147483648 .. 2147483647]</li></ul></li></ul></li><li><span style="text-decoration: underline;" data-mce-mark="1">Logic Block</span><ul><li>Performs Boolean operations (AND, OR, XOR or NOT)</li><li>Output<ul><li><em>result</em>, result of the operation [true|false]</li></ul></li></ul></li><li><span style="text-decoration: underline;" data-mce-mark="1">Compare Block</span><ul><li>Performs less than (&lt;), greater than (&gt;) or equal (=) operations</li><li>Output<ul><li><em>result</em>, result of the operation [true|false]</li></ul></li></ul></li><li><span style="text-decoration: underline;" data-mce-mark="1">Range Block</span><ul><li>Determines if a value is within a range of numbers</li><li>Output<ul><li><em>yes/no</em>, true of the value is within range, false otherwise</li></ul></li></ul></li></ul></li><li>Text strings<ul><li><span style="text-decoration: underline;" data-mce-mark="1">Number to Text block</span><ul><li>Converts a number to a text string</li><li>Output<ul><li><em>text</em>, text representation of number [string]</li></ul></li></ul></li><li><span style="text-decoration: underline;" data-mce-mark="1">Text block</span><ul><li>Concatenates a maximum of three text strings</li><li>Output<ul><li><em>text</em>, concatenation of text strings [string]</li></ul></li></ul></li></ul></li></ul><h2>Program Flow</h2><p><a href="http://www.coertvonk.com/family/school/lego-mindstorms-nxt-g-6107/attachment/switch" rel="attachment wp-att-6188"><img class="alignright  wp-image-6188" title="switch" alt="" src="http://www.coertvonk.com/wp-content/uploads/switch.png" width="97" height="103" /></a>Flow elements can take input from an embedded sensor or from a data wire.</p><ul><li>Conditionals<ul><li><span style="text-decoration: underline;" data-mce-mark="1">Switch block</span> (equiv. to switch())<ul><li>Checks for a condition, and runs blocks on the sequence beam corresponding to that condition.</li><li>More then two conditions are allowed.</li><li>The '*' button selects the default condition.</li><li>Floating point inputs are rounded to the nearest integer before comparing them.</li><li>Comments should be left outside a switch block.</li></ul></li></ul></li><li>Wait<ul><li><span style="text-decoration: underline;" data-mce-mark="1">Wait block</span><ul><li>Busy-loop to poll an input until the specified condition is met.</li></ul></li></ul></li><li>Loops<ul><li><span style="text-decoration: underline;" data-mce-mark="1">Loop block</span> (equiv. to do while())<ul><li>Repeats a set of blocks until the end condition is met.</li><li>The loop count output is updated at the start of the last run through the loop, it will be one fewer than the total number of times the loop repeats.</li></ul></li></ul></li></ul><h2><strong>My blocks (equiv. to user functions)</strong></h2><p>My blocks should be used to abstract program sections that perform specific functions.  Dividing a program into smaller pieces, makes the program easier to read and maintain.  Each My block can be tested independently and reused in the same or other programs.</p><ul><li>Usage<ul><li><em>Create</em>, select the blocks; "Edit &gt; Make a new My Block" from the menu</li><li><em>Open</em>, double-click the My Block</li><li><em>Use</em>, select from the Custom Palette (using the tab at the bottom of the Palettes)</li><li><em>Close</em>, "File &gt; Close" from the menu</li><li><em>Organize</em>, "Edit &gt; Manage Custom Palette" from the menu; then use the file system to organize.</li></ul></li><li>Creating My blocks that have a data hub<ul><li>Use compare, text or math blocks to supply input values to the blocks that will become a new My block.  These additional blocks are only needed to supply the data wire, and will not become part of the My block.</li><li>Select the blocks for the new My Block and call "Edit &gt; Make a new My Block" from the menu.  All the data wires will remain connected. The value of the wire will also become configurable using the Configuration Panel.</li><li>Note that once a My block is made, you can change the name of data plugs, but you can not add more plugs.  You will have to recreate the My block instead.</li></ul></li><li>Appears broken if<ul><li>two data plugs have the same name, or</li><li>there is problem with the data wire connections, or</li><li>the source file for the block has been moved or renamed in the computer's file system.</li></ul></li><li>Note<ul><li>If you absolutely have to copy a My block, then use the file system.  Don't use "save as" from the menu.</li><li>When moving a program to another computer, also move the My Blocks or better yet create a package that contains all the related files ("Tools &gt; Create Pack and Go")</li></ul></li></ul><h2>Data</h2><p><a href="http://www.coertvonk.com/family/school/lego-mindstorms-nxt-g-6107/attachment/data" rel="attachment wp-att-6225"><img class="alignright  wp-image-6225" alt="data" src="http://www.coertvonk.com/wp-content/uploads/data.png" width="79" height="79" /></a>Most blocks have input plugs that correspond to the parameters in its configuration panel.  Using the data inputs, a program can change these parameters.  For example, the output of an ultrasound sensor could be used to specify the power of the motors, thereby slowing down the robot when it approaches an object.</p><p><strong>Data wires (equiv. to mailboxes)</strong></p><p>In the NXT-G world, data passes over so called "Data wires".  A Data wire connects <em>one output</em> to one or more inputs.</p><ul><li>Scope<ul><li>Local to the blocks that it connects to the wire.</li></ul></li><li>Usage<ul><li><em>draw a wire between blocks</em><ul><li>expand the data hubs (click on the tab at the bottom of a block).</li><li>the plugs on the left are inputs; the plugs on the right are outputs.</li><li>click on an output terminal</li><li>click on the input terminal that you want to connect.</li></ul></li><li><em>draw a wire into the boundary of a Switch block</em><ul><li>enable tabbed view (disable flat view)</li><li>connect a wire to the input</li><li>switch back to flat view</li></ul></li></ul><ul><li><em>draw wires from within the boundary of a Switch block</em><ul><li>enable tabbed view</li><li>select the "true" condition and connect a wire</li><li>select the "false" condition and connect a wire from the output to the edge of the block where the existing wire crosses it.</li><li>switch back to flat view</li></ul></li></ul><ul><li><em>delete a wire</em><ul><li>click the data plug at the right of the wire.</li></ul></li></ul></li><li>Note<ul><li>Use variables instead of passing data wires in/out of a Loop or Switch block.</li><li>Occasionally, a wire may be routed behind another block, making it appear as if its terminals are connected.</li><li>A dashed grey wire indicates a problem, such as<ul><li>two plugs have different data types (Boolean, integer, float, string)</li><li>the output of a pass-through plug is not used without the input side connected</li><li>multiple inputs are connected to one output plug.</li><li>an input is connected to an output that appears later on the sequence beam.</li></ul></li></ul></li></ul><p><strong>Variable block (equiv. to variables)</strong></p><p>Variables are expected to change over time, such as a distance to a wall.  A variable can be used to connect <em>one or more outputs</em> to one or more inputs.</p><ul><li>Scope<ul><li>Local to the program (and its My blocks) that defines it.</li></ul></li><li>Usage<ul><li><em>create a variable</em>, "Edit &gt; Define Variables" from the menu.</li><li><em>use a variable</em>, insert a Variable block.</li><li><em>delete a variable</em>, first remove any Variable blocks that use it.</li></ul></li><li>Notes<ul><li>A program shares its variables with its My blocks if they have the same name and data type.</li><li>Perhaps not the best coding practice, but variables can be used when a My Block needs to remember a value.</li></ul></li></ul><p><strong>Constant block (equiv. to const or #defines)</strong></p><p>As the name implies, constant values do not change.  An example is the diameter of the wheels on a robot.  A constant block supplies a <em>constant value</em> to more or one inputs.</p><ul><li>Scope<ul><li>Global to all programs.</li></ul></li><li>Usage<ul><li><em>create</em>, "Edit &gt; Define Constants" from the menu.  Specify the action "choose from list".</li><li><em>use</em>, insert a Constant block.</li><li><em>change</em>, save any open programs that use that constant.</li><li><em>delete</em>, "Edit &gt; Define constants" from the menu.  Note that any Constant block that uses that constant will change to Custom.</li></ul></li><li>Note<ul><li>When working with a program that uses <em>custom constants</em>, note that:<ul><li>changing the value in one Constant block won’t affect the other programs.</li><li>creating a constant using the Edit Constant dialog will change all "Custom" constants with the same name.</li></ul></li></ul></li></ul><p><strong>File Access block</strong></p><p>Files can store settings or input/output data for a program.</p><ul><li>Scope<ul><li>Global to all programs running on a NXT.  Remain available after the program ends.</li></ul></li><li>Usage<ul><li><em>create</em>, insert a File Access block; select create as the action.  A list of files already on the NXT will appear (assuming it is connected using either USB or BT).</li><li><em>write</em>, insert a File Access block; select write as the action to appends to a file.</li><li><em>read</em>, insert a File Access block; select read as the action.</li><li><em>delete</em>, insert a File Access block; select delete as the action.</li><li><em>close</em>, insert a File Access block; select close.  Remember to close a file after writing to it.  Otherwise you can not delete or read from it.</li></ul></li><li>Note<ul><li>A program can write to or read from up to four files at once.</li><li>The Initial File Size data plug that allows you to specify how much memory to allocate for the file. If the file grows past the initial size, the NXT will move the file to larger memory space, thereby introducing a slight delay.</li></ul></li></ul><div><h2>Sequence Beams (=threads).</h2><p><a href="http://www.coertvonk.com/family/school/lego-mindstorms-nxt-g-6107/attachment/sequencebeam" rel="attachment wp-att-6185"><img class="alignright  wp-image-6185" title="sequencebeam" alt="" src="http://www.coertvonk.com/wp-content/uploads/sequencebeam.png" width="94" height="70" /></a>Multitasking means doing more than one thing at a time. The sequence beam can fork, allowing your robot to do more than one thing at a time.  But first, a short word about execution order:</p><p><strong>Execution order</strong></p><ul><li>In general, a block will finish what it’s doing before the next block on the Sequence Beam runs.  Exceptions are when "wait for completion" is unchecked, or a Move/Motor block is set to run indefinitely.</li><li>A block starts once all input values on the data wires are available.</li><li>A Loop/Switch block starts only once all the input values are available on data wires that enter the block (even though they might not be immediately used)</li><li>A data wire that starts inside a Loop/Switch block and connects to a block outside will only have a value after the Loop/Switch block finishes.</li><li>Only one copy of a particular My Block can run at the same time (non-re-entrant)</li><li>A program ends once it reaches the end of all the Sequence beams.</li></ul><p><strong>To add a task</strong></p><ul><li>Expand vertical space:<ul><li>Add a Display block (that has a large data hub) at the end of the Loop block.</li><li>Open the data hub to create space within the loop.</li><li>Add a small comment to the bottom-left side of the Loop block to keep it open after the Display block is removed.</li><li>Delete the display block.</li></ul></li><li>Add a new Sequence beam:<ul><li>Add a new block under the existing Sequence beam.</li><li>Shift-click the existing Sequence Beam, and connect it to the new block.</li></ul></li><li>To expand horizontal space:<ul><li>Select the outer Loop block.</li><li>Click-and-hold the mouse on the Sequence Beam between the top-right block and the edge of the Loop block.  Slowly drag the mouse to the right to widen the loop block.</li></ul></li></ul><p><strong>Note</strong></p><ul><li>Especially when working with multiple Sequence beams, allow the NXT-G some time to catch up with your editing.</li><li>Do not access the same sensor or motor from different Sequence beams.</li><li>Blocks on different sequence beams can communicate using variables, not pure data wires.</li></ul><h2>Debugging</h2><p>Often debugging a program proves to be more challenging than writing it.  The NXT-G environment offers the following debug approaches:</p></div><div><ul><li><img class="alignright" title="feedback" alt="" src="http://www.coertvonk.com/wp-content/uploads/feedback.png" width="59" height="81" />Using Feedback boxes<ul><li>The Feedback Boxes, at the right side of the Configuration Panel show the value of sensors or loop variables while the NXT is connected to the computer using an USB cable or Bluetooth connection.</li></ul></li><li>Using the NXT display<ul><li><a href="http://robotsquare.com/2012/02/23/tutorial-displaying-numbers/">displaying numbers</a> (Laurens Valk)</li><li><a href="http://courses.washington.edu/engr100/Section_Wei/NXT/tricks.pdf">using the display</a></li></ul></li><li>Using Bluetooth<ul><li><a href="http://www.norgesgade14.dk/networkbtremote.php">BT remote</a> (Anders)</li><li><a href="http://www.codeproject.com/Articles/18857/Communicating-with-LEGO-NXT-via-Bluetooth-in-C">nxt sending bluetooth messages to pc</a></li><li><a href="http://mindstorms.lego.com/en-us/support/files/default.aspx">bluetooth development kit</a> (lego)</li></ul></li><li><a href="http://find.botmag.com/100701">programming and debugging options</a></li></ul><h2>References</h2><table border="0"><tbody><tr><td dir="" id="" lang="" scope="" align="" valign="top">[1]</td><td><a href="http://www.amazon.com/Art-LEGO-MINDSTORMS-NXT-G-Programming/dp/1593272189/?s=books&amp;ie=UTF8&amp;qid=1354928857">The Art of Lego Mindstorms NXT-G Programming</a> (book)<br /> Terry Griffin, 2010</td></tr><tr><td dir="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top">[2]</td><td rowspan="1" colspan="1"><a href="http://www.amazon.com/gp/product/1593272111?ie=UTF8&amp;tag=valkdiscovery-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1593272111">The Lego Mindstorms NXT 2.0 Discovery Book</a> (book)<br /> Laurens Valk, 2010</td></tr><tr><td dir="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top">[3]</td><td rowspan="1" colspan="1"><a href="http://www.nxtprograms.com/help/MyBlocks/tutorial.html">Creating and using your own blocks with My Blocks</a><br /> Dave Parker, 2007-2012</td></tr><tr><td dir="" id="" lang="" scope="" align="" valign="top">[4]</td><td><a href="http://www.nytimes.com/2008/12/02/technology/techspecial2/02robots.html">Robots in a box</a> (article)<br /> New York Times, 2008</td></tr><tr><td dir="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top">[5]</td><td rowspan="1" colspan="1"><a href="http://www.firstlegoleague.org/sites/default/files/Challenge/TeamResources/SeniorSolutions/2012Programming.pdf" target="_blank">Basic Programming: Tips, Skills, &amp; Resources</a> (presentation)<br /> Tony Ayad and LeRoy Nelson, 2012</td></tr><tr><td dir="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top">[6]</td><td rowspan="1" colspan="1"><a href="http://www.stemcentric.com/nxt-tutorial/">NXT Tutorial</a> (video)<br /> Dale Yocum at Catlin Gabel School, 2012</td></tr><tr><td dir="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top">[7]</td><td rowspan="1" colspan="1"><a href="http://www.hightechkids.org/sites/default/files/CoachingLibrary/fll_programming_101_nxt_g.pdf">FFL Programming 101</a><br /> Innovations in Science and Technology Education, 2007</td></tr><tr><td dir="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top">[8]</td><td rowspan="1" colspan="1"><a href="http://www.nxtprograms.com/projects2.html#ProjectsByProgram">Example projects by complexity</a><br /> Dave Parker, 2007-2012</td></tr><tr><td dir="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top">[9]</td><td rowspan="1" colspan="1"><a href="http://find.botmag.com/100702">Programming solution for NXT - debugging</a><br /> Robot Magazine, 2012</td></tr></tbody></table></div>]]></description>
		<wfw:commentRss>http://www.coertvonk.com/family/school/lego-mindstorms-nxt-g-6107/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<enclosure url="http://www.coertvonk.com/wp-content/uploads/school-lego.png" length="83684" type="image/jpg" />
<media:content xmlns:media="http://search.yahoo.com/mrss/" url="http://www.coertvonk.com/wp-content/uploads/school-lego.png" width="300" height="300" medium="image" type="image/jpeg">
<media:copyright>Coert Vonk</media:copyright>
</media:content>
	</item>
		<item>
		<title>DD-WRT and Wireshark</title>
		<link>http://www.coertvonk.com/technology/networking/dd-wrt-and-wireshark-5928</link>
		<comments>http://www.coertvonk.com/technology/networking/dd-wrt-and-wireshark-5928#comments</comments>
		<pubDate>Wed, 19 Sep 2012 00:05:36 +0000</pubDate>
		<dc:creator>Coert</dc:creator>
				<category><![CDATA[Networking]]></category>
		<category><![CDATA[DD-WRT]]></category>
		<category><![CDATA[etherpuppet]]></category>
		<category><![CDATA[named pipe]]></category>
		<category><![CDATA[tcpdump]]></category>
		<category><![CDATA[wireshark]]></category>

		<guid isPermaLink="false">http://www.coertvonk.com/?p=5928</guid>
		<description><![CDATA[<div><img width="150" height="150" src="http://www.coertvonk.com/wp-content/uploads/networking-ddwrt-and-wireshark-150x150.png" class="attachment-post-thumbnail wp-post-image" alt="networking-ddwrt-and-wireshark" /></div><p><a href="http://www.coertvonk.com/technology/networking/dd-wrt-and-wireshark-5928/attachment/networking-ddwrt-and-wireshark" rel="attachment wp-att-6650"><img class="alignright size-thumbnail wp-image-6650" alt="networking-ddwrt-and-wireshark" src="http://www.coertvonk.com/wp-content/uploads/networking-ddwrt-and-wireshark-150x150.png" width="150" height="150" /></a>Wireshark is a open-source protocol analyzer that can visualize the frames passing through the router. This analyzer is available on many platforms, but can not run directly on the router.</p><h4>using tcpdump</h4><p>While one could run tcpdump directly on the router, interpreting its output takes a bit of work. Another option run tcpdump on the router and pipe its output to wireshark on a Linux host. Details can be found in <a href="http://www.seangri-la.com/cgi-bin/moin.cgi/Remote_packet_capture">Remote Packet Capture</a>. An excerpt.  To capture traffic on bridge br0, use the following commands on a Linux host.</p><pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">mkfifo /tmp/$PPID
ssh rtr "tcpdump -i br0 -w - 'not ((src host rtr and src port 22) or (dst host rtr and dst port 22))'" &gt; /tmp/$PPID. &amp;
wireshark -k -i /tmp/$PPID</pre><h4>using etherpuppet</h4><p>Instead we forward all packets from an interface on the router to a Linux host, where they the protocol analyzer runs.</p><p>Prepare the router</p><pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">cd /jffs
wget http://www.secdev.org/projects/etherpuppet/files/etherpuppet-mipsel
chmod 755 etherpuppet-mipsel</pre><p>Prepare the Linux host</p><pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">wget http://hg.secdev.org/etherpuppet/raw-files/top/etherpuppet.c
gcc -o etherpuppet etherpuppet.c
sudo yum install wireshark-gnome
sudo usermod -a -G wireshark $NAME</pre><p>Instruct the router to forward all packets on the bridge that joins the LAN and wireless traffic (<em>br0</em>).</p><pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">./etherpuppet-mipsel -i br0 -s 999 -C</pre><p>Receive the packets on the Linux host and start the protocol analyzer.</p><pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">sudo ./etherpuppet -m -c rtr2.vonk:999 &amp;</pre><pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">sudo ifconfig puppet0 up
sudo wireshark # select interface puppet0</pre><p>In Wireshark select the<em> puppet0</em> interface.</p>]]></description>
		<wfw:commentRss>http://www.coertvonk.com/technology/networking/dd-wrt-and-wireshark-5928/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<enclosure url="http://www.coertvonk.com/wp-content/uploads/networking-ddwrt-and-wireshark.png" length="128394" type="image/jpg" />
<media:content xmlns:media="http://search.yahoo.com/mrss/" url="http://www.coertvonk.com/wp-content/uploads/networking-ddwrt-and-wireshark.png" width="300" height="300" medium="image" type="image/jpeg">
<media:copyright>Coert Vonk</media:copyright>
</media:content>
	</item>
		<item>
		<title>DD-WRT heading two seperate networks</title>
		<link>http://www.coertvonk.com/technology/networking/dd-wrt-leading-two-seperate-networks-5829</link>
		<comments>http://www.coertvonk.com/technology/networking/dd-wrt-leading-two-seperate-networks-5829#comments</comments>
		<pubDate>Thu, 13 Sep 2012 16:15:37 +0000</pubDate>
		<dc:creator>Coert</dc:creator>
				<category><![CDATA[Networking]]></category>
		<category><![CDATA[DD-WRT]]></category>
		<category><![CDATA[segregation]]></category>

		<guid isPermaLink="false">http://www.coertvonk.com/?p=5829</guid>
		<description><![CDATA[<div><img width="150" height="150" src="http://www.coertvonk.com/wp-content/uploads/networking-ddwrt-leading-two-seperate-networks-150x150.png" class="attachment-post-thumbnail wp-post-image" alt="networking-ddwrt-leading-two-seperate-networks" /></div>This article shows how you can use a $75 consumer class router to support two different networks.  Besides the usual primary network, it will create a secondary network supporting both wireless and wired connections.  The secondary network could  be used to provide internet access to customers or visitors.<a href="http://www.coertvonk.com/technology/networking/dd-wrt-leading-two-seperate-networks-5829/attachment/seperate-networks2" rel="attachment wp-att-5876"><img class="alignright size-full wp-image-5876" title="seperate-networks2" alt="" src="http://www.coertvonk.com/wp-content/uploads/seperate-networks2.png" width="235" height="261" /></a>

The router is assumed to be flashed with open source DD-Wrt firmware.  This firmware adds some business class features to your router.  The router will be configured by taking advantage of two features that allow network traffic to be separated:
<ul>
	<li><em>VLANs</em>, allows wired LAN ports to be grouped and each group to be treated differently.</li>
	<li><em>multiple SSIDs</em>, allows multiple wireless network names (SSID) and security settings.  The traffic over each SSID can be treated differently.</li>
</ul>
<span style="color: #ffffff;">:</span>
<h2>Before we start</h2>
The router is assumed to be running open source <a href="http://www.dd-wrt.com/">DD-Wrt</a> firmware and configured for a single wired and wireless network.  The router should also be configured for shell access (<a href="http://www.dd-wrt.com/wiki/index.php/SSH">ssh</a>) or telnet.  Further, the reader should have a basic understanding of
<ul>
	<li>the web based user interface (WebGUI)</li>
	<li>networking concepts such as IP addresses, sub nets, routing, bridging and network interfaces.  Some of the more specific terminology used in this article is:
<ul>
	<li>A <em>broadcast domain</em>, is a network segment, in which all nodes can communicate directly by layer-2 broadcasts.  Examples are a wired GigE network, or a wireless network.</li>
	<li>A <em>switch</em>, handles frames at the data link layer (layer 2).</li>
	<li>A <em>router</em>, handles packets at the network layer (layer 3).  A router forms a boundary between broadcast domains.</li>
	<li>A <em>bridge</em>, connects two or more network segments into a single broadcast domain (layer 2).</li>
	<li>A <em>virtual LAN</em> <em>(VLAN)</em>, creates distinct broadcast domains within one ore more physical networks.  A VLAN is a switched network that is logically segmented by functions, project teams, or applications without regard to the physical location of users.</li>
</ul>
</li>
</ul>
The configuration presented here has been tested on an <a href="http://www.anandtech.com/print/6180">Asus RT-N16</a> router running <a href="ftp://ftp.dd-wrt.com/others/eko/V24-K26/svn15943-snow/dd-wrt.v24-15943_NEWD-2_K2.6_mega.bin">DD-Wrt mega build 15943</a>.  The approach outlined might also apply to other routers or builds, albeit with minor changes.

<span style="color: #ffffff;">:</span>
<h2>Inside the router</h2>
To create a secondary network, we need to separate the four LAN ports and create an virtual wireless network.  The following section builds a basic understanding of the default data paths in the router.  The following section describes how the software configuration
<h3>Hardware block diagram</h3>
Many consumer class routers are based on a chipset consisting of a IP switch and System-on-Chip.  For example, the Asus RT-N16 router that is build around:
<ul>
	<li><em>System-on-Chip</em> <a href="http://www.broadcom.com/products/Wireless-LAN/802.11-Wireless-LAN-Solutions/BCM4718">BCM4718</a>, provides the CPU, WiFi and USB.</li>
	<li><em>Switch Fabric</em> <a href="http://www.broadcom.com/products/Switching/Home-and-Small-Business/BCM53115">BCM53115</a>, provides  the WAN and four LAN ports</li>
</ul>
Other GigE routers such as the Cisco/Linksys E2000 or E3000 are very similar.  Older routers such as the WRT54G have slightly different port numbers  (<a href="http://www.dd-wrt.com/wiki/index.php/Default_Configuration_Overview">details)</a>.

<a href="http://www.coertvonk.com/technology/networking/dd-wrt-leading-two-seperate-networks-5829/attachment/block-before3" rel="attachment wp-att-5871"><img class="aligncenter  wp-image-5871" title="block-before3" alt="" src="http://www.coertvonk.com/wp-content/uploads/block-before3.png" width="598" height="218" /></a>

The block diagram above shows the data paths within the router.  Note:
<ul>
	<li>the LAN port numbers on the case do not correspond to the port numbers on the switch;</li>
	<li>the WAN port connects to a special interface on the switch and can't be reassigned;</li>
	<li>port 8 connects the VLAN trunk from the switch to interface <em>eth0</em> on the CPU.</li>
</ul>
The switch tags incoming frames with a VLAN identifier.  Frames arriving on the WAN port are tagged as VLAN2, while frames from the LAN ports are tagged as VLAN1.  The frames destined for the CPU are sent on <em>port 8</em>.

The CPU receives the frames over port <em>eth0</em>.  Frames with a VLAN2 tag are treated as WAN traffic.  Frames with a VLAN1 tag are combined (bridged) with frames from the wireless module (<em>eth1</em>) and treated as LAN traffic.
<h3>Firmware mapping</h3>
The configuration for the DD-Wrt is stored in nonvolatile memory (nvram).  The configuration can be shown as described in the DD-Wrt document <a href="http://www.dd-wrt.com/wiki/index.php/Switched_Ports">Switched Ports</a>.  An excerpt:

The tagging configuration is stored in <em>vlan#ports</em> variables where '*' symbolizes the default path.  Note that the <em>vlan0ports</em> variable appears to be unused on GigE routers.  For the switch to move frames outside of any vlan, it needs to include port 8.  This allows the SoC to route the packet.  The vlan with the default is used for packets that do not have a vlan tag (see <a href="http://www.dd-wrt.com/wiki/index.php/Default_Configuration_Overview">here</a>).
<pre class="brush: bash; highlight: 1; gutter: false; toolbar: off; tab-size: 8">nvram show | grep vlan.*ports | sort
vlan0ports=1 2 3 4 5*
vlan1ports=4 3 2 1 8*
vlan2ports=0 8</pre>
An other important variable is <em>port5vlans</em>.  It identifies every active VLAN plus the number 16 that indicates that tagging is enabled.  The other variables appear only for the WebGUI.
<pre class="brush: bash; highlight: 1; gutter: false; toolbar: off; tab-size: 8">nvram show | grep port.*vlan | sort
port0vlans=2 18 19
port1vlans=1 18 19
port2vlans=1 18 19
port3vlans=1 18 19
port4vlans=1 18 19
port5vlans=1 2 16</pre>
Every active VLAN needs to have its name set to <em>et0</em>.
<pre class="brush: bash; highlight: 1; gutter: false; toolbar: off; tab-size: 8">nvram show | grep vlan.*hwname | sort
vlan0hwname=et0
vlan1hwname=et0
vlan2hwname=et0</pre>
<span style="color: #ffffff;">:</span>
<h2>Creating to separate networks</h2>
To create a second network, we need to introduce an additional VLAN and an additional SSID for the wireless.  The two can then be bridged together and given an unique subnet address.  Before you start, I highly recommend making a backup of your current configuration.

<a href="http://www.coertvonk.com/technology/networking/dd-wrt-leading-two-seperate-networks-5829/attachment/block-after2" rel="attachment wp-att-5872"><img class="aligncenter size-full wp-image-5872" title="block-after2" alt="" src="http://www.coertvonk.com/wp-content/uploads/block-after2.png" width="598" height="218" /></a>
<h3>Create a virtual wireless network (wl0.1)</h3>
Using a web browser, connect to the router and bring up the WebGUI.
<ol>
	<li>Wireless &gt; Virtual Interfaces &gt; Add.  Specify the basic wireless settings.  For the network configuration, choose bridged.  Click Save.</li>
	<li>Wireless &gt; Wireless Security &gt; Virtual Interface wl0.1.  Specify the security settings.  Click Apply Settings, to save and apply the changes.</li>
</ol>
<h3>Create a virtual local area network (vlan3)</h3>
We will use the shell (ssh) interface to configure the VLANs, because on Broadcom based routers the GUI does not always do so correctly.  Login using ssh, and run the following commands
<pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">nvram set vlan3hwname=et0       # VLAN3 is enabled
nvram set vlan1ports="3 4 8*"   # assign LAN1/LAN2 to VLAN1
nvram set vlan3ports="1 2 8*"   # assign LAN3/LAN4 to VLAN3
nvram set port4vlans="1 18 19"  # LAN1 is part of VLAN1 (GUI only)
nvram set port3vlans="1 18 19"  # LAN2 is part of VLAN1 (GUI only)
nvram set port2vlans="3 18 19"  # LAN3 is part of VLAN3 (GUI only)
nvram set port1vlans="3 18 19"  # LAN4 is part of VLAN3 (GUI only)
nvram commit
reboot</pre>
<h3>Bridge vlan3 and wl0.1 (br1)</h3>
To make the new wired and wireless network to behave as one, we logically combine interfaces <em>vlan3</em> and <em>wl0.1</em> using a new bridge interface <em>br1</em>:
<ol>
	<li>Bridge the <em>vlan3</em> and <em>wl0.1</em> interfaces together as <em>br1</em>
<ul>
	<li>Setup &gt; Networking &gt; Bridging &gt; Create Bridge &gt; Add.  Enter <em>br1</em> in the first field and click Apply Settings.</li>
	<li>Setup &gt; Networking &gt; Bridging &gt; Create Bridge &gt; For <em>br1</em> enter a private IP address and subnet mask.  E.g. 10.0.4.1 and 255.255.255.0.  Click Apply Settings.</li>
	<li>Setup &gt; Networking &gt; Assign to bridge &gt; Add.  Select <em>br1</em>, interface <em>vlan3</em> (LAN3 and LAN4) and click Apply Settings.</li>
	<li>Setup &gt; Networking &gt; Assign to bridge &gt; Add.  Select <em>br1</em>, interface <em>wl0.1</em> (the virtual wireless interface) and click Apply Settings.</li>
</ul>
</li>
	<li>Configure the DHCP server for <em>br1</em>
<ul>
	<li>Setup &gt; Networking &gt; DHCPD &gt; Multiple DHCP Server &gt; Add.  Select br1 and fill in the first m maximum number of DHCP addresses and lease time in minutes.  E.g. 200, 50 and 1440.  Click Apply Settings.</li>
</ul>
</li>
</ol>
<h3>Separate the networks</h3>
Now that we have the two networks up and running, it is time to separate them.  The firewall rules listed below added to Administration &gt; Commands &gt; Save Firewall.  If you use an USB memory stick, the rules can also be stored in an executable <em>/jffs/etc/config/*.wanup</em> script.  Such a script runs automatically each time the WAN link and firewall are up (see <a href="http://www.dd-wrt.com/wiki/index.php/Script_Execution" target="_blank">Script Execution</a>).

To restrict <em>br1</em> from accessing <em>br0</em> and visa versa,
<pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">iptables -I FORWARD -i br0 -o br1 -m state --state NEW -j DROP
iptables -I FORWARD -i br1 -o br0 -m state --state NEW -j DROP</pre>
Optionally, to restrict <em>br1</em> from accessing the management interface of the router.
<pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">iptables -I INPUT -i br1 -m state --state NEW -j DROP
iptables -I INPUT -i br1 -p udp --dport 67 -j ACCEPT
iptables -I INPUT -i br1 -p udp --dport 53 -j ACCEPT
iptables -I INPUT -i br1 -p tcp --dport 53 -j ACCEPT</pre>
<h3>Test</h3>
To test the interfaces, configure a space computer interface for DHCP and connect it to each of the LAN ports.  Then verify that the assigned IP address matches the subnet of the network.  Do the same with the wireless networks.]]></description>
		<wfw:commentRss>http://www.coertvonk.com/technology/networking/dd-wrt-leading-two-seperate-networks-5829/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<enclosure url="http://www.coertvonk.com/wp-content/uploads/networking-ddwrt-leading-two-seperate-networks.png" length="150751" type="image/jpg" />
<media:content xmlns:media="http://search.yahoo.com/mrss/" url="http://www.coertvonk.com/wp-content/uploads/networking-ddwrt-leading-two-seperate-networks.png" width="300" height="300" medium="image" type="image/jpeg">
<media:copyright>Coert Vonk</media:copyright>
</media:content>
	</item>
		<item>
		<title>DD-WRT and OpenVPN (without nvram footprint)</title>
		<link>http://www.coertvonk.com/technology/networking/dd-wrt-and-openvpn-5591</link>
		<comments>http://www.coertvonk.com/technology/networking/dd-wrt-and-openvpn-5591#comments</comments>
		<pubDate>Fri, 07 Sep 2012 17:12:37 +0000</pubDate>
		<dc:creator>Coert</dc:creator>
				<category><![CDATA[Networking]]></category>
		<category><![CDATA[DD-WRT]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[openvpn]]></category>
		<category><![CDATA[route]]></category>
		<category><![CDATA[tunnel]]></category>

		<guid isPermaLink="false">http://www.coertvonk.com/?p=5591</guid>
		<description><![CDATA[<div><img width="150" height="150" src="http://www.coertvonk.com/wp-content/uploads/networking-ddwrt-and-openvpn-150x150.png" class="attachment-post-thumbnail wp-post-image" alt="networking-ddwrt-and-openvpn" /></div><a href="http://www.coertvonk.com/technology/networking/dd-wrt-and-openvpn-5591/attachment/networking-ddwrt-and-openvpn" rel="attachment wp-att-6644"><img class="alignright size-thumbnail wp-image-6644" alt="networking-ddwrt-and-openvpn" src="http://www.coertvonk.com/wp-content/uploads/networking-ddwrt-and-openvpn-150x150.png" width="150" height="150" /></a>In a virtual private network (VPN) a group of two or more computer systems communicate securely over the public internet.  Security is provided by authentication and encryption.  Computers that connect through a VPN have access to private network as if they were physically connected to it.

This article focuses on the <a href="http://openvpn.net/index.php/open-source.html">OpenVPN</a> implementation as it is included in the <a href="http://www.dd-wrt.com/">DD-Wrt router firmware</a>.  Besides security, one of its prominent features is that its traffic can traverse network address translators (NAT) and firewalls.

Two examples are given that describe the typical configurations:
<ul>
	<li><em>remote access</em>, providing remote users access to a private network, and</li>
	<li><em>site-to-site</em>, connecting a remote network to a private network.</li>
</ul>
These examples have been tested on two <a href="http://www.dd-wrt.com/wiki/index.php/Asus_RT-N16">Asus RT-N16</a> routers running <a href="ftp://ftp.dd-wrt.com/others/eko/V24-K26/svn15943-snow/dd-wrt.v24-15943_NEWD-2_K2.6_mega.bin">DD-Wrt mega build 15943</a>.  The approach outlined here might apply to other routers or builds that support OpenVPN and a writable file system such as JFFS, albeit with minor changes.

<span style="color: #ffffff;">:</span>
<h2>Before you start</h2>
This article assumes that readers possess a prior understanding of basic networking concepts such as IP addresses, DNS names, sub nets, routing, bridging, network interfaces, LANs and firewall rules.

Prior to configuring OpenVPN, we need to gain shell access to the routers, give the server a domain name, and create writable storage, keys and certificates.
<h3>Writable storage</h3>
The most obvious method of configuring OpenVPN is through the DD-Wrt web interface (WebGUI).  This stores the configuration, certificates and keys in nonvolatile memory (nvram).  In many routers, there may not be enough nvram to store all this information.  To show the amount of nvram available, use the command "nvram show | grep size:".

The approach presented here, has no nvram footprint.  Instead it stores the configuration, keys and certificates on an USB memory stick.  To format this memory stick, use the WebGUI as described in the <a title="DD-Wrt JFFS Wiki" href="http://www.dd-wrt.com/wiki/index.php/JFFS">DD-Wrt JFFS Wiki</a>.  An excerpt:
<ol>
	<li>Insert the memory stick into any available USB port on the back of your DD-Wrt router.</li>
	<li>In the WebGUI:
<ul>
	<li>Administration &gt; JFFS2 Support &gt; Enable = true, click <em>Save</em></li>
	<li>Wait a few seconds, the click <em>Apply</em>, wait a few seconds</li>
	<li>Administration &gt; JFFS2 Support &gt; Clean JFFS = true, click <em>Apply</em></li>
	<li>Wait for the router to finish formatting the memory stick and brings up the WebGUI again.</li>
	<li>Administration &gt; JFFS2 Support &gt; Clean JFFS = true, click <em>Save</em></li>
</ul>
</li>
	<li>Reboot the router (just to make sure)</li>
	<li>The memory stick will auto mount at <em>/jffs</em>.</li>
</ol>
<h3>Certificates and keys</h3>
OpenVPN uses bidirectional authentication based on X.509 certificates.  In this model the CA is a third party that is trusted by the owner of the certificate and the party relying on the certificate.

To establish  mutual trust, the client authenticates the server certificate, and the server authenticates the client certificate.  It does this by first verifying that the presented certificate was signed by a certifying authority (CA) .  It then tests information in the certificate header such as the common name (CN) or certificate type (client or server).  For details refer to the <a title="OpenVPN Howto" href="http://openvpn.net/index.php/open-source/documentation/howto.html#pki">OpenVPN Howto</a>.

In the examples below, we will setup our own CA and generate self signed certificates using a Linux host:
<ol>
	<li>Copy the <em>easy-rsa </em>directory and initialize:
<pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">cp -R /usr/share/openvpn/easy-rsa/2.0 ~/openvpn-ca  # easy-rsa may be elsewhere
cd ~/openvpn-ca
vi vars  # update the fields at the end of the file 
. ./vars
./clean-all</pre>
</li>
	<li>While we're at it, assign extended key usage that will allow you to use the client certificates for other purposes such as code signing and email.
<pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">vi .`./whichopensslcnf`
# under [ usr_cert ], extend the extendedKeyUsage parameter to
# "clientAuth, emailProtection, codesigning"</pre>
<blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;">later if so desired, you can convert client certificates to PKCS12 format using
<pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">openssl pkcs12 -export -in client.crt -inkey client.key \
           -out client.p12 -certfile ca.crt</pre>
You can then import the certificates in windows by running "certmgr.msc" and importing the <i>ca.crt</i> to the Trusted Root Certificate Authority, and the <i>client.p12</i> to the Personal certificates.</blockquote>
</li>
	<li>Create a certifying authority certificate and corresponding secret key.  Use your name followed by CA as the common name:
<pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">./build-ca</pre>
</li>
	<li>Create Diffie Hellman parameters and shared secret key for tls-auth:
<pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">./build-dh
openvpn --genkey --secret keys/ta.key</pre>
</li>
	<li>Show certificate details:
<pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">openssl -x509 -in keys/rtr2.crt --noout -text</pre>
</li>
</ol>
<h3>Real-time clock</h3>
Certificates have introduction and expiration dates, and therefore require the real-time clock and time zone to be set correctly.

The Network Time Protocol (NTP) can be used to automatically set the clocks.  To configure NTP on the DD-Wrt server and clients:
<ul>
	<li>Setup &gt; Basic Setup &gt; Time Settings.  For my locality the settings are:
<ul>
	<li>Time Zone = UTC-08:00</li>
	<li>Summer Time = 2nd Sun Mar - first Sun Nov</li>
	<li>Server IP/Name = 0.north-america.pool.ntp.org</li>
</ul>
</li>
</ul>
<h3>Domain name</h3>
Usually the client will find the server by its public domain name.  If your router gets a dynamic WAN address, you should configure a Dynamic DNS (DDNS) service on the router used as OpenVPN servers.  This will give the router a public domain name whose address is automatically updated.
<ul>
	<li>Setup &gt; DDNS &gt; Dynamic Domain Name System (my personal favorite is afraid.org)
<ul>
	<li>DDNS Service = freedns.afraid.org</li>
	<li>Host Name = <em>yourhostname</em>,<em>hash</em> (the <em>hash</em> value can be obtained as described in <a href="http://knoxgeek.blogspot.com/2009/08/dd-wrt-and-freednsafraidorg.html">DD-Wrt and freedns.afraid.org</a>).</li>
</ul>
</li>
</ul>
<h3>SSH and emacs</h3>
The examples below assume that routers are accessible using secure shell (<a href="http://www.dd-wrt.com/wiki/index.php/SSH">ssh</a>).  This also allows use of ssh features in an editor such as emacs. For example, on the Linux host used as the certifying authority:
<pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">emacs /rtr:/jffs/etc/config/rtr-server.wanup</pre>
Where <em>rtr</em> corresponds to an entry in  your <em>~/.ssh/config</em> file.

<span style="color: #ffffff;">:</span>
<h2>Routing versus Bridging</h2>
OpenVPN can connect clients using network routing or bridging.  For a comparison between routing and bridging, refer to <a href="http://community.openvpn.net/openvpn/wiki/BridgingAndRouting">Bridging vs. Routing</a>.  An excerpt:
<ul>
	<li><em>Routing</em> uses the kernel device TUN to simulate a network layer device.  It operates at the network layer where it handles <em></em>IP packets.  As a result, it:
<ul>
	<li>has a low overhead, because it does not support broadcasts or require Ethernet headers;</li>
	<li>for IPv6, OpenVPN version &gt;=2.3 is required.</li>
</ul>
</li>
	<li><em>Bridging</em>uses the kernel device TAP to simulates a link layer device.  It operates at the link layer and handles Ethernet frames.  Consequently it:
<ul>
	<li>supports non-IP based traffic;</li>
	<li>supports Windows network neighborhood discovery without using WINS;</li>
	<li>broadcasts and Ethernet headers cause overhead (for examples, you need to tell DHCP server not to respond to request coming over TAP).</li>
</ul>
</li>
</ul>
<span style="color: #ffffff;">:</span>
<h2>Routing example: Site-to-Site</h2>
OpenVPN can be used to connect two local area networks (LANs).  In this example, two DD-Wrt routers are used.  One serves as the server, and the other as the client.  Note that the private network numbers are fairly arbitrary.  They were chosen to match my existing networks.
<ul>
	<li><em>rtr</em>, the server, with
<ul>
	<li>WAN address <em>rtr.yourdomain.com</em></li>
	<li>LAN network 10.0.1.0/24</li>
</ul>
</li>
	<li><em>rtr2</em>, the client.
<ul>
	<li>LAN network 10.0.2.0/24</li>
</ul>
</li>
</ul>
The server will use network 10.0.3.0/24 for the VPN.  Of that allocates the first address (10.0.3.1) for itself.  Clients will be allocated one of the remaining addresses.

<a href="http://www.coertvonk.com/technology/networking/dd-wrt-and-openvpn-5591/attachment/rtr-server" rel="attachment wp-att-5818"><img class="aligncenter size-full wp-image-5818" title="rtr-server" alt="rtr-server" src="http://www.coertvonk.com/wp-content/uploads/rtr-server.png" width="437" height="354" /></a>

The examples presented here, do not use the WebGUI nor NVRAM.  Instead they use bash scripts store on an memory stick and mounted as <em>/jffs</em>.  The scripts are automatically started by DD-Wrt each time the WAN link and firewall are up.  For more information refer to <a href="http://www.dd-wrt.com/wiki/index.php/Script_Execution" target="_blank">DD-Wrt Script Execution</a>.
<h3>Certificates</h3>
<ul>
	<li>On the Linux host, create certificates and corresponding secret keys for the server and client.
<pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">./build-key-server rtr-server # common name = rtr, no passwd
./build-key        rtr2       # common name = rtr2, no passwd</pre>
</li>
</ul>
<h3>OpenVPN Server</h3>
<ul>
	<li>From the Linux host, copy the certificates/keys files to <em>/jffs/etc/openvpn </em>on the server.
<pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">ssh rtr mkdir -p /jffs/etc/config
ssh rtr mkdir -p /jffs/etc/openvpn/ccd
scp ca.crt dh1024.pem ta.key rtr-server.crt rtr-server.key rtr:/jffs/etc/openvpn/</pre>
</li>
	<li>Create a startup script <em>/jffs/etc/openvpn/config/rtr-server.wanup </em>on the server.  Make the script executable (<em>chmod 755</em>).  DD-Wrt will call this script each time the WAN link comes up.
<pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">#!/bin/sh

DEV=tun0
PORT=1194
PROTO=udp

BASE=$(basename $0)
NAME=${BASE%\.*}
TMP=/tmp/$NAME
PID=$TMP/pid
LOG=$TMP/log
#LOG=/dev/null
DIR=$(dirname $0)/../openvpn

[ -d $TMP ] || mkdir -p $TMP

if [ -e $PID ] ; then
    kill -0 `cat $PID`
    if [ $? -eq 1 ] ; then
	rm $PID  # remove false PID
    fi
fi

if [ -e $PID ] ; then
    kill -HUP `cat $PID`  # restart
else
    rm $PID
    ln -s /usr/sbin/openvpn $TMP/openvpn
    $TMP/openvpn \
	--daemon --writepid $PID --log-append $LOG \
	--cd $DIR --config $NAME.ovpn \
	--dev $DEV --port $PORT --proto $PROTO \
	--up "$DIR/$NAME.helper $DEV $PORT $PROTO up" \
	--down "$DIR/$NAME.helper $DEV $PORT $PROTO down" \
	--ifconfig-pool-persist $TMP/ip-pool 86400
fi</pre>
</li>
	<li>Create an helper script <em>/jffs/etc/openvpn/rtr-server.helper </em>on the server. Make the script executable (<em>chmod 755</em>).
<pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">#!/bin/sh
DEV=$1
PORT=$2
PROTO=$3
case "$4" in
    'up')
        iptables -I INPUT -p $PROTO --dport $PORT -j ACCEPT
        iptables -I INPUT   -i $DEV -j ACCEPT
        iptables -I FORWARD -i $DEV -j ACCEPT
        iptables -I FORWARD -o $DEV -j ACCEPT
	;;
    'down')
        iptables -D INPUT -i $DEV -j ACCEPT
        iptables -D INPUT -p $PROTO --dport $PORT -j ACCEPT
        iptables -D FORWARD -i $DEV -j ACCEPT
        iptables -D FORWARD -o $DEV -j ACCEPT
	;;
    *)
	exit 1
esac
exit 0</pre>
</li>
	<li>Create the configuration file <em>/jffs/etc/openvpn/rtr-server.ovpn </em>on the server
<pre class="brush: text; gutter: false; toolbar: off; tab-size: 8">server 10.0.3.0 255.255.255.0
ca ca.crt
cert rtr-server.crt
key rtr-server.key
dh dh1024.pem
tls-auth ta.key 0
tls-server
keepalive 10 120
cipher bf-cbc
auth sha1
mtu-disc yes
topology subnet
fast-io
verb 4
mute 5
management 127.0.0.1 5002
management-log-cache 50
push "route 10.0.1.0 255.255.255.0"
client-config-dir ccd                  # run client script matching CN
route 10.0.2.0 255.255.255.0 10.0.3.1  # kernel to OpenVPN server
client-to-client</pre>
</li>
	<li>Create the client specific configuration file <em>/jffs/etc/openvpn/ccd/rtr2 </em>on the server
<pre class="brush: text; gutter: false; toolbar: off; tab-size: 8">iroute 10.0.2.0 255.255.255.0  # OpenVPN server to remote clients</pre>
</li>
	<li>Start the OpenVPN server
<pre class="brush: text; gutter: false; toolbar: off; tab-size: 8">/jffs/etc/config/rtr-server.wanup</pre>
</li>
	<li>See how it is going.  Note that you can also use the WebGUI (Status &gt; OpenVPN) to inspect the OpenVPN log messages.
<pre class="brush: text; gutter: false; toolbar: off; tab-size: 8">more /tmp/rtr-server/log  # a treasure trove of debug information
netstat -lu               # should be listening on port 1194
iptables -nvL             # INPUT chain should have port 1194 open</pre>
</li>
</ul>
<h3>OpenVPN Client</h3>
<ul>
	<li>From the Linux host, copy the certificates/keys files to <em>/jffs/etc/openvpn</em>
<pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">ssh rtr2 mkdir -p /jffs/etc/config
ssh rtr2 mkdir -p /jffs/etc/openvpn
scp ca.crt ta.key rtr2.crt rtr2.key rtr2:/jffs/etc/openvpn/</pre>
</li>
	<li>Create a startup script <em>/jffs/etc/openvpn/config/rtr2-to-rtr.wanup </em>on the server.  Remember to make the script executable (<em>chmod 755</em>).  DD-Wrt will call this script each time the WAN link comes up.
<pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">#!/bin/sh

DEV=tun0
PORT=1194
PROTO=udp

BASE=$(basename $0)
NAME=${BASE%\.*}
TMP=/tmp/$NAME
PID=$TMP/pid
LOG=$TMP/log
#LOG=/dev/null
DIR=$(dirname $0)/../openvpn

[ -d $TMP ] || mkdir -p $TMP

if [ -e $PID ] ; then
    kill -0 `cat $PID`
    if [ $? -eq 1 ] ; then
	rm $PID  # remove false PID
    fi
fi

if [ -e $PID ] ; then
    kill -HUP `cat $PID`  # restart
else
    rm $PID
    ln -s /usr/sbin/openvpn $TMP/openvpn
    $TMP/openvpn \
	--daemon --writepid $PID --log-append $LOG \
	--cd $DIR --config $NAME.ovpn \
	--dev $DEV --port $PORT --proto $PROTO \
	--up "$DIR/$NAME.helper $DEV up" \
	--down "$DIR/$NAME.helper $DEV down"
fi</pre>
</li>
	<li>Create an helper script <em>/jffs/etc/openvpn/rtr2-to-rtr.helper </em>on the server. Remember to make the script executable (<em>chmod 755</em>).
<pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">#!/bin/sh
DEV=$1
case "$2" in
    'up')
        iptables -I INPUT   -i $DEV -j ACCEPT
        iptables -I FORWARD -i $DEV -j ACCEPT
        iptables -I FORWARD -o $DEV -j ACCEPT
	;;
    'down')
        iptables -D INPUT -i $DEV -j ACCEPT
        iptables -D FORWARD -i $DEV -j ACCEPT
        iptables -D FORWARD -o $DEV -j ACCEPT
	;;
    *)
	exit 1
esac
exit 0</pre>
</li>
	<li>Create the configuration file <em>/jffs/etc/openvpn/rtr2-to-rtr.ovpn </em>on the client
<pre class="brush: text; gutter: false; toolbar: off; tab-size: 8">client
remote rtr.yourdomain.com
ns-cert-type server
ca ca.crt
cert rtr2.crt
key rtr2.key
tls-auth ta.key 1
tls-client
cipher bf-cbc
auth sha1
resolv-retry infinite
nobind
persist-key
persist-tun
mtu-disc yes
fast-io
verb 4
mute 5
management 127.0.0.1 5001
management-log-cache 50</pre>
</li>
	<li>Start the OpenVPN client
<pre class="brush: text; gutter: false; toolbar: off; tab-size: 8">/jffs/etc/config/rtr2-to-rtr.wanup</pre>
</li>
	<li>See how things are going.  Note that you can also use the WebGUI (Status &gt; OpenVPN) to inspect the OpenVPN log messages.
<pre class="brush: text; gutter: false; toolbar: off; tab-size: 8">more /tmp/rtr2-to-rtr/log</pre>
</li>
</ul>
<span style="color: #ffffff;">:</span>
<h2>Bridging example: Remote Access</h2>
OpenVPN can also be used to connect remote computers to a local area network.  The VPN gives the remote computers access to resources on the local area network such as files, printers, databases or internal websites.

In this example, one DD-Wrt router is configured as an OpenVPN server.  Road warrior clients can connect to this router to gain access to the server's LAN.  The systems are:
<ul>
	<li><em>rtr2</em>, the server with:
<ul>
	<li>LAN network 10.0.2.0/24</li>
	<li>WAN address <em>rtr2.yourdomain.com</em></li>
</ul>
</li>
	<li><em>client</em>, connecting from a public IP address, running either
<ul>
	<li>Windows 7 x64 with <a href="http://openvpn.net/release/openvpn-2.1.3-install.exe">OpenVPN GUI &gt;=2.1.3</a> installed, or</li>
	<li>Mac OS X with  <a href="http://code.google.com/p/tunnelblick/">Tunnelblick &gt;=3.2.8</a>  installed.</li>
</ul>
</li>
</ul>
<a href="http://www.coertvonk.com/technology/networking/dd-wrt-and-openvpn-5591/attachment/rtr2-server" rel="attachment wp-att-5819"><img class="aligncenter size-full wp-image-5819" title="rtr2-server" alt="rtr2-server" src="http://www.coertvonk.com/wp-content/uploads/rtr2-server.png" width="437" height="261" /></a>
<h3>Certificates</h3>
<ul>
	<li>On the Linux host, create certificates and corresponding secret keys for the server and clients.
<pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">./build-key-server rtr2-server  # common name = rtr2, no passwd
./build-key        username1    # common name = username1, no passwd
./build-key        username2    # common name = username2, no passwd</pre>
</li>
</ul>
<h3>OpenVPN Server</h3>
<ul>
	<li>From the Linux host, copy the certificates/keys files to <em>/jffs/etc/openvpn </em>on the server.
<pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">ssh rtr mkdir -p /jffs/etc/config
ssh rtr mkdir -p /jffs/etc/openvpn/ccd
scp ca.crt dh1024.pem ta.key rtr-server.crt rtr-server.key rtr:/jffs/etc/openvpn/</pre>
</li>
	<li>Create a startup script <em>/jffs/etc/openvpn/config/rtr2-server.wanup </em>on the server. Make the script executable (<em>chmod 755</em>). DD-Wrt will call this script each time WAN link comes up.
<pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">#!/bin/sh

BR=br0
DEV=tap0
ETHDEV=eth0
PORT=1194
PROTO=udp

BASE=$(basename $0)
NAME=${BASE%\.*}
TMP=/tmp/$NAME
PID=$TMP/pid
LOG=$TMP/log
#LOG=/dev/null
DIR=$(dirname $0)/../openvpn

[ -d $TMP ] || mkdir -p $TMP
echo "$(date) $NAME: WAN up" &gt;$LOG

if [ -e $PID ] ; then
    kill -0 `cat $PID`
    if [ $? -eq 1 ] ; then
	rm $PID  # remove false PID
    fi
fi

if [ -e $PID ] ; then
    kill -HUP `cat $PID`  # restart
else
    rm $PID

    ln -s /usr/sbin/openvpn $TMP/openvpn
    $TMP/openvpn \
	--daemon --writepid $PID --log-append $LOG \
	--cd $DIR --config $NAME.ovpn \
	--dev $DEV --port $PORT --proto $PROTO \
	--up "$DIR/$NAME.helper $BR $DEV $PORT $PROTO up" \
	--down "$DIR/$NAME.helper $BR $DEV $PORT $PROTO down" \
	--ifconfig-pool-persist $TMP/ip-pool 86400
fi</pre>
</li>
	<li>Create an helper script <em>/jffs/etc/openvpn/rtr2-server.helper </em>on the server. Make the script executable (<em>chmod 755</em>).
Note that the <em>tap</em> interface will get a random MAC address and the bridge (<em>br0</em>) picking up the lowest address.  This confuses Windows Network Discovery in Windows 7, triggering a "Set Network Location" dialog.  To prevent this, you can take the last random MAC address and reuse it for subsequent <em>tap</em> interfaces.  (More details <a href="http://www.dd-wrt.com/phpBB2/viewtopic.php?p=508041">here</a>.)
<pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">#!/bin/sh
BR=$1
DEV=$2
PORT=$3
PROTO=$4
case "$5" in
    'up')
	#ifconfig $DEV hw ether enter_your_last_mac_address
        ifconfig $DEV 0.0.0.0 promisc up 
        brctl addif $BR $DEV 
        iptables -I INPUT -p $PROTO --dport $PORT -j ACCEPT
	iptables -I INPUT   -i $DEV -j ACCEPT
	iptables -I FORWARD -i $DEV -j ACCEPT
	iptables -I FORWARD -o $DEV -j ACCEPT
	;;
    'down')
	brctl delif $DEV
	ifconfig $DEV down
	iptables -D INPUT -i $DEV -j ACCEPT
	iptables -D INPUT -p $PROTO --dport $PORT -j ACCEPT
	iptables -D FORWARD -i $DEV -j ACCEPT
	iptables -D FORWARD -o $DEV -j ACCEPT
	;;
    *)
	exit 1
esac
exit 0</pre>
</li>
	<li>Create the configuration file <em>/jffs/etc/openvpn/rtr2-server.ovpn </em>on the server. Note that port 5002 is used by the <em>/etc/openvpn*.sh</em>scripts.
<pre class="brush: text; gutter: false; toolbar: off; tab-size: 8">server-bridge 10.0.2.1 255.255.255.0 10.0.2.150 10.0.2.159
ca ca.crt
cert rtr2-server.crt
key rtr2-server.key
dh dh1024.pem
tls-auth ta.key 0
keepalive 10 120
cipher bf-cbc
auth sha1
mtu-disc yes
topology subnet
client-to-client
push "route 10.0.1.0 255.255.255.0 10.0.2.1" # optional across other VPN
fast-io
verb 4
mute 5
management 127.0.0.1 5002
management-log-cache 50</pre>
</li>
	<li>Start the OpenVPN server
<pre class="brush: text; gutter: false; toolbar: off; tab-size: 8">/jffs/etc/config/rtr2-server.wanup</pre>
</li>
	<li>See how it is going. Note that you can also use the WebGUI (Status &gt; OpenVPN) to inspect the OpenVPN log messages.
<pre class="brush: text; gutter: false; toolbar: off; tab-size: 8">more /tmp/rtr2-server/log  # a treasure trove of debug information
netstat -lu                # should be listening on port 1194
iptables -nvL              # INPUT chain should have port 1194 open</pre>
</li>
</ul>
<h3>OpenVPN Server (using WebGUI)</h3>
Alternatively, the server can be configured using the DD-Wrt WebGUI.  The config will be stored in nvram, except for the large certificates and key files that are stored on a memory stick.  In this configuration, DD-Wrt generate matching files in <em>/tmp/openvpn/</em>.
<ul>
	<li>Copy the certificates/keys files.  Remember to limit access to the key files (<em>chmod 600</em>).
<ul>
	<li><em>ca.crt</em></li>
	<li><em>rtr2-server.crt</em></li>
	<li><em>rtr2-server.key</em></li>
	<li><em>dh1024.pem</em></li>
	<li><em>ta.key</em></li>
</ul>
</li>
	<li>Services &gt; VPN &gt; OpenVPN Server.  These values will be used to create the configuration file <em>/tmp/openvpn/openvpn.conf</em>
<ul>
	<li>Start OpenVPN Server = enable</li>
	<li>Start Type = WAN up (after domain resolver is up)</li>
	<li>Switch Server config = new Style</li>
	<li>Pool IP = 10.0.2.150 .. 10.0.2.159</li>
	<li>Gateway = 10.0.2.1</li>
	<li>Netmask = 255.255.255.0</li>
	<li>Port = 1194</li>
	<li>Tunnel Protocol = UDP</li>
	<li>Encryption Cipher = Blowfish CBC</li>
	<li>Hash Algorithm = SHA1</li>
	<li>Advanced Options = disable</li>
	<li>The Cert, Key fields are left blank.  Instead use the Additional Config field to refer to the files on the USB stick  (<a href="http://www.dd-wrt.com/phpBB2/viewtopic.php?t=145460">see OpenVPN with key and certificate files via WebGUI</a>).
<pre class="brush: text; gutter: false; toolbar: off; tab-size: 8">cert /jffs/rtr2.crt
ca /jffs/ca.crt
key /jffs/rtr2.key
dh /jffs/dh2048.pem
tls-auth /jffs/ta.key 0
push "route 10.0.2.0 255.255.255.0"</pre>
</li>
</ul>
</li>
</ul>
<h3>OpenVPN Client, running Windows 7</h3>
<ul>
	<li>Use explorer to show the directory "C:\Program Files (x86)\OpenVPN\config\"
<ul>
	<li>Populate the directory with the certificate and key files from the Linux host:
<ul>
	<li><em>ca.crt</em></li>
	<li><em>username1.crt</em></li>
	<li><em>username1.key</em></li>
	<li><em>ta.key</em></li>
</ul>
</li>
</ul>
<ul>
	<li>Create the configuration file <em>rtr2.ovpn</em> in that same directory<em>
</em>
<pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">remote rtr2.yourdomain.com 1194
client
ca ca.crt 
cert username1.crt 
key username1.key 
tls-auth ta.key 1
ns-cert-type server
dev tap
proto udp 
nobind 
resolv-retry infinite 
persist-key 
persist-tun 
remote-cert-tls server 
float
script-security 2
cipher BF-CBC
auth SHA1
verb 3
mute 5</pre>
</li>
</ul>
</li>
	<li>With OpenVPN running, right-click on its icon in the task area (bottom right) &gt; connect &gt; <em>rtr2</em>.</li>
</ul>
<h3>OpenVPN Client, running OS X</h3>
<ul>
	<li>Create folder rtr2.yourdomain.com on your Desktop.  (details can be found in the <a href="http://code.google.com/p/tunnelblick/wiki/cConfigT">wiki</a>)
<ul>
	<li>Copy the certificate/key files to that folder
<ul>
	<li><em>ca.crt</em></li>
	<li><em>username2.crt</em></li>
	<li><em>username2.key</em></li>
	<li><em>ta.key</em></li>
</ul>
</li>
</ul>
<ul>
	<li>In that folder, create configuration file <em>rtr2.ovpn</em>
<pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">remote rtr2.yourdomain.com 1194  # update me
client
ca ca.crt 
cert username2.crt 
key username2.key 
tls-auth ta.key 1
ns-cert-type server
dev tap
proto udp 
nobind 
resolv-retry infinite 
persist-key 
persist-tun 
remote-cert-tls server 
float
script-security 2
cipher BF-CBC
auth SHA1
verb 3
mute 5</pre>
</li>
</ul>
</li>
	<li>Append the extension <em>.tblk</em> to the folder name. This will change the folder icon into a Tunnelblick VPN Configuration.</li>
	<li>Double-click the folder's new icon to install it. Choose private configuration when asked.</li>
</ul>]]></description>
		<wfw:commentRss>http://www.coertvonk.com/technology/networking/dd-wrt-and-openvpn-5591/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<enclosure url="http://www.coertvonk.com/wp-content/uploads/networking-ddwrt-and-openvpn.png" length="131668" type="image/jpg" />
<media:content xmlns:media="http://search.yahoo.com/mrss/" url="http://www.coertvonk.com/wp-content/uploads/networking-ddwrt-and-openvpn.png" width="300" height="300" medium="image" type="image/jpeg">
<media:copyright>Coert Vonk</media:copyright>
</media:content>
	</item>
		<item>
		<title>DD-WRT and U-Verse, router behind router (and debugging with wireshark)</title>
		<link>http://www.coertvonk.com/technology/networking/ddwrt-uverse-5602</link>
		<comments>http://www.coertvonk.com/technology/networking/ddwrt-uverse-5602#comments</comments>
		<pubDate>Fri, 31 Aug 2012 18:36:40 +0000</pubDate>
		<dc:creator>Coert</dc:creator>
				<category><![CDATA[Networking]]></category>
		<category><![CDATA[10 minutes]]></category>
		<category><![CDATA[at&t]]></category>
		<category><![CDATA[DD-WRT]]></category>
		<category><![CDATA[dhcp]]></category>
		<category><![CDATA[DMZ+]]></category>
		<category><![CDATA[DMZplus]]></category>
		<category><![CDATA[double nat]]></category>
		<category><![CDATA[iptables]]></category>
		<category><![CDATA[lease time]]></category>
		<category><![CDATA[sbc]]></category>
		<category><![CDATA[u-verse]]></category>

		<guid isPermaLink="false">http://www.coertvonk.com/?p=5602</guid>
		<description><![CDATA[<div><img width="150" height="150" src="http://www.coertvonk.com/wp-content/uploads/networking-ddwrt-uverse-150x150.png" class="attachment-post-thumbnail wp-post-image" alt="networking-ddwrt-uverse" /></div><a href="http://www.coertvonk.com/technology/networking/ddwrt-uverse-5602/attachment/networking-ddwrt-uverse" rel="attachment wp-att-6639"><img class="alignright size-thumbnail wp-image-6639" alt="networking-ddwrt-uverse" src="http://www.coertvonk.com/wp-content/uploads/networking-ddwrt-uverse-150x150.png" width="150" height="150" /></a>In our nick of the woods, AT&amp;T is migrating customers to U-Verse (VDSL).  The internet service comes with a 2-Wire 3600HGV WiFi router.
<h3>Preventing Double NAT</h3>
When you want to continue using your own router, it To use your own router instead (and prevent double NAT), you need to put their router in bridge mode.  Note that your system password is printed on the side of the router.

http://192.168.1.254/

Settings &gt; LAN &gt; Wireless &gt; Wireless Interface = disabled

Settings &gt; System Info &gt; Event Notifications &gt; Router-behind-Router detection = enabled

Browse to any web page.  The router will intercept this, and ask you to apply a DMZplus fix.  Accept that.
<h3>DHCP Lease Time</h3>
When the U-Verse router in in DMZplus mode, it limits the DHCP lease to 10 minutes.  Worse, the DHCP reply comes from a different IP address.  This causes the state full DD-WRT firewall to drop the reply.  Work around this by adding the following firewall rule:
<pre class="brush: bash; gutter: false; toolbar: off; tab-size: 8">iptables -I input -p udp --dport 68 -j ACCEPT</pre>]]></description>
		<wfw:commentRss>http://www.coertvonk.com/technology/networking/ddwrt-uverse-5602/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<enclosure url="http://www.coertvonk.com/wp-content/uploads/networking-ddwrt-uverse.png" length="134606" type="image/jpg" />
<media:content xmlns:media="http://search.yahoo.com/mrss/" url="http://www.coertvonk.com/wp-content/uploads/networking-ddwrt-uverse.png" width="300" height="300" medium="image" type="image/jpeg">
<media:copyright>Coert Vonk</media:copyright>
</media:content>
	</item>
		<item>
		<title>Complex Arithmetic in Extended Memory for HP-41cv/cx</title>
		<link>http://www.coertvonk.com/technology/hp41/complex-arithmetic-xmem-4426</link>
		<comments>http://www.coertvonk.com/technology/hp41/complex-arithmetic-xmem-4426#comments</comments>
		<pubDate>Sat, 03 Mar 2012 19:11:24 +0000</pubDate>
		<dc:creator>Coert</dc:creator>
				<category><![CDATA[Math (HP-41)]]></category>

		<guid isPermaLink="false">http://www.coertvonk.com/?p=4426</guid>
		<description><![CDATA[<div><img width="150" height="150" src="http://www.coertvonk.com/wp-content/uploads/complex-arithmetic-xmem-150x150.png" class="attachment-post-thumbnail wp-post-image" alt="complex-arithmetic-xmem" /></div><a href="http://www.coertvonk.com/technology/hp41/complex-arithmetic-xmem-4426/attachment/complex-arithmetic-xmem-2" rel="attachment wp-att-6617"><img class="alignright size-thumbnail wp-image-6617" alt="complex-arithmetic-xmem" src="http://www.coertvonk.com/wp-content/uploads/complex-arithmetic-xmem-150x150.png" width="150" height="150" /></a>This program introduces complex number operations to the HP-41CV and HP-41CX pocket calculators. It is a variation on Frans de Vries' program published in PPC Journal [1]. I made it more intuitive by showing the result as a complex number and by making the <span class="hp41-key">R/S</span> button behave like a <span class="hp41-cikey">COMPLEX</span> prefix to operations.
<h3>History</h3>
In May 1985, Frans de Vries published his Complex Arithmetic program for the HP-41CX [1]. I am very grateful for his work, and much of this documentation is based on his work. My iteration of this program has been a pet project while in college. Inspired by this program, I wrote a library in Oxford Pascal for the Commodore-64. Internally this library used polar notation because complex multiplication may result in an angle exceeding the branch cut. I designed a RS232 interface for this Commodore-64, and waited for an unsupervised moment and transferred the library to the Pr1me computer on campus. When I acquired my first IBM PC clone, once again this program moved alongside with me.

Now, twenty-five years later, I restored my faithful HP-41 and use the same program once again. This version is also verified to run under Windows using Warren Furlow's V41 simulator when compiled with Leo Duran's hp41uc.
<h3>Instructions</h3>
To start the program use <span class="hp41-ckey">XEQ</span> "CA". From here you can use the complex operations by pressing <span class="hp41-cikey">COMPLEX</span> (the <span class="hp41-key">R/S</span> key on the normal keyboard) followed by the desired operation. The overlay shown below these operation can be recognized by the blue paint splash behind the labels. These same operations are referenced in this article by enclosing them in a <span class="hp41-ckey">blue box</span>.

Note that <span class="hp41-ckey">BCUT</span> is only implemented in "<a href="http://www.coertvonk.com/technology/hp41/complex-arithmetic-branchcut-5032">Complex Arithmetic with adjustable branch cut for HP-41cv/cx</a>".

<a href="http://www.coertvonk.com/technology/hp41/complex-arithmetic-xmem-4426/attachment/overlay6" rel="attachment wp-att-5045"><img class="wp-image-5045 aligncenter" title="Complex Arithmetic keyboard overlay" alt="Complex Arithmetic keyboard overlay" src="http://www.coertvonk.com/wp-content/uploads/overlay6.jpg" width="550" height="875" /></a>

The table shows the key assignments with their effect on the complex stack.
<table style="width: 500px;" border="1">
<tbody>
<tr>
<td><em>operation</em></td>
<td><em>key</em></td>
<td><em>description</em></td>
<td><em>stack</em></td>
</tr>
<tr>
<td><span class="hp41-cikey">COMPLEX</span></td>
<td><span class="hp41-key">R/S</span></td>
<td>Prefix for Complex operations.</td>
<td>N</td>
</tr>
<tr>
<td><span class="hp41-cnkey">INIT</span></td>
<td><span class="hp41-nkey">ON</span></td>
<td>Reinitialize, but do not clear stack.</td>
<td></td>
</tr>
<tr>
<td><span class="hp41-ckey">+</span></td>
<td><span class="hp41-key">+</span></td>
<td>Adds Z1 to Z2.</td>
<td>E,L,↓</td>
</tr>
<tr>
<td><span class="hp41-ckey">/</span></td>
<td><span class="hp41-key">*</span></td>
<td>Multiplies Z2 by Z1.</td>
<td>E,L,↓</td>
</tr>
<tr>
<td><span class="hp41-ckey">/</span></td>
<td><span class="hp41-key">/</span></td>
<td>Divides Z2 by Z1.</td>
<td>E,L,↓</td>
</tr>
<tr>
<td><span class="hp41-ckey">//</span></td>
<td><span class="hp41-key">XEQ</span></td>
<td>Take Z1 and Z2 parallel (network theory).</td>
<td>E,L,↓</td>
</tr>
<tr>
<td><span class="hp41-ckey">CHS</span></td>
<td><span class="hp41-key">CHS</span></td>
<td>Negate Z1.</td>
<td>E</td>
</tr>
<tr>
<td><span class="hp41-ckey">CON</span></td>
<td><span class="hp41-key">ISG</span></td>
<td>Complement/conjugate of Z1.</td>
<td>E</td>
</tr>
<tr>
<td><span class="hp41-ckey">1/Z</span></td>
<td><span class="hp41-key">1/X</span></td>
<td>Reciprocal of Z1.</td>
<td>E</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">Z2<sup>Z1</sup></span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">y<sup>x</sup></span></td>
<td rowspan="1" colspan="1">Z2 to the power Z1.</td>
<td rowspan="1" colspan="1">E,L,↓</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">LOG</span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">LOG</span></td>
<td rowspan="1" colspan="1">Base 10 logarithm of Z1.</td>
<td rowspan="1" colspan="1">E,L</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">LN</span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">LN</span></td>
<td rowspan="1" colspan="1">Natural logarithm of Z1.</td>
<td rowspan="1" colspan="1">E,L</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">e<sup>Z</sup></span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">e<sup>x</sup></span></td>
<td rowspan="1" colspan="1">e to the power Z1.</td>
<td rowspan="1" colspan="1">E,L</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">Z<sup>n</sup></span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">x<sup>2</sup></span></td>
<td rowspan="1" colspan="1">Z1 to the real number power n.</td>
<td rowspan="1" colspan="1">E,L</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">Z<sup>1/n</sup></span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">√x</span></td>
<td rowspan="1" colspan="1">All n<sup>th</sup> roots of Z1.</td>
<td rowspan="1" colspan="1">E,L</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">n<sup>Z</sup></span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">10<sup>x</sup></span></td>
<td rowspan="1" colspan="1">Real number N to the power Z1.</td>
<td rowspan="1" colspan="1">E,L</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">RECT</span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">P→R</span></td>
<td rowspan="1" colspan="1">Sets the input/output mode to rectangular.</td>
<td rowspan="1" colspan="1">N</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">POL</span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">R→P</span></td>
<td rowspan="1" colspan="1">Sets the input/output mode to polar.</td>
<td rowspan="1" colspan="1">N</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">ENTER<span class="hp41-cup-arrow"> </span></span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">ENTER<span class="hp41-up-arrow"> </span></span></td>
<td rowspan="1" colspan="1">Lifts the stack and disables stack left.</td>
<td rowspan="1" colspan="1">D,↑,(↑)</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-cnkey">VIEW</span></td>
<td rowspan="1" colspan="1"><span class="hp41-nkey">ALPHA</span></td>
<td rowspan="1" colspan="1">Enters a new complex number on the stack without lifting the complex stack (compare to the use of <span class="hp41-nkey">ALPHA</span>/<span class="hp41-nkey">ALPHA</span> to terminate digit entry without using <span class="hp41-key">ENTER<span class="hp41-up-arrow"> </span></span>. Recalls Z1 if flag 22 is clear.</td>
<td rowspan="1" colspan="1">E,(↑)</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">CLZ1</span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">CLX</span></td>
<td rowspan="1" colspan="1">Clears Z1 and disables stack lift.</td>
<td rowspan="1" colspan="1">D</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">CLST</span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">RTN</span></td>
<td rowspan="1" colspan="1">Clears the complex stack and the normal stack (LASTZ1 is preserved).</td>
<td rowspan="1" colspan="1">E</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">LASTZ1</span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">LASTX</span></td>
<td rowspan="1" colspan="1">Recalls LASTZ1 onto the stack.</td>
<td rowspan="1" colspan="1">E,(↑)</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">VIEWZn</span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">VIEW</span></td>
<td rowspan="1" colspan="1">Views the contents of Zn. Specify 0 to view LASTZ1.</td>
<td rowspan="1" colspan="1">N</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">R</span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">RDN</span></td>
<td rowspan="1" colspan="1">Rolls the stack down by one complex register.</td>
<td rowspan="1" colspan="1">E</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">R</span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">R</span></td>
<td rowspan="1" colspan="1">Rolls the stack up by one complex register.</td>
<td rowspan="1" colspan="1">E</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">Z1<span class="hp41-cxy"> </span>Z2</span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">X<span class="hp41-xy"> </span>Y</span></td>
<td rowspan="1" colspan="1">Exchanges Z1 with Z2.</td>
<td rowspan="1" colspan="1">E</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">Z1<span class="hp41-cxy"> </span>Zn</span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">CL∑</span></td>
<td rowspan="1" colspan="1">Exchanges Z1 with Zn. Specify 0 for LASTZ1</td>
<td rowspan="1" colspan="1">E</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">ARC</span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">∑+</span></td>
<td rowspan="1" colspan="1">ARC prefix.</td>
<td rowspan="1" colspan="1">N</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">HYP</span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">∑-</span></td>
<td rowspan="1" colspan="1">HYP prefix.</td>
<td rowspan="1" colspan="1">N</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">SIN</span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">SIN</span></td>
<td rowspan="1" colspan="1">Sine of Z1.</td>
<td rowspan="1" colspan="1">E,L</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">COS</span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">COS</span></td>
<td rowspan="1" colspan="1">Cosine of Z1.</td>
<td rowspan="1" colspan="1">E,L</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">TAN</span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">TAN</span></td>
<td rowspan="1" colspan="1">Tangent of Z1.</td>
<td rowspan="1" colspan="1">E,L</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">CSC</span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">SIN<sup>-1</sup></span></td>
<td rowspan="1" colspan="1">Cosecant of Z1</td>
<td rowspan="1" colspan="1">E,L</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">SEC</span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">COS<sup>-1</sup></span></td>
<td rowspan="1" colspan="1">Secant of Z1</td>
<td rowspan="1" colspan="1">E,L</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-ckey">COT</span></td>
<td rowspan="1" colspan="1"><span class="hp41-key">TAN<sup>-1</sup></span></td>
<td rowspan="1" colspan="1">Cotangent of Z1</td>
<td rowspan="1" colspan="1">E,L</td>
</tr>
</tbody>
</table>
The prefixes ARC and HYP provide a rich set of trigonometric and hyperbolic functions. In order to squeeze the program (866 bytes) into the x-memory, the operations ATAN, ATANH, ACOT and ACOTH needed to be removed.
<table style="background-color: #ffffff;" border="0">
<tbody>
<tr>
<td>N</td>
<td>=</td>
<td>neutral stack lift status</td>
<td></td>
<td>↑</td>
<td>=</td>
<td>stack lifts</td>
</tr>
<tr>
<td>D</td>
<td>=</td>
<td>disables stack lift</td>
<td></td>
<td>↓</td>
<td>=</td>
<td>stack drops</td>
</tr>
<tr>
<td>E</td>
<td>=</td>
<td>enables stack lift</td>
<td></td>
<td>(↑)</td>
<td>=</td>
<td>stack lift if enabled</td>
</tr>
<tr>
<td>L</td>
<td>=</td>
<td>Z1 saved in LASTZ1</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<h3>Stack</h3>
The calculating environment consists of 6 complex stack registers, numbered Z1 thru Z6, and a complex LASTZ1 register. The large complex stack limits the need for store and recall functions.
<h4>Entering and displaying complex numbers</h4>
Both rectangular coordinates and polar form are supported for data entry and viewing. To switch between modes, use the <span class="hp41-ckey">RECT</span> and <span class="hp41-ckey">POL</span> operations. Flag 0 shown on the LCD display serves as an annunciator for polar mode.

Input to and output of the complex operations is through the normal stack. In rectangular mode, the real part of the complex number in should be placed in X register and the imaginary part in Y. In polar mode, the magnitude should be in X and the phase in Y. After each operations, the result of the operation is stored on the complex stack as Z1, and shown on the display in a condensed format. To see the full accuracy, press <span class="hp41-key">XY</span> to see the imaginary part (or phase in Polar mode), and <span class="hp41-key">XY</span> again to see the real part (or modulus in Polar mode).
<h4>Start</h4>
<p style="padding-left: 30px;">The program consist of two parts. The first part labeled "CA" fits in a mere 5 registers of main memory (after removing the GTO "X"). It handles the initialization and then jumps to the second part labeled "X". This second part is intended to be placed in extended memory, but can also be used in main memory.</p>
<p style="padding-left: 30px;">Start the program with <span class="hp41-key">XEQ</span> "CA". This clears the complex stack and initializes relevant flags and angular mode. The program will display the top of the complex stack (Z1), and halt at line 13 in "X" and will also return to this place after each operation. At this point, you have the option of enter an operand.</p>

<h4>Operations</h4>
<p style="padding-left: 30px;">Pressing <span class="hp41-cikey">COMPLEX</span> will activate the GETKEY keyboard. The program waits of a keystroke, and uses the key code to call the corresponding operation.</p>
<p style="padding-left: 30px;">Most operation require one or two operand from the stack. Exceptions to this rule are functions that take a real number argument (<span class="hp41-ckey">Z<sup>n</sup></span>, <span class="hp41-ckey">Z<sup>1/n</sup></span>, <span class="hp41-ckey">n<sup>Z</sup></span>, <span class="hp41-ckey">VIEWZn</span>, <span class="hp41-ckey">Z1<span class="hp41-cxy"> </span>Zn</span>) and mode switches (<span class="hp41-ckey">RECT</span>, <span class="hp41-ckey">POL</span>) and prefixes (<span class="hp41-g-key">g</span>, <span class="hp41-ckey">ARC</span>, <span class="hp41-ckey">HYP</span>).</p>
<p style="padding-left: 30px;">For the function <span class="hp41-ckey">Z<sup>1/n</sup></span>, the above is also valid, but this function does not immediately return to the normal halting point. Also, n must be a positive integer. Instead, this operation shows all the n<sup>th</sup> roots of the complex number in Z1. The ALPHA annunciator is used to indicate that more roots are to follow. When the operation is finished displaying the roots, the first root will be available as Z1 on the complex stack (and X,Y on the regular stack).</p>
<p style="padding-left: 30px;">The use of the prefixes <span class="hp41-ckey">ARC</span> and <span class="hp41-ckey">HYP</span> is similar to the use of the shift key, with flag 03 and 04 acting as the annunciator for <span class="hp41-ckey">ARC</span> and <span class="hp41-ckey">HYP</span> respectively. They can be used in any combination to denote and execute the desired function. The state of these flags only affects trigonometric operations.</p>
<p style="padding-left: 30px;">Note that operations can anywhere between 1 and take up to 6 seconds to execute.</p>

<h4>Entering operands</h4>
<p style="padding-left: 30px;">Depending on the operation, the operand can be a real or complex number. Real numbers must always be in the X register before pressing <span class="hp41-cikey">COMPLEX</span>. Complex numbers can either be entered on the regular stack as an X,Y pair, or taken from the complex stack.</p>
<p style="padding-left: 30px;">The functions <span class="hp41-ckey">VIEWZn</span> and <span class="hp41-ckey">Z1<span class="hp41-cxy"> </span>Zn</span> require an integer number between 0 and the complex stack size (default 6). The functions <span class="hp41-ckey">RECT</span> and <span class="hp41-ckey">POL</span> will also recall Z1 into the normal stack, so that it can be shown correctly in the new mode.</p>

<h4>Error handling</h4>
<p style="padding-left: 30px;">The program has no accommodation (apart from the SF 25) at line 40 in "X" to avoid error halts. This implies that attempts to divide by zero, take the log of zero, etc. will usually cause a DATA ERROR halt. Pressing <span class="hp41-cnkey">INIT</span> lets the program return to its normal halting point at line 13 in "X".</p>

<h4>Extended memory</h4>
<p style="padding-left: 30px;">As mentioned earlier, the second part of the program can be placed in extended memory. To do so, save it on 4 magnetic cards and then load it into x-memory. Note that it is not possible to change the program while in extended memory, because once the program executes in x-memory, the bytes near the <span class="hp41-key">GTO</span> and <span class="hp41-key">XEQ</span> instructions will be changed to match to the corresponding LBL address. This would cause the check sum of the fill to mismatch. For more details on running a program in extended memory, refer to the book "Extend your HP-41" [6].</p>

<h3>Examples</h3>
The following examples assume a <span class="hp41-key">ENG</span> 3, <span class="hp41-key">SF</span> 28, <span class="hp41-key">CF</span> 29 display mode.
<ol>
	<li><strong> Calculate: (2 + 3j).(7 - 6j) + (4 + 5j)</strong>
<table border="1">
<tbody>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><em>input</em></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><em>display</em></td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><span class="hp41-key">XEQ</span> "CA"</td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">0.00E0+0.00E0J</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">3 <span class="hp41-key">ENTER<span class="hp41-up-arrow"> </span></span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">3.000</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">2 <span class="hp41-cikey">COMPLEX</span> <span class="hp41-ckey">ENTER<span class="hp41-cup-arrow"> </span></span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">2.00E0+3.00E0J</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">6 <span class="hp41-key">CHS</span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""></td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><span class="hp41-key">ENTER<span class="hp41-up-arrow"> </span></span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">-6.000</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">7 <span class="hp41-cikey">COMPLEX</span> <span class="hp41-ckey">ENTER<span class="hp41-cup-arrow"> </span></span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">7.00E0-6.00E0J</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">5 <span class="hp41-key">ENTER<span class="hp41-up-arrow"> </span></span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">5.000</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">4 <span class="hp41-cikey">COMPLEX</span> <span class="hp41-ckey">+</span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">11.0E0-1.00E0J</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><span class="hp41-cikey">COMPLEX</span> <span class="hp41-ckey">*</span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">25.0E0+31.0E0J</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><span class="hp41-key">X<span class="hp41-cxy"> </span>Y</span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">31.000</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" rowspan="1" colspan="1" scope="" align="" valign=""><span class="hp41-key">X<span class="hp41-cxy"> </span>Y</span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">25.000</td>
</tr>
</tbody>
</table>
The answer is 25 + 31j</li>
	<li><strong>Calculate: (3 + 4.5j)^5</strong>
<table border="1">
<tbody>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><em>input</em></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><em>display</em></td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">4.5 <span class="hp41-key">ENTER<span class="hp41-up-arrow"> </span></span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">4.500</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">3 <span class="hp41-cikey">COMPLEX</span> <span class="hp41-ckey">ENTER<span class="hp41-cup-arrow"> </span></span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">3.00E0+4.50E0J</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">5 <span class="hp41-cikey">COMPLEX</span> <span class="hp41-ckey">Z<sup>N</sup></span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">926.E0-4.53E3J</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" rowspan="1" colspan="1" scope="" align="" valign=""><span class="hp41-key">X<span class="hp41-xy"> </span>Y</span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">-4.533 03</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" rowspan="1" colspan="1" scope="" align="" valign=""><span class="hp41-key">X<span class="hp41-xy"> </span>Y</span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">926.4 00</td>
</tr>
</tbody>
</table>
The answer is 926.4 - -4533j<span style="color: #ffffff;">:</span></li>
	<li><strong>Show what is in LASTZ1</strong>
<table border="1">
<tbody>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><em>input</em></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><em>display</em></td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><span class="hp41-cikey">COMPLEX</span> <span class="hp41-ckey">LASTZ1</span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">3.00E0+4.50E0J</td>
</tr>
</tbody>
</table>
Note that the complex number is saved, not the power 5</li>
	<li><strong>Calculate: 1 / (3, Φ40°)</strong>
<table border="1">
<tbody>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><span style="color: #000000;">input</span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><span style="color: #000000;">display</span></td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><span class="hp41-cikey">COMPLEX</span> <span class="hp41-ckey">POL</span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">5.41E0&lt;56.3E0</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">40 <span class="hp41-key">ENTER<span class="hp41-up-arrow"> </span></span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">40.00 00</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">3 <span class="hp41-cikey">COMPLEX</span> <span class="hp41-ckey">1/Z</span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">333.E-3&lt;-40.0E0</td>
</tr>
</tbody>
</table>
The answer is 0.3333 Φ -40º
<span style="color: #ffffff;">:</span></li>
	<li><strong>Calculate: asinh(8 - 5j)</strong>
<table border="1">
<tbody>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><em>input</em></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><em>display</em></td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><span class="hp41-cikey">COMPLEX</span> <span class="hp41-ckey">RECT</span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">255.E-3-214.E-3J</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">5 <span class="hp41-key">CHS</span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""></td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><span class="hp41-key">ENTER<span class="hp41-up-arrow"> </span></span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">-5.000 00</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">8 <span class="hp41-cikey">COMPLEX</span> <span class="hp41-ckey">ARC</span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""></td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><span class="hp41-ckey">HYP</span> <span class="hp41-ckey">SIN</span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">2.94E0-556.E-3J</td>
</tr>
</tbody>
</table>
The first answer is still there
<table border="1">
<tbody>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><em>input</em></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><em>display</em></td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">5 <span class="hp41-cikey">COMPLEX</span> <span class="hp41-ckey">Z1<span class="hp41-cxy"> </span>Zn</span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">94E0-556.E-3J</td>
</tr>
</tbody>
</table>
<span style="color: #ffffff;">:</span></li>
	<li><strong>Calculate the the 3 cube roots of 5 + 3j</strong>
<table border="1">
<tbody>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><em>input</em></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><em>display</em></td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">3 <span class="hp41-key">ENTER<span class="hp41-up-arrow"> </span></span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">3.000 00</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">5 <span class="hp41-cikey">COMPLEX</span> <span class="hp41-ckey">VIEW</span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">5.00E0+3.00E0J</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">3 <span class="hp41-cikey">COMPLEX</span> <span class="hp41-ckey">Z<sup>1/n</sup></span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">1.77E0+322.E-3J (alpha)</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><span class="hp41-cikey">COMPLEX</span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">-1.16E0+1.37E0J (alpha)</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><span class="hp41-cikey">COMPLEX</span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">-606.E-3-1.69E0J (alpha)</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" rowspan="1" colspan="1" scope="" align="" valign=""><span class="hp41-cikey">COMPLEX</span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">1.77E0+322.E-3J</td>
</tr>
</tbody>
</table>
<span style="color: #ffffff;">:</span></li>
	<li><strong>Calculate: csch(1 + 2j)</strong>
<table border="1">
<tbody>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><em>input</em></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><em>display</em></td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">2 <span class="hp41-key">ENTER<span class="hp41-up-arrow"> </span></span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">2.000 00</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">1 <span class="hp41-cikey">COMPLEX</span> <span class="hp41-ckey">HYP</span> <span class="hp41-ckey">CSC</span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">-489.E-3+1.40E0J</td>
</tr>
</tbody>
</table>
:</li>
	<li><strong>Calculate: ln(4 + 5j) + (3 - 2j)<sup>(2 - 3j)</sup></strong>
<table border="1">
<tbody>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><em>input</em></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><em>display</em></td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">5 <span class="hp41-key">ENTER<span class="hp41-up-arrow"> </span></span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">5.000 00</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">4 <span class="hp41-cikey">COMPLEX</span> <span class="hp41-ckey">LN</span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">1.86E0+896.E-3J</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">2 <span class="hp41-key">CHS</span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""></td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><span class="hp41-key">ENTER<span class="hp41-up-arrow"> </span></span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">-2.000 00</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">3 <span class="hp41-cikey">COMPLEX</span> <span class="hp41-ckey">ENTER<span class="hp41-cup-arrow"> </span></span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">3.00E0-2.00E0J</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">3 <span class="hp41-key">CHS</span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""></td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><span class="hp41-key">ENTER<span class="hp41-up-arrow"> </span></span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">-3.000 00</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">2 <span class="hp41-cikey">COMPLEX</span> <span class="hp41-ckey">Z2<sup>Z1</sup></span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">-1.79E-3-3.19E-3J</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><span class="hp41-cikey">COMPLEX</span> <span class="hp41-ckey">+</span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">1.85E0+893.E-3J</td>
</tr>
</tbody>
</table>
<span style="color: #ffffff;">:</span></li>
	<li><strong>Calculate: 2<sup>(3+4j)</sup></strong>
<table border="1">
<tbody>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><em>input</em></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign=""><em>display</em></td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">4 <span class="hp41-key">ENTER<span class="hp41-up-arrow"> </span></span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">4.000 00</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">3 <span class="hp41-cikey">COMPLEX</span> <span class="hp41-ckey">ENTER<span class="hp41-cup-arrow"> </span></span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">3.00E0+4.00E0J</td>
</tr>
<tr>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">2 <span class="hp41-cikey">COMPLEX</span> <span class="hp41-ckey">N<sup>Z</sup></span></td>
<td dir="" id="" lang="" style="width: 150px;" scope="" align="" valign="">-7.46E0+2.89E0J</td>
</tr>
</tbody>
</table>
The number <em>N</em> must always be the last one that is entered.
<span style="color: #ffffff;">:</span></li>
</ol>
<h3>Tweaks</h3>
<ul>
	<li>The size of the complex stack can be adjusted in line 008 of program "CA".</li>
	<li>If flag 14 is set when calling "CA", the stack will not be cleared, which may be useful if you left "CA" temporarily and want to continue. This however assumes that the data registers used for the complex stack are left undisturbed.</li>
	<li>The program uses flag 22 "numeric entry" to determine if there is a new entry in X,Y. If there is a numeric entry, the number is first pushed onto the complex stack, respecting stack lift status. This implies that you can clear flag 22 manually if you have made an accidental digit entry and still want the next operation to be performed on the current Z1.</li>
	<li>Operands that require a real number input, will always take that number from the X register, new entry or not. If stack lift is disabled, the stack will first be shifted down, so the function will be performed on Z2. This is done, so that you may have <span class="hp41-ckey">ENTER<span class="hp41-cup-arrow"> </span></span>'ed the complex number on which you want the function to be executed, and without the shift down there would be left a superfluous copy of that number on the stack.</li>
</ul>
<h3>Program listing</h3>
This program consists of two parts
<ol>
	<li>Requires
<ul>
	<li>X-Functions module on the HP-41cv</li>
</ul>
</li>
	<li>Part 1 should be placed in main memory and is available as
<ul>
	<li><a href="http://coertvonk.com/wp-content/hp-41/ca300.txt">source code</a></li>
	<li><a href="http://coertvonk.com/wp-content/hp-41/ca300.raw">raw code</a> for the V41 emulator</li>
	<li><a href="http://coertvonk.com/wp-content/hp-41/ca300.pdf">bar code</a> for the HP Wand (HP82153A)</li>
</ul>
</li>
	<li>Part 2, can be placed in either main or extended memory. When placed in extended memory, the instruction GTO "X" should be removed. This part is available as
<ul>
	<li><a href="http://coertvonk.com/wp-content/hp-41/ca300xm.txt">source code</a></li>
	<li><a href="http://coertvonk.com/wp-content/hp-41/ca300xm.raw">raw code</a> for the V41 emulator</li>
	<li><a href="http://coertvonk.com/wp-content/hp-41/ca300xm.pdf">bar code</a> for the HP Wand</li>
</ul>
</li>
	<li>The keyboard overlay is available as
<ul>
	<li><a href="http://coertvonk.com/wp-content/hp-41/ca300.jpg">image</a>, scaled down by 98% so when printed on 4×6", it typically comes out as true-size.</li>
	<li><a href="http://coertvonk.com/wp-content/hp-41/ca300inv.jpg">inverted image</a>, scaled down by 98% so when printed on 4×6", it typically comes out as true-size.</li>
</ul>
</li>
</ol>
<h4>part 1</h4>
<pre class="brush: hpfocal; gutter: false; toolbar: off; tab-size: 8">; The program consists of two parts.  The part listed below should be in main
; memory.  The other part (listed in CA300xm.txt) can be placed in either main
; or extended memory.  When placed in extended memory, THE INSTRUCTION GTO "X"
; SHOULD BE REMOVED.
;
; Before placing the second part in XM, the program should be PACKed
; and run in RAM.  This should be done to compile all the GTO's and
; XEQ's.  If this is not done one will see CHKSUM ERR when trying to
; download this program into RAM. [9]

1	LBL "CA"
2	CF 03		; clear prefix flags (ARC, HYP)
3	CF 04
4	RAD
5	FS? 14		; if the "do not clear stack" flag is set
6	GTO 00		;   then jump to LBL 00,
7	SIZE?		;   else if needed extended the # of data registers
8	6
9	STO 00
10	ST+ X
11	3
12	+
13	X&gt;Y?
14	PSIZE
15	CLX
16	STO 01		; clear LASTZ
17	STO 02
18	LBL 00
19	GTO "X"		 ; REMOVE THIS LINE when LBL "X" in X-memory !!
20	"\8D\BE"
21	RCL M
22	STO b		; jump to "X" in extended memory at address 0x8DBE
22	END</pre>
<h4>part 2</h4>
<ul>
	<li>Stack and alpha registers:
<ul>
	<li>The program uses all registers</li>
</ul>
</li>
	<li>Data registers:
<ul>
	<li>R00, depth of complex stack (default value is 6)</li>
	<li>R01, real part of LASTZ1</li>
	<li>R02, imaginary part of LASTZ1</li>
	<li>R03, real part of complex number Z1</li>
	<li>R04, imaginary part of complex number Z1</li>
	<li>:</li>
	<li>R13, real part of complex number Z6</li>
	<li>R14, imaginary part of complex number Z6</li>
	<li>Note that the internal format of the complex stack is always rectangular.</li>
</ul>
</li>
	<li>Flags:
<ul>
	<li>flag 00, "POL", when set indicates Polar notation (POL), otherwise rectangular notation (RECT)</li>
	<li>flag 02, "no stack lift", when set disables the stack lift</li>
	<li>flag 03, "ARC", when set indicates inverse trigonometric operation (ARC)</li>
	<li>flag 04, "HYP", when set indicates hyperbolic operation (HYP)</li>
	<li>flag 10, "alt operation", allows similar operations to reuse code</li>
	<li>flag 14, "clipped corner", is used for all but magnetic cards. During initialization it indicates "do not clear stack"; during keyboard fetching it indicates more key strokes need to follow; and during triogonometry operations, indicates inverse operation.</li>
	<li>flag 22, "keyboard input", set when numeric input is entered from the keyboard, cleared on power cycle. [7]</li>
	<li>flag 25, "ignore error", when set, ignores improper operations (like div by zero) or range errors.</li>
	<li>flag 30, used for "always false" test. Used to negate prior test. [7]</li>
	<li>flag 47, "shift set", used internally in shifted operations.</li>
	<li>flag 44-46, cleared as a side effect of showing the "shift" annunciator</li>
	<li>flag 48-55, cleared as a side effect of showing the "shift" annunciator</li>
</ul>
</li>
	<li>Legend:
<ul>
	<li>(x + y.j), complex number held on the regular stack</li>
	<li>X register holds the real part (x)</li>
	<li>Y register holds the imaginary part (y)</li>
	<li>(M . e^j.phi), complex number in polar notation</li>
</ul>
</li>
</ul>
<pre class="brush: hpfocal; gutter: false; toolbar: off; tab-size: 8">; INITIALIZE AND MAIN LOOP
;
; An infinite loop to fetch a keystroke identifying the operation to be
; executed.  The "shift" key causes the "shift" status to be toggled, for all
; other keys the LBL that matches the key code will be called (or keycode+5 if
; "shift" was active).
;
; called      : from "CA" in main memory, or
;               in response to [CINIT] keycode (labeled [ON] on keyboard)
; on entry    : when flag 14 is set, the complex stack will not be cleared
; on exit     : value of Z1 shown.  Also available as X,Y.

1	LBL "X"
2	RDN
3	FC?C 14		; if the "do not clear stack" flag is not set
4	XEQ 48		;   then clear the complex stack

5	LBL 01		; [CINIT] operation
6	CF 10
7	CF 22
8	CF 25
9	FS? 00
10	R-P
11	XEQ 10		; display complex number (x + y.j)
12	STOP
13	ENTER^
14	LBL 02
15	CLX
16	GETKEY		; wait for an operation keycode
17	X=0?
18	GTO 02
19	31
20	X#Y?		; if not the "shift" key
21	GTO 00		;   then handle that operation
22	R^  		;   else update the shift annunciator
23	R^
24	"\01\00"
25	FS? 47
26	CLA
27	RCLFLAG
28	ASTO d
29	STOFLAG
30	AOFF
31	GTO 02

32	LBL 00	   	; handle operation associated with a keycode
31	CLX
34	5
35	FC? 47		; if "shift was active"
36	CLX 		;   then increment key code by 5
37	+
38	RDN
39	CLD
40	SF 25
41	XEQ IND T	; call the corresponding operation
42	FC?C 14
43	GTO 01
44	ENTER^
45	GTO 02

; TOGGLE [ARC] MODIFIER, for ASIN, ACOS, ATAN

46	LBL 11		; [ARC], key label [sigma+]
47	FC?C 03
48	SF 03
49	SF 14		; indicate "more key strokes to follow"
50	RTN

; TOGGLE [HYP] MODIFIER, for SINH, COSH and TANH

51	LBL 16		; [HYP], key label [sigma-]
52	FC?C 04
53	SF 04
54	SF 14		; indicate "more key strokes to follow"
55	RTN

; SWITCH BETWEEN POLAR AND RECTANGULAR NOTATION

56	LBL 68		; [RECT], key label [P&gt;R]
57	CF 00
58	GTO 00
59	LBL 69		; [POL], key label [R&gt;P]
60	SF 00
61	LBL 00
62	RCL 04		; get Z1 from the complex stack as (x + y.j)
63	RCL 03
64	RTN

; COMPLEX RECIPROCAL (1/Z)
;
; on entry : Z in X,Y registers in the form (x + y.j)
; on exit  : the result is stored as Z1 on the complex stack
;    	     the result is stored in X,Y in the form (x + y.j)
;	     LASTZ1 holds a copy of the operation operand Z

65	LBL 12	    	; [1/Z] operation

66	XEQ 09		; push (x + y.j) onto complex stack and update LASTZ1
67	XEQ 31		; compute (x + j.y) = 1 / (x + j.y)
68	GTO 03		; copy (x + y.j) to complex stack, and return

; COMPLEX ENTER^
;
; on entry : Z in X,Y registers in the form (x + y.j)
; on exit  : Z is pushed up the complex stack as Z1 and Z2
;    	     Z is X,Y in the form (x + y.j)
;    	     LASTZ1 is unchanged

69	LBL 41	        ; [CENTER^] operation

70	XEQ 04		; push (x + y.j) onto complex stack
71	XEQ 11		; move complex stack up, Z1 &gt; Z2 &gt; Z3 &gt; Z4 &gt; Z5 &gt; Z6
72	SF 02		; "no stack lift"
73	RTN

; COMPLEX CLEAR STACK
;
; on entry : n/a
; on exit  : Z1..Z6 on the complex stack are set to (0 + 0j)
;    	     LASTZ1 is unchanged

74	LBL 48	        ; [CCLST] operation

75	RCL 00
76	ISG X
77	""
78	ST+ X
79	 E3
80	/
81	3
82	+
83	.
84	LBL 36
85	STO IND Y
86	ISG Y
87	GTO 36
88	CF 02		; no "no stack lift"
89	CLST
90	RTN

; COMPLEX CHANGE SIGN AND COMPLEX CONJUGATE (Complement)
;
;     -(x + y.j) = -x - y.j  (change sign)
;     (x + y.j)* =  x - y.j  (conjugate)
;
; on entry : Z in X,Y registers in the form (x + y.j)
; on exit  : the result is stored as Z1 on the complex stack
;    	     the result is stored in X,Y in the form (x + y.j)
;	     LASTZ1 holds a copy of the operation operand Z

91	LBL 42		; [CHSZ] operation
92	SF 10
93	LBL 47		; [COMPLZ] operation

94	XEQ 04		; push (x + y.j) onto complex stack
95	FS? 10
96	CHS
97	X&lt;&gt;Y
98	CHS
99	X&lt;&gt;Y
100	GTO 03		; copy (x + y.j) to complex stack, and return

; CLEAR Z1
;
; on entry : Z in X,Y registers in the form (x + y.j)
; on exit  : Z is pushed up the complex stack as Z1 and Z2
;    	     Z is X,Y in the form (x + y.j)
;    	     LASTZ1 is unchanged

101	LBL 49	        ; [CLZ1] operation

102	XEQ 04		; push (x + y.j) onto complex stack
103	CLST
104	SF 02		; "no stack lift"
105	GTO 03		; copy (x + y.j) to complex stack, and return

; LAST Z1
;
; on entry : n/a
; on exit  : the operand from the last numeric operation (except CHSZ)
;              is pushed onto the complex stack
;    	     the operand from the last numeric operation (except CHSZ)
;              is stored in X,Y in the form (x + y.j)

106	LBL 88 	  	; [LASTZ1] operation

107	FS? 02
108	FS? 22		; if "no stack lift" or "input from keyboard"
109	XEQ 41		;   then perform ENTER^
110	CF 02
111	RCL 02		; LASTZ1
112	RCL 01
113	GTO 03		; copy (x + y.j) to complex stack, and return

; COMPLEX ADDITION AND SUBTRACTION
;
;     (z + t.j) + (x + y.j) = (x + z) + j.(y + t)
;     (z + t.j) - (x + y.j) = (x - z) + j.(y - t)
;
; on entry : if number was entered on the keyboard,
;              then (x + y.j) as entered in X,Y registers, and
;                   (z + t.j) from Z1 on the complex stack
;              else (x + y.j) from Z1 on the complex stack, and
;                   (z + t.j) from Z2 on the complex stack
; on exit  : the result is stored as Z1 on the complex stack
;    	     the result is stored in X,Y in the form (x + y.j)
;	     LASTZ1 holds a copy of (x + y.j)

114	LBL 51		; [C-] operation
115	SF 10
116	LBL 61		; [C+] operation

117	XEQ 07		; get two operands, as (x + j.y) and (z + j.t)
118	FS? 10
119	CHS
120	X&lt;&gt;Y
121	FS? 10
122	CHS
123	ST+ T
124	RDN
125	+
126	GTO 03		; copy (x + y.j) to complex stack, and return

; COMPLEX MULTIPLICATION AND DIVISION
;
;     Z2 * Z1 = (re1 + j.im1) * (re2 + j.im2) =
;             = (re1.re2 - im1.im2 ) + j.(im1.re1 + re1.im2)
;
;     Z2 / Z1 = Z2 * 1/Z1

127	LBL 81		; [C/] operation
128	SF 10
129	LBL 71		; [C*] operation

130	XEQ 07		; get two operands, as (x + j.y) and (z + j.t)
131	FS? 10		; if division
132	XEQ 31		;   then compute (x + j.y) = 1 / (x + j.y)
133	XEQ 00		; compute (x + j.y) * ( z + j.t)
134	GTO 03		; copy (x + y.j) to complex stack, and return

; COMPLEX POWER OF A COMPLEX NUMBER
;
;           (x+y.j)      z    -t.phi1    j.(z.phi1 + t.ln(r1))
;     (z+t.j)       =  r1  . e        . e
;
;   where:
;         r1   = sqrt(x^2+y^2)
;         phi1 = .... x + y.j ....????

135	LBL 17		; [Z2^Z1] operation

136	XEQ 07		; get two operands, as (x + j.y) and (z + j.t)
137	R^
138	R^
139	RAD
140	R-P
141	LN
142	XEQ 00		; compute (x + j.y) * ( z + j.t)
143	E^X
144	P-R
145	GTO 03		; copy (x + y.j) to complex stack, and return

; COMPLEX PARALLEL CIRCUIT, useful in network theory
;
;            Z1 . Z2
; Z1 // Z2 = -------    {for |Z1+Z2| &lt;&gt; 0}
;            Z1 + Z2

146	LBL 32		; [CPAR] operation
147	XEQ 07		; get two operands, as (x + j.y) and (z + j.t)
148	XEQ 31		; compute 1 / ( x + j.y)
149	R^
150	R^
151	XEQ 31		; compute 1 / ( x + j.y)
152	X&lt;&gt;Y
153	ST+ T
154	RDN
155	+
156	XEQ 31		; compute 1 / ( x + j.y)

; REPLACE Z1 with (x + y.j) ON COMPLEX STACK

157	LBL 03	    	; [PRGM] keycode
158	DEG		; switch to DEG mode
159	STO 03
160	X&lt;&gt;Y
161	STO 04
162	X&lt;&gt;Y
163	RTN

; MULTIPLY TWO COMPLEX NUMBERS subroutine
;
;     (x + y.j) * (z + t.j) = (x + j.y) * (z + j.im2) =
;                           = (x.z - y.t ) + j.(y.x + x.t)

164	LBL 00
165	STO L
166	R^
167	ST* L
168	X&lt;&gt; Z
169	ST* Z
170	R^
171	ST* Y
172	ST* Z
173	X&lt;&gt; L
174	+
175	X&lt;&gt; Z
176	-
177	RTN

; COMPLEX COMMON (base 10) and NATURAL (base e) LOGARITHM
;
;     ln(x + y.j) = ln(r) + j.phi
;
;     Z1
;       log(Z2) = ln(Z2) / ln(Z1)

178	LBL 14		; [LOG(Z)] operation
179	XEQ 08		; get operand, as (x + j.y) and update LASTZ
180	LN  		; x=ln(M1), y=phi1
181	GTO 00

182	LBL 15		; [LN(Z)] operation
183	XEQ 09		; push (x + y.j) onto complex stack and update LASTZ
184	 E		; x=1

185	LBL 00
186	RDN
187	RAD
188	R-P
189	LN
190	R^
191	ST/ Z
192	/
193	GTO 03		; copy (x + y.j) to complex stack, and return

; COMPLEX COMMON (base 10) and NATURAL (base e) EXPONENTIAL
;
;     (x + j.y)    x              x
;    e          = e .sin(y) + j.e .cos(y)

194	LBL 19		; [n^Z] operation
195	XEQ 08		; get operand, as (x + j.y) and update LASTZ
196	LN
197	GTO 00		; reuse part of  [E^Z] operation

198	LBL 20		; [E^Z] operation
199	XEQ 09		; push (x + y.j) onto complex stack and update LASTZ
200	 E

201	LBL 00
202	ST* Z
203	*
204	E^X
205	RAD
206	P-R
207	GTO 03		; copy (x + y.j) to complex stack, and return

; COMPLEX EXPONENTIATION WITH REAL EXPONENT n

208	LBL 18		; [Z^n] operation

209	XEQ 08		; get operand, as (x + j.y) and update LASTZ
210	RDN
211	R-P
212	R^
213	ST* Z
214	Y^X
215	P-R
216	GTO 03		; copy (x + y.j) to complex stack, and return

; COMPLEX ROOT OF REAL NUMBER n
;        __
;     Z1/         1/Z1
;     \/ Z2   = Z2
;        __
;     n /        1/n   j.(phi/n)
;     \/ Z    = M   . e

217	LBL 13		; [Z^1/n] operation

218	XEQ 08		; get operand, as (x + j.y) and update LASTZ
219	RDN
220	R-P
221	R^
222	1/X
223	Y^X
224	360
225	R^
226	ST/ T
227	ST/ Y
228	R^
229	R^
230	LBL 05
231	FC? 00
232	P-R
233	XEQ 10		; display complex number (x + y.j)
234	AON
235	STOP
236	FC? 00
237	R-P
238	R^
239	ST+ Z
240	RDN
241	DSE Z
242	GTO 05		; loop back to LBL 05
243	P-R
244	AOFF
245	GTO 03		; copy (x + y.j) to complex stack, and return

; COMPLEX SINE, COSECANT, COSINE AND SECANT
;
;     sin( x + j.y) = sin(x).cosh(y) + j.cos(x).sinh(y)
;     cos( x + j.y) = cos(x).cosh(y) - j.sin(x).sinh(y)
;     sinh(x + j.y) = cos(y).sinh(x) + j.sin(y).cosh(x)
;     cosh(x + j.y) = cos(y).cosh(x) + j.sin(y).sinh(x)
;     csc(x + j.y)  = 1 / sin( x + j.y)
;     sec(x + j.y)  = 1 / cos( x + j.y)
;     csch(x + j.y) = 1 / sinh(x + j.y)
;     sech(x + j.y) = 1 / cosh(x + j.y)
;
; Flags used:
;     flag 04, indicates [HYP]
;     flag 10, indicates [SIN], otherwise [COS]
;     flag 14, indicates inverse operation (CSC and COS, aka SIN^-1 and COS^-1)
;
; Reference:
;     http://en.wikipedia.org/wiki/Complex_number#Complex_analysis

246	LBL 28		; [CSC(Z)] operation
247	SF 14

248	LBL 23		; [SIN(Z)] operation
249	SF 10

250	LBL 29		; [SEC(Z)] operation
251	FC? 10
252	SF 14

253	LBL 24		; [COS(Z)] operation

254	XEQ 09		; push (x + y.j) onto complex stack and update LASTZ
255	FS?C 03		; ARC?
256	GTO 13
257	XEQ 00		; calculate cos/sin/cosh/sinh
258	ST* T
259	RDN
260	*
261	CHS
262	FC? 04		; HYP?
263	FS? 10		; SIN?
264	CHS
265	FC?C 04		; HYP?
266	FC? 10		; COS?
267	X&lt;&gt;Y
268	FS?C 14		; inverse operation?
269	XEQ 31		;   then compute Z1 = 1 / Z1
270	GTO 03		; copy (x + y.j) to complex stack, and return

; COMPLEX TANGENT AND COTANGENT, doesn't support ARC or HYP variations
;
;     tan(x + j.y) = sin(2.x)  / ( cosh(2.y) + cos(2.x) ) +
;                    sinh(2.y) / ( cosh(2.y) + cos(2.x) ) . j
;     cot(Z) = 1 / tan(Z)
;
; Flags used:
;     F03 indicates [ARC]
;     F04 indicates [HYP]
;     F14 indicates inverse operation (COT aka TAN^-1]

271	LBL 30		; [COT(Z)] operation
272	SF 14
273	LBL 25		; [TAN(Z)] operation
274	FS?C 03		; ARC?
275	GTO 02		;   UNSUPPORTED, jump back to main routine
276	FS?C 04		; HYP?
277	GTO 02		;   UNSUPPORTED, jump back to main routine
278	XEQ 09		; push (x + y.j) onto complex stack and update LASTZ
279	2		; multiply x and y by 2
280	ST* Z
281	*
282	XEQ 00		; calculate cos/sin/cosh/sinh (F04=0, F10=0)
283	R^
284	+
285	ST/ Z
286	/   		; answers is now as (x + y.j)
287	FS?C 14		; inverse operation?
288	XEQ 31		;   then compute Z1 = 1 / Z1
289	GTO 03		; copy (x + y.j) to complex stack, and return

; TRIGONOMIC OPERATIONS HELPER subroutine
;
; Call with:
;   complex number on the stack as (x + y.j).
;   F04 indicates [HYP]
;   F10 indicates [SIN], otherwise [COS]
;
; This operation returns:
;
;           | [HYP]    [HYP]
;	    | [SIN]    [COS]	[SIN]	[COS]
;     ------+----------------------------------
; re  y-reg | sin(y)   sin(y)   sin(x)  sin(x)
; re  z-reg | cosh(x)  sinh(x)  cosh(y) sinh(y)
;     ------+----------------------------------
; im  x-reg | cos(y)   cos(y)   cos(x)  cos(x)
; im  t-reg | sinh(x)  cosh(x)  sinh(y) cosh(y)
;
;            x     -x      2.x
;           e  -  e       e    -  1                    1
; sinh(x) = ---------  =  ---------  ,    csch(x) = -------
;                              x                    sinh(x)
;              2            2.e
;
;            x     -x      2.x
;           e  +  e       e    +  1                   1
; cosh(x) = ---------  =  ---------  ,    sech(x) = -------
;                              x                    cosh(x)
;               2           2.e
; Reference:
;     http://en.wikipedia.org/wiki/Hyperbolic_trig_operations

290	LBL 00
291	FS? 04		; HYP?
292	X&lt;&gt;Y		;
293	2
294	RCL Z
295	ST+ X
296	E^X-1
297	ST+ Y
298	R^
299	E^X
300	ST+ X
301	ST/ Z
302	/
303	FS? 10		; SIN? (not COS)
304	X&lt;&gt;Y		;
305	R^
306	RAD
307	SIN
308	R^
309	COS
310	RTN

; INVERSE TRIGONOMIC OPERATIONS, ARC and HYP-ARC
;
;     arcsin(x + y.j) = arcsin(b) + j.sign(y).ln(a + sqrt(a^2-1)
;     arccos(x + y.j) = arccos(b) - j.sign(y).ln(a + sqrt(a^2-1))
;     arccsc(Z)  =    arcsin(1/Z)
;     arcsec(Z)  =    arccos(1/Z)
;     arcsinh(Z) = -j.arcsin(j.Z)
;     arccosh(Z) =  j.arccos(Z)
;     arccsch(Z) =  j.arccsc(j.Z)
;     arcsech(Z) =  j.arcsec(Z)
;   where
;     a = ( sqrt( (x+1)^2 + y^2 ) + sqrt( (x-1)^2 + y^2) ) / 2
;     b = ( sqrt( (x+1)^2 + y^2 ) - sqrt( (x-1)^2 + y^2) ) / 2
;     sign(y) returns 1 when y&gt;=0, othewise returns -1
;
; Flags used:
;     F04 indicates [HYP]
;     F10 indicates [SIN], otherwise [COS]
;     F14 indicates inverse operation (CSC and COS, aka SIN^-1 and COS^-1]
;
; Reference:
;     http://en.wikipedia.org/wiki/Inverse_trigonometric_operation

311	LBL 13
312	FS?C 14		; inverse operation?
313	XEQ 31		; compute Z1 = 1 / Z1
314	FS? 04		; HYP flag
315	FC? 10
316	GTO 00
317	X&lt;&gt;Y
318	CHS
319	LBL 00		; entered with Z1 as (x + y.j)
320	RCL X
321	 E
322	ST- Z
323	+
324	X^2
325	X&lt;&gt;Y
326	X^2
327	X&lt;&gt; Z
328	X^2
329	ST+ Z
330	+
331	SQRT
332	STO Z
333	X&lt;&gt;Y
334	SQRT
335	ST- Z
336	+
337	2
338	ST/ Z
339	/   		; X holds a;  Y holds b; Z holds y
340	ENTER^
341	X^2
342	SIGN
343	ST- L
344	X&lt;&gt; L
345	SQRT
346	+
347	LN
348	R^
349	SIGN
350	*
351	FC? 10
352	CHS
353	X&lt;&gt;Y
354	RAD
355	FS? 10
356	ASIN
357	FC? 10
358	ACOS		; Z1 (x + y.j) now holds the answer to simple ARCSIN or ARCCOS
359	FC?C 04
360	GTO 03		; we're done for non-HYP operations;
361	FS? 10		; proceed for for HYP or inverse-HYP
362	CHS
363	X&lt;&gt;Y
364	FC? 10
365	CHS
366	GTO 03		; copy (x + y.j) to complex stack, and return

; VIEW COMPLEX NUMBER Zn

367	LBL 89		; [VIEWZn] operation
368	RCL 00
369	X&lt;Y?		; if n &gt; complex stack depth, recall Z1 and return
370	GTO 14		; get (x + y.j) from complex stack, and return
371	SIGN
372	+
373	ST+ X
374	SIGN
375	CLX
376	RCL IND L	; recall imaginary part of Zn
377	DSE L
378	RCL IND L	; recall real part of Zn
379	FS? 00		; if notation selected
380	R-P 		;   then convert to polar notation
381	XEQ 10		; display complex number (x + y.j)
382	PSE 		; pause, but allow number input
383	GTO 14		; get (x + y.j) from complex stack, and return

; EXCHANGE COMPLEX STACK REGISTERS

384	LBL 21		; [Z1&lt;&gt;Z2] operation
385	XEQ 04		; push (x + y.j) onto complex stack
386	2
387	LBL 26		; [Z1&lt;&gt;Zn] operation
388	RCL 00
389	X&lt;Y?
390	GTO 14		; get (x + y.j) from complex stack, and return
391	X&lt;&gt;Y
392	ST+ X
393	1.003002	; X register holds 1.003002; Y register holds 2.n,
394	CF 02		; no "no stack lift"
395	GTO 00		; perform register swap and return

; COMPLEX STACK ROLL, up or down
;
; Does not roll around
; Uses block rotate trick form PPC Journal V10N3p15a

396	LBL 22		; [CR^] operation
397	SF 10
398	LBL 27		; [CRDN] operation

399	XEQ 04		; push (x + y.j) onto complex stack
400	3
401	ENTER^
402	5
403	FS? 10		; CR^?
404	X&lt;&gt;Y
405	RCL 00		; complex stack depth (csdepth)
406	DSE X
407	ST+ X
408	 E3
409	ST/ Z
410	X^2
411	/
412	+		; for CRDN
413	LBL 00
414	+
415	REGSWAP		; register swap for sss.dddnnn

; GET (x + y.j) FROM COMPLEX STACK

416	LBL 14
417	RCL 04		; imaginary part of Z1
418	RCL 03		; real part of Z1
419	RTN

; COMPLEX 1/Z1
;
; Formula:
;      1             x                 y
;    -------  =  ---------  -  j . ---------
;    x + y.j     x^2 + y^2         x^2 + y^2
;
; doesn't disturb Z and T
420	LBL 31
421	X^2
422	X&lt;&gt;Y
423	STO M
424	ST* X
425	ST+ Y
426	X&lt;&gt; M
427	CHS
428	X&lt;&gt;Y
429	ST/ Y
430	ST/ L
431	X&lt;&gt; L
432	RTN

; GET TWO OPERANDS as (x + j.y) and (z + j.t)
; 1st operand is from keyboard, otherwise from Z1
; stack management subroutine for operations with two complex number operands

433	LBL 07
434	XEQ 06		; get one operand (x + y.j) from keyboard input
                        ;  otherwise from Z1 on the complex stack
435	FC?C 02
436	FC? 22		; if "no stack lift" or no "input from keyboard"
437	XEQ 12		;   then move complex stack down
438	RCL 04		; get operand (z + t.j) from Z1 on the complex stack
439	RCL 03
440	R^
441	R^
442	GTO 00

; GET OPERAND, as (x + j.y) and UPDATE LASTZ
; stack management subroutine for operations with one complex and one real number operand

443	LBL 08	   	; called with n in register X
444	FS?C 02		; if "no stack lift"
445	XEQ 12		;   then move complex stack down, Z1 &lt; Z2 &lt; Z3 &lt; Z4 &lt; Z5 &lt; Z6
446	RCL 04		; copy Z1 to LASTZ
447	STO 02
448	RCL 03
449	STO 01
450	RCL Z		; n in register X, complex operand as (y + z.j)
451	RTN

; PUSH (x + y.j) ONTO COMPLEX STACK and UPDATE LASTZ
; stack management subroutine for operations with one complex number operand

452	LBL 09
453	XEQ 04		; push (x + y.j) onto complex stack
454	LBL 00
455	STO 01		; copy to LASTZ1
456	X&lt;&gt;Y
457	STO 02
458	X&lt;&gt;Y
459	RTN

; COMPLEX ALPHA/ALPHA ROUTINE

460	LBL 04	      	; [CVIEW] key code [ALPHA]
461	FC?C 02
462	FC? 22
463	FS? 30		; if both "no stack lift" and "keyboard input"
464	XEQ 11		;   then move complex stack up, Z1 &gt; Z2 &gt; Z3 &gt; Z4 &gt; Z5 &gt; Z6

465	XEQ 06		; get one operand
466	STO 03
467	X&lt;&gt;Y
468	STO 04
469	X&lt;&gt;Y
470	RTN

; GET ONE OPERAND (x + y.j)
; from keyboard input, otherwise from Z1 on the complex stack 

471	LBL 06
472	FS? 00		; if in polar mode, then convert it to Rect
473	FC? 22
474	FS? 30
475	P-R
476	FS? 22		; keyboard input?
477	RTN
478	RCL 04
479	RCL 03
480	RTN

; DISPLAY
; in rectangular mode "x + y.j", or in polar mode "x &lt;y" with the
; angle in degrees
; subroutine that views both parts of the complex number in X and Y in
; condensed format in the display, without disturbing Z, T or the display
; mode.  ENG 2 was chosen because, to display complex numbers in analog
; electronics.

481	LBL 10		; Z1 = x + j.y
482	SIGN		; save X in LASTX
483	RDN
484	CLA
485	RCLFLAG		; save flags
486	ENG 2
487	ARCL L
488	RDN
489	FS? 00		; in Rectangular notation append real part,
490	GTO 00		; and '+' sign if imaginary part is positive
491	X&lt;0?
492	GTO 00
493	&gt;"+"
494	LBL 00
495	R^
496	FS? 00		; for Polar notation, append angle ('&lt;') sign
497	&gt;"&lt;"
498	ARCL Y
499	FC? 00
500	&gt;"J"		; in Rectangular notation append 'J' char
501	AVIEW
502	STOFLAG		; restore flags
503	X&lt;&gt; L		; restore X from LASTX
504	RTN

; ROLL THE COMPLEX STACK, by one position up or down
; subroutine to shift the stack up or down by one complex register
;
; Does not roll around like RDN or R^
; Does not enter or retrieve data.
;
; Example:
;                  | stack lift | stack drop
;    --------------+------------+------------
;    Z6    6 + 6j  |   5 + 5j   |   6 + 6j
;    Z5    5 + 5j  |   4 + 4j   |   6 + 6j
;    Z4    4 + 4j  |   3 + 3j   |   5 + 5j
;    Z3    3 + 3j  |   2 + 2j   |   4 + 4j
;    Z2    2 + 2j  |   1 + 1j   |   3 + 3j
;    Z1    1 + 1j  |   1 + 1j   |   2 + 2j

505	LBL 11		; stack lift, Z1 &gt; Z2 &gt; Z3 &gt; Z4 &gt; Z5 &gt; Z6
506	3.005		;   typically when a new number is moved into Z1
507	GTO 00
508	LBL 12		; stack drop, Z1 &lt; Z2 &lt; Z3 &lt; Z4 &lt; Z5 &lt; Z6
509	5.003		;   typically when a operation combines Z1 and Z2
510	LBL 00
511	SIGN
512	RCL 00		; complex stack depth (csdepth)
513	X&lt;&gt;Y
514	ST- Y
515	RDN
516	ST+ X
517	 E6
518	ST/ Y
519	X&lt;&gt; L
520	+		; register X is in sss.dddnnn format
521	REGMOVE		; copies 2*(csdepth-1) registers from sss to ddd
522	RDN
523	END</pre>
<h3>References</h3>
<table>
<tbody>
<tr>
<td dir="" id="" lang="" scope="" align="" valign="top">[1]</td>
<td dir="" id="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top"></td>
<td dir="" id="" lang="" scope="" align="" valign="top">COMPLEX ARITHMETIC
Frans de Vries, May 1985
<a href="http://www.hp41.org/LibView.cfm?Command=Image&amp;ItemID=229&amp;FileID=6443">PPC Journal V12N5, page 4-9</a></td>
</tr>
<tr>
<td dir="" id="" lang="" scope="" align="" valign="top">[2]</td>
<td dir="" id="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top"></td>
<td dir="" id="" lang="" scope="" align="" valign="top">SCIENTIFIC ANALYSIS IN THE POCKET CALCULATOR, chapter 3-8, appendix 4
Jon M. Smith, 1975
New York, John Wiley &amp; sons</td>
</tr>
<tr>
<td dir="" id="" lang="" scope="" align="" valign="top">[3]</td>
<td dir="" id="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top"></td>
<td dir="" id="" lang="" scope="" align="" valign="top">LAPLACE-, FOURIER- EN Z-TRANSFORMATIE, chapter 1
Ir. A. van der Knaap, 1983
HTS Dordrecht, the Netherlands</td>
</tr>
<tr>
<td dir="" id="" lang="" scope="" align="" valign="top">[4]</td>
<td dir="" id="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top"></td>
<td dir="" id="" lang="" scope="" align="" valign="top">COMPLEXE REKENWIJZE OP DE STANDAARD HP41CV
Coert Vonk, 1986
HP Users Nieuws #8 June 1986 pg. 24-29</td>
</tr>
<tr>
<td dir="" id="" lang="" scope="" align="" valign="top">[5]</td>
<td dir="" id="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top"></td>
<td dir="" id="" lang="" scope="" align="" valign="top">MATHEMATICAL TABLES AND FORMULAS, formula 26 pg. 242
R.D. Carmichael and E.R. Smith
Dover Publications Inc, New York</td>
</tr>
<tr>
<td dir="" id="" lang="" scope="" align="" valign="top">[6]</td>
<td dir="" id="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top"></td>
<td dir="" id="" lang="" scope="" align="" valign="top">EXTEND YOUR HP-41C, page 558
Wlodek Mier-Jedrzejowicz, 1986
<a href="http://www.hpmuseum.org/software/swcd.htm">Synthetix</a></td>
</tr>
<tr>
<td dir="" id="" lang="" scope="" align="" valign="top">[7]</td>
<td dir="" id="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top"></td>
<td dir="" id="" lang="" scope="" align="" valign="top">HP-41C FLAGS, PART 1
<a href="http://www.hpmuseum.net/pdf/KeyNotes_1980_Sep_Vol4No3_13pages_OCR.pdf">HP Key Notes V4N3, 1980</a></td>
</tr>
<tr>
<td dir="" id="" lang="" scope="" align="" valign="top">[8]</td>
<td dir="" id="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top"></td>
<td dir="" id="" lang="" scope="" align="" valign="top">COMPLEX FUNCTIONS FOR THE HP-41
Jean-Marc Baillard, 2004
<a href="http://www.hpmuseum.org/software/41/41cmpxf.htm">see article</a></td>
</tr>
<tr>
<td dir="" id="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top">[9]</td>
<td dir="" id="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top"></td>
<td dir="" id="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top">RUNNING PRGMS IN X-MEMORY
Philip Karras, April 1982
<a href="http://www.hp41.org/LibView.cfm?Command=Image&amp;FileID=5144">PPC Journal, V9N3, pg.26</a></td>
</tr>
</tbody>
</table>]]></description>
		<wfw:commentRss>http://www.coertvonk.com/technology/hp41/complex-arithmetic-xmem-4426/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<enclosure url="http://www.coertvonk.com/wp-content/uploads/complex-arithmetic-xmem.png" length="154278" type="image/jpg" />
<media:content xmlns:media="http://search.yahoo.com/mrss/" url="http://www.coertvonk.com/wp-content/uploads/complex-arithmetic-xmem.png" width="300" height="300" medium="image" type="image/jpeg">
<media:copyright>Coert Vonk</media:copyright>
</media:content>
	</item>
		<item>
		<title>Polynomial Factorization (to 5th degree) for HP-41cv/cx</title>
		<link>http://www.coertvonk.com/technology/hp41/polynomial-factorization-4461</link>
		<comments>http://www.coertvonk.com/technology/hp41/polynomial-factorization-4461#comments</comments>
		<pubDate>Tue, 28 Feb 2012 22:56:50 +0000</pubDate>
		<dc:creator>Coert</dc:creator>
				<category><![CDATA[Math (HP-41)]]></category>

		<guid isPermaLink="false">http://www.coertvonk.com/?p=4461</guid>
		<description><![CDATA[<div><img width="150" height="150" src="http://www.coertvonk.com/wp-content/uploads/hp41-150x150.png" class="attachment-post-thumbnail wp-post-image" alt="hp41" /></div>This program calculates the roots of a polynomial up to the 5<sup>th</sup> degree (quintic).
<h3>History</h3>
Around 1985, Michiel Niemeijer published a similar program for the HP-41 in the Dutch publication HP User News [1].  I am not sure if that was the source.  My changes were aimed at making the user experience more intuitive. This article lists my version 1.1 from October 12, 1986.

Now, twenty-five years later, I restored my HP-41CV and use the program once again. The HP-41 version is also verified to run under Windows using Warren Furlow’s V41 simulator when compiled with Leo Duran’s hp41uc.
<h3>Theory</h3>
Consider the monic fourth-order polynomial [3]

<a href="http://www.coertvonk.com/technology/hp41/polynomial-factorization-4461/attachment/pol5-1" rel="attachment wp-att-4848"><img class="size-full wp-image-4848 aligncenter" title="pol5-1" alt="" src="http://www.coertvonk.com/wp-content/uploads/pol5-1.png" width="244" height="24" /></a>A root of polynomial <em>p(z)</em> is a number <em>x<sub>i</sub></em> such that <em>p(x<sub>i</sub>)=0</em>.  Each <em>n</em><sup>th</sup>-order polynomial has exactly <em>n</em> roots.  These roots may be real or complex.  Then we have <em>p(z<sub>1</sub>)=0, p(z<sub>2</sub>)=0, p(z<sub>3</sub>)=0, p(z<sub>4</sub>)=0</em>, and we can write

<a href="http://www.coertvonk.com/technology/hp41/polynomial-factorization-4461/attachment/pol5-2" rel="attachment wp-att-4849"><img class="size-full wp-image-4849 aligncenter" title="pol5-2" alt="" src="http://www.coertvonk.com/wp-content/uploads/pol5-2.png" width="259" height="24" /></a>This is the factored form of the monic polynomial.  Multiplying out the symbolic factored form gives a nonlinear system of four equations and four unknowns.  Solving it gives
<h3><a href="http://www.coertvonk.com/technology/hp41/polynomial-factorization-4461/attachment/pol5-3" rel="attachment wp-att-4850"><img class="size-full wp-image-4850 aligncenter" title="pol5-3" alt="" src="http://www.coertvonk.com/wp-content/uploads/pol5-3.png" width="86" height="73" /></a>Examples</h3>
Assumes <span class="hp41-key">FIX</span> 3 and <span class="hp41-key">SIZE</span> 15.
<ol>
	<li><strong>Calculate the roots for: <em>x<sup>5</sup> - x<sup>4</sup> - 101.x<sup>3</sup> + 101.x<sup>2</sup> + 100.x - 100 = 0</em></strong>
<table style="width: 300px;" border="1" frame="box" cellpadding="0">
<tbody>
<tr>
<td><em>entry</em></td>
<td><em>display</em></td>
</tr>
<tr>
<td><span class="hp41-key">XEQ</span> "POL5"</td>
<td class="hp41-display">ORDER?</td>
</tr>
<tr>
<td>5 <span class="hp41-key">R/S</span></td>
<td class="hp41-display">X^5= ?</td>
</tr>
<tr>
<td>1 <span class="hp41-key">R/S</span></td>
<td class="hp41-display">X^4= ?</td>
</tr>
<tr>
<td>1 <span class="hp41-key">CHS</span></td>
<td class="hp41-display"></td>
</tr>
<tr>
<td><span class="hp41-key">R/S</span></td>
<td class="hp41-display">X^3= ?</td>
</tr>
<tr>
<td>101 <span class="hp41-key">CHS</span></td>
<td class="hp41-display"></td>
</tr>
<tr>
<td><span class="hp41-key">R/S</span></td>
<td class="hp41-display">X^2= ?</td>
</tr>
<tr>
<td>101 <span class="hp41-key">R/S</span></td>
<td class="hp41-display">X^1=?</td>
</tr>
<tr>
<td>100 <span class="hp41-key">R/S</span></td>
<td class="hp41-display">CONST?</td>
</tr>
<tr>
<td>100 <span class="hp41-key">CHS</span></td>
<td class="hp41-display"></td>
</tr>
<tr>
<td><span class="hp41-key">R/S</span></td>
<td class="hp41-display">1.000</td>
</tr>
<tr>
<td><span class="hp41-key">R/S</span></td>
<td class="hp41-display">-1.000</td>
</tr>
<tr>
<td><span class="hp41-key">R/S</span></td>
<td class="hp41-display">10.000</td>
</tr>
<tr>
<td><span class="hp41-key">R/S</span></td>
<td class="hp41-display">1.000</td>
</tr>
<tr>
<td><span class="hp41-key">R/S</span></td>
<td class="hp41-display">-10.000</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-key">R/S</span></td>
<td class="hp41-display" rowspan="1" colspan="1">END</td>
</tr>
</tbody>
</table>
</li>
	<li><strong>Calculate<strong> the roots for</strong>: <em>x<sup>4</sup> + x<sup>3</sup> + x<sup>2</sup> + 11.x + 10 = 0</em></strong>
<table style="width: 300px;" border="1">
<tbody>
<tr>
<td><em>entry</em></td>
<td><em>display</em></td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-key">R/S</span></td>
<td class="hp41-display" rowspan="1" colspan="1">ORDER?</td>
</tr>
<tr>
<td>4 <span class="hp41-key">R/S</span></td>
<td class="hp41-display">X^4= ?</td>
</tr>
<tr>
<td>1 <span class="hp41-key">R/S</span></td>
<td class="hp41-display">X^3= ?</td>
</tr>
<tr>
<td>1 <span class="hp41-key">R/S</span></td>
<td class="hp41-display">X^2= ?</td>
</tr>
<tr>
<td>1 <span class="hp41-key">R/S</span></td>
<td class="hp41-display">X^1= ?</td>
</tr>
<tr>
<td>11 <span class="hp41-key">R/S</span></td>
<td class="hp41-display">CONST= ?</td>
</tr>
<tr>
<td>10 <span class="hp41-key">R/S</span></td>
<td class="hp41-display">-1.000</td>
</tr>
<tr>
<td><span class="hp41-key">R/S</span></td>
<td class="hp41-display">-2.000</td>
</tr>
<tr>
<td><span class="hp41-key">R/S</span></td>
<td class="hp41-display">1.000+2.000J</td>
</tr>
<tr>
<td><span class="hp41-key">R/S</span></td>
<td class="hp41-display">1.000-2.000J</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-key">R/S</span></td>
<td rowspan="1" colspan="1">END</td>
</tr>
</tbody>
</table>
</li>
	<li><strong>Calculate <strong>the roots for</strong>: <em>x<sup>3</sup> - x<sup>2</sup> + x - 1 = 0</em></strong>
<table style="width: 300px;" border="1">
<tbody>
<tr>
<td><em>entry</em></td>
<td><em>display</em></td>
</tr>
<tr>
<td><span class="hp41-key">XEQ</span> "POL5"</td>
<td class="hp41-display">ORDER?</td>
</tr>
<tr>
<td>3 <span class="hp41-key">R/S</span></td>
<td class="hp41-display">X^3= ?</td>
</tr>
<tr>
<td>1 <span class="hp41-key">R/S</span></td>
<td class="hp41-display">X^2= ?</td>
</tr>
<tr>
<td>1 <span class="hp41-key">CHS</span></td>
<td class="hp41-display"></td>
</tr>
<tr>
<td><span class="hp41-key">R/S</span></td>
<td class="hp41-display">X^1= ?</td>
</tr>
<tr>
<td>1 <span class="hp41-key">R/S</span></td>
<td class="hp41-display">CONST?</td>
</tr>
<tr>
<td>1 <span class="hp41-key">CHS</span></td>
<td class="hp41-display"></td>
</tr>
<tr>
<td><span class="hp41-key">R/S</span></td>
<td class="hp41-display">1.000E-10+1.000J</td>
</tr>
<tr>
<td><span class="hp41-key">R/S</span></td>
<td class="hp41-display">1.000E-10-1.000J</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-key">R/S</span></td>
<td class="hp41-display" rowspan="1" colspan="1">1</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-key">R/S</span></td>
<td class="hp41-display" rowspan="1" colspan="1">END</td>
</tr>
</tbody>
</table>
</li>
</ol>
<h3>Method</h3>
The 5<sup>th</sup> root is numerically factored, although there are other methods. [3]
<h3>Program listing</h3>
<ul>
	<li>Requires
<ul>
	<li>X-Functions module on the HP-41cv</li>
</ul>
</li>
	<li>Available as
<ul>
	<li><a href="http://coertvonk.com/wp-content/hp-41/pol5.txt">source code</a></li>
	<li><a href="http://coertvonk.com/wp-content/hp-41/pol5.raw">raw code</a> for the V41 emulator</li>
	<li><a href="http://coertvonk.com/wp-content/hp-41/pol5.pdf">bar code</a> for the HP Wand (HP82153A)</li>
</ul>
</li>
	<li>Size
<ul>
	<li>The program takes 527 bytes including the END, and fits on 5 magnetic tracks.</li>
</ul>
</li>
	<li>Registers used
<ul>
	<li>R00, constant</li>
	<li>R01, 1st order coefficient</li>
	<li>:</li>
	<li>R05, 4th order coefficient</li>
	<li>R06, highest order</li>
	<li>R07, loop variable for coefficient input</li>
	<li>R08, subroutine label (highest coefficient + 10)</li>
	<li>R09, display loop variable (dd)</li>
</ul>
</li>
	<li>Flags used
<ul>
	<li>flag 00, when set R00/R01 holds complex roots (R00+-R01.j), otherwise R00/R01 holds real roots</li>
	<li>flag 02, when set, R02/R03 holds complex roots (R02+-R03.j), otherwise R02/R03 holds real roots</li>
</ul>
</li>
</ul>
<pre class="brush: hpfocal; gutter: false; toolbar: off; tab-size: 8">01	LBL "POL5"
02	SF 00		; no complex root in R00/R01
03	FIX 0
04	CF 29
05	"ORDER ?"
06	PROMPT
07	STO 06		; highest order coefficient
08	STO 07		; loop variable for coefficient input
09	 E1
10	+
11	STO 08

12	LBL 21		; coefficients input
13	"X^"
14	ARCL 07
15	&gt;"= ?"
16	PROMPT
17	FS?C 00		; complex root in R00/R01?
18	GTO 20
19	RCL IND 06	; convert to depressed form
20	/
21	LBL 20
22	STO IND 07
23	DSE 07		; decrement loop variable
24	GTO 21
25	"CONST ?"
26	PROMPT
27	RCL IND 06
28	/
29	STO 00

30	SF 29		; "digit grouping"
31	FIX 3
32	 E		; x=1
33	STO IND 06	; highest order coefficient is 1 (because depressed form)
34	-1
35	STO 09		; init dd to -1
36	GTO IND 08	; jump to label matching highest order of polynomial

; SOLVE 2nd ORDER

37	LBL 12
38	XEQ 08		; find two roots
39	XEQ 09		; display two roots
40	GTO 11

; SOLVE 3rd ORDER

41	LBL 13
42	XEQ 10		; Find 3 roots
43	XEQ 09		; display first two roots
44	XEQ 16		; display next root
45	GTO 11

; SOLVE 4th ORDER

46	LBL 14
47	XEQ 18		; find four roots
48	XEQ 09		; display first two roots
49	XEQ 09		; display next two roots
50	GTO 11

; SOLVE 5th ORDER

51	LBL 15
52	XEQ 19		; find five roots
53	XEQ 09		; display first two roots
54	XEQ 09		; display next two roots
55	XEQ 16		; display next root

; FINISH UP, and get ready to do it again

56	LBL 11
57	"END"
58	PROMPT
59	XEQ "POL5"

; DISPLAY TWO ROOTS

60	LBL 09
61	CLA
62	ISG 09		; dd++
63	""              ; NOP
64	FC?C IND 09	; if they are not a complex roots,
65	GTO 17		;   then display two real roots

66	RCL IND 09	; display complex root in rectangular form
67	ISG 09
68	""
69	RCL IND 09
70	ABS
71	ARCL Y
72	&gt;"+"
73	ARCL X
74	&gt;"J"
75	AVIEW
76	STOP
77	CLA		; display conjugate of that root in rectangular form
78	ARCL Y
79	CHS
80	ARCL X
81	&gt;"J"
82	PROMPT
83	RTN

; DISPLAY TWO REAL ROOTS

84	LBL 17
85	DSE 09		; dd
86	""              ; NOP
87	XEQ 16		; display next root, then fall through to show the next one

; DISPLAY ONE REAL ROOT

88	LBL 16
89	CLA
90	ISG 09		; dd points to next root
91	""              ; NOP
92	ARCL IND 09	; display register pointed to by dd
93	PROMPT
94	RTN

; FIND FIVE ROOTS
;
; on entry:
;   depressed form coefficients a0, a1, a2, a3, a4 in R00 .. R04
;
; on exit:
;   if FS?00 then root1 = (R00 + R01.j) and root2 = (R01 - R01.j)
;            else root1 = (R00 +   0.j) and root2 = (R01 -   0.j)
;   if FS?02 then root3 = (R02 + R03.j) and root4 = (R02 - R03.j)
;            else root3 = (R02 +   0.j) and root4 = (R03 -   0.j)
;   root5 = (R04 + 0.j)

95	LBL 19
96	RCL 00
97	STO N		; N = a0
98	 E
99	%
100	STO M		; M = a0 / 100
101	CLST

102	LBL 00		; on entry Z=1
103	RCL Z		; X=Z
104	STO O		; O = starts with 1
105	4   		; fn = a0 + n*(a1 + n*(a2 + n*(a3 + n*(a4 + n))))
106	RCL N
107	LBL 01
108	RCL IND Y
109	+
110	RCL N
111	*
112	DSE Y
113	GTO 01
114	RCL 00
115	+
116	ST* M		; M = M * fn
117	ST- O		; O = O - fn
118	RCL M
119	RCL O
120	X#0?		; if (O &lt;&gt; 0 )
121	/		;   then M = M / O
122	STO M		;   else M = 0

123	X&lt;&gt; N           ; N = N + M
124	ST+ N
125	RCL N
126	X#Y?		; if ( N &lt;&gt; M )
127	GTO 00		;   then next iteration

128	RCL O		; Eliminate 5th root
129	R^  		;   a3' = a4 + root5-&gt;re
130	*		;   a2' = a3 + root5-&gt;re * a3
131	+		;   a1' = a2 + root5-&gt;re * a2
132	X&lt;&gt; 04          ;   a0' = a1 + root5-&gt;re * a1
133	3
134	X&lt;&gt;Y            ; root5 = N + O * fn
135	 E
136	LBL 02
137	RCL 04
138	*
139	+
140	ENTER^
141	X&lt;&gt; IND Z
142	X&lt;&gt;Y
143	DSE Z
144	GTO 02
145	RCL 04
146	*
147	+
148	STO 00		; rolls over to "FIND FOUR ROOTS"

; FIND FOUR ROOTS
;
; on entry:
;   depressed form coefficients a0, a1, a2, a3 in R00 .. R03
;
; on exit:
;   if FS?00 then root1 = (R00 + R01.j) and root2 = (R01 - R01.j)
;            else root1 = (R00 +   0.j) and root2 = (R01 -   0.j)
;   if FS?02 then root3 = (R02 + R03.j) and root4 = (R02 - R03.j)
;            else root3 = (R02 +   0.j) and root4 = (R03 -   0.j)

149	LBL 18
150	RCL 01
151	STO N		; N = a1
152	X^2
153	RCL 00
154	STO M		; M = a0
155	RCL 02
156	CHS
157	STO O		; O = -a2
158	STO 02
159	4
160	*
161	RCL 03
162	ST* 01
163	X^2
164	+
165	*
166	+
167	CHS
168	X&lt;&gt; 00          ; Now:
169	4		;   a2' = -a2                  (R02)
170	*		;   a1' = a1*a3-4*a0	       (R01)
171	ST- 01		;   a0' = a0*(4*a2-a3^2)-a1^2  (R00)

172	XEQ 07		; Find 3 roots

173	RCL 02		; Determine largest root
174	FS? 00		;   if complex root in R00/R01, then
175	GTO 06          ;     X = root3-&gt;re
176	RCL 01		;   else
177	X&lt;Y?            ;     X = maximum of root1-&gt;re, root2-&gt;re, root3-&gt;re
178	X&lt;&gt;Y
179	RCL 00
180	X&lt;Y?
181	X&lt;&gt;Y            ; X = largestRoot

182	LBL 06 		; Eliminate the largest root
183	STO 00		;   A = a3/2
184	STO 02     	;   B = largestRoot/2
185	RCL O		;   C = sqrt(A*A-a2+largestRoot);
186	+   		;   D = sqrt(B*B-a0);
187	RCL 03		;   S = sign(A*B-a1/2))    (sign returns 1 if &gt;=0, -1 if  02
225	STO 00
226	RCL 01
227	X&lt;&gt; 03
228	STO 01
229	CF 02
230	FS? 00
231	SF 02		; Find the next two roots
232	CLA		;   a1' = A - S.C;
233	GTO 03 		;   a0' = B - D;

; FIND THREE ROOTS
;
; on entry:
;   depressed form coefficients a0, a1, a2 in R00 .. R02
;
; on exit:
;   if FS?00 then root1 = (R00 + R01.j) and root2 = (R01 - R01.j)
;            else root1 = (R00 +   0.j) and root2 = (R01 -   0.j)
;   root3 = (R02 + 0.j)

234	LBL 10		; Find the 3rd root
235	LBL 07
236	XEQ 04
237	RCL 02
238	3
239	/
240	-

241	STO 00		; Eliminate the 3rd root
242	ST+ 02
243	RCL 02
244	*
245	ST+ 01
246	RCL 02
247	X&lt;&gt; 01          ; Find the next two roots (rolls over to LBL 08)
248	X&lt;&gt; 00          ;     a1' = a2 + root3-&gt;re                           (R01)
249	STO 02		;     a0' = a1 + root3-&gt;re * ( a2 + root3-&gt;re)       (R00)

; FIND TWO ROOTS
;
; on entry:
;   depressed for coefficients a0, a1 in R00 .. R01
;
; on exit:
;   if FS?00 then root1 = (R00 + R01.j) and root2 = (R01 - R01.j)
;            else root1 = (R00 +   0.j) and root2 = (R01 -   0.j)

250	LBL 08
251	LBL 03
252	CF 00
253	RCL 00
254	4
255	*
256	RCL 01
257	STO 00
258	X^2
259	-		; discr = (a1^2)/4 - a0;
260	X&gt;0?            ; discr &gt; 0?
261	SF 00
262	ABS
263	SQRT
264	2
265	CHS
266	ST/ 00
267	/
268	CHS
269	STO 01
270	FS? 00		; complex root in R00/R01?
271	RTN 		; X = sqrt(abs(a0-a1^2/4))

272	RCL 00
273	STO 01
274	RDN
275	ST+ 00
276	ST- 01
277	RTN 		; X = sqrt(abs(a0-a1^2/4))

; FIND 3RD ROOT HELPER, returns the real part + a2/3 in X
;
; on entry:
;   depressed form coefficients a0, a1, a2 in R00 .. R02
;
; on exit:
;   Note the ' sign, because to get root3, 2/3 needs to be subtracted
;   X register holds (root3 + a2/3)

278	LBL 04
279	RCL 01	        ; Method:
280	RCL 02	        ;   p = a1/3 - a2^2/9
281	X^2 		;   q = a1*a2/6 - a2^3/27 - a0/2;
282	3		;   tmp = p^3 + q^2
283	/
284	-
285	3
286	/
287	RCL 01
288	RCL 02
289	*
290	6
291	/
292	RCL 02
293	3
294	/
295	LASTX
296	Y^X
297	-
298	RCL 00
299	2
300	/
301	-
302	X=0?		; if (q==0) then
303	RTN		;     X = (0 + 0.j)

304	STO Z  	        ; else
305	X^2
306	X&lt;&gt;Y
307	3
308	Y^X
309	+		;     if (tmp &lt; 0)
310	Xre' = 2*(q^2+sqrt(-tmp)^2)^1/3 *
311	GTO 05		;             cos(phi(q,sqrt(-tmp))/3)

312	SQRT		;     else
313	ST- Z		;         X = sign(q-sqrt(tmp))*abs(q-sqrt(tmp))^1/3 +
314	+   		;             sign(q+sqrt(tmp))*abs(q+sqrt(tmp))^1/3
315	SIGN
316	LASTX
317	ABS
318	3
319	1/X
320	Y^X
321	*
322	X&lt;&gt;Y
323	SIGN
324	LASTX
325	ABS
326	3
327	1/X
328	Y^X
329	*
330	+
331	RTN

332	LBL 05
333	CHS
334	SQRT
335	X&lt;&gt;Y
336	R-P
337	3
338	1/X
339	Y^X
340	X&lt;&gt;Y
341	3
342	/
343	COS
344	*
345	ST+ X
346	RTN

347	END</pre>
<h3>References</h3>
<table border="0">
<tbody>
<tr>
<td dir="" id="" lang="" scope="" align="" valign="top">[1]</td>
<td dir="" id="" lang="" scope="" align="" valign="top"></td>
<td><em>Title Unknown</em>
Michiel Niemeijer, <em>approx 1985</em>
HP User News, TH Boekhandel Prins, Binnenwatersloot 30, Delft, the Netherlands</td>
</tr>
<tr>
<td dir="" id="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top">[2]</td>
<td dir="" id="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top"></td>
<td dir="" id="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top">Mathematics of the Discrete Fourier Fransform (DFT), <a href="https://ccrma.stanford.edu/~jos/mdft/Factoring_Polynomial.html">Factoring a Polynomial</a>
Julius O. Smith III, Stanford University, April 2007 (2nd edition)
W3K Publishing, ISDN 978-0974560748</td>
</tr>
<tr>
<td dir="" id="" lang="" scope="" align="" valign="top">[3]</td>
<td dir="" id="" lang="" scope="" align="" valign="top"></td>
<td dir="" id="" lang="" scope="" align="" valign="top">Quintic Equation (5th degree)
<a href="http://mathworld.wolfram.com/QuinticEquation.html"> Wolfram</a></td>
</tr>
</tbody>
</table>]]></description>
		<wfw:commentRss>http://www.coertvonk.com/technology/hp41/polynomial-factorization-4461/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<enclosure url="http://www.coertvonk.com/wp-content/uploads/hp41.png" length="226487" type="image/jpg" />
<media:content xmlns:media="http://search.yahoo.com/mrss/" url="http://www.coertvonk.com/wp-content/uploads/hp41.png" width="300" height="300" medium="image" type="image/jpeg">
<media:copyright>Coert Vonk</media:copyright>
</media:content>
	</item>
		<item>
		<title>Hyperbolic Operations for HP-41cv/cx</title>
		<link>http://www.coertvonk.com/technology/hp41/hyperbolic-4623</link>
		<comments>http://www.coertvonk.com/technology/hp41/hyperbolic-4623#comments</comments>
		<pubDate>Mon, 27 Feb 2012 21:09:28 +0000</pubDate>
		<dc:creator>Coert</dc:creator>
				<category><![CDATA[Math (HP-41)]]></category>

		<guid isPermaLink="false">http://www.coertvonk.com/?p=4623</guid>
		<description><![CDATA[<div><img width="150" height="150" src="http://www.coertvonk.com/wp-content/uploads/hp41-150x150.png" class="attachment-post-thumbnail wp-post-image" alt="hp41" /></div>This program adds hyperbolic operations to the HP-41.
<h3>History</h3>
I wrote this code in October 1986.  I uses some modified functions to improve accuracy.
<h3>Instructions</h3>
The labels automatically map to the user keyboard. Note that some hyperbolic operations leave the stack disturbed.
<h3>Examples</h3>
<ol>
	<li>Calculate the <em>sinh(1)</em>
<table border="1">
<tbody>
<tr>
<td><span class="hp41-key">GTO</span> "HYP"</td>
<td class="hp41-display"></td>
</tr>
<tr>
<td><span class="hp41-nkey">USER</span></td>
<td class="hp41-display"></td>
</tr>
<tr>
<td>1 <span class="hp41-ckey">SIN</span></td>
<td class="hp41-display">1.1752</td>
</tr>
</tbody>
</table>
</li>
</ol>
<h3>Listing</h3>
<ul>
	<li>Requires
<ul>
	<li>X-Functions module on the HP-41cv</li>
</ul>
</li>
	<li>Available as
<ul>
	<li><a href="http://coertvonk.com/wp-content/hp-41/hyp101.txt">source code</a></li>
	<li><a href="http://coertvonk.com/wp-content/hp-41/hyp101.raw">raw code</a> for the V41 emulator</li>
	<li><a href="http://coertvonk.com/wp-content/hp-41/hyp101.pdf">bar code</a> for the HP Wand (HP82153A)</li>
</ul>
</li>
	<li>Size
<ul>
	<li>12 registers; 78 bytes including END; 1 magnetic track (78/112=0.70)</li>
</ul>
</li>
</ul>
<pre class="brush: hpfocal; gutter: false; toolbar: off; tab-size: 8">01	LBL "HYP"

02	LBL H	; [sinh]
03	STO M
04	E^X-1
05	LASTX
06	E^X
07	/
08	RCL M
09	E^X-1
10	+
11	LBL 00
12	2
13	/
14	RTN

15	LBL I 	; [cosh]
16	E^X
17	1/X
18	LASTX
19	+
20	GTO 00

21	LBL J	; [tanh]
22	XEQ H
23	RCL M
24	XEQ I
25	/
26	RTN

27	LBL C	; [asinh]
28	X^2
29	LASTX
30	X&lt;&gt;Y
31	 E
32	+
33	GTO 01

34	LBL E	; [atanh]
35	 E
36	+
37	ENTER^
38	ENTER^
39	2
40	-
41	/
42	CHS
43	LN
44	GTO 00

45	LBL D	; [acosh]
46	X^2
47	LASTX
48	X&lt;&gt;Y
49	 E
50	-
51	LBL 01
52	SQRT
53	+
54	LN
55	END</pre>]]></description>
		<wfw:commentRss>http://www.coertvonk.com/technology/hp41/hyperbolic-4623/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<enclosure url="http://www.coertvonk.com/wp-content/uploads/hp41.png" length="226487" type="image/jpg" />
<media:content xmlns:media="http://search.yahoo.com/mrss/" url="http://www.coertvonk.com/wp-content/uploads/hp41.png" width="300" height="300" medium="image" type="image/jpeg">
<media:copyright>Coert Vonk</media:copyright>
</media:content>
	</item>
		<item>
		<title>Eigenvalues for HP-41cv/cx</title>
		<link>http://www.coertvonk.com/technology/hp41/eigenvalues-4606</link>
		<comments>http://www.coertvonk.com/technology/hp41/eigenvalues-4606#comments</comments>
		<pubDate>Mon, 27 Feb 2012 17:15:59 +0000</pubDate>
		<dc:creator>Coert</dc:creator>
				<category><![CDATA[Math (HP-41)]]></category>

		<guid isPermaLink="false">http://www.coertvonk.com/?p=4606</guid>
		<description><![CDATA[<div><img width="150" height="150" src="http://www.coertvonk.com/wp-content/uploads/hp41-150x150.png" class="attachment-post-thumbnail wp-post-image" alt="hp41" /></div>This program determines the eigenvalues of a real number matrix.
<h3>Theory</h3>
Multiplying a vector <em></em>with a square matrix, usually changes both the magnitude (scale) and the direction of the vector.  In the special case where it changes only the magnitude of the vector and leaves the direction unchanged (or switches the vector to the opposite direction), that vector is called an eigenvector of that matrix.

When multiplied by a matrix, each eigenvector of that matrix changes its magnitude by a factor, called the eigenvalue corresponding to that eigenvector.  In other words: vector <em>x</em> is called an eigenvector<em></em> of the matrix <em>A</em> with eigenvalue <em>λ</em> if the following equation holds [5]
<p style="text-align: center;"><em>A.x = λ.x</em></p>
The eigenvalues of <em>A</em> are precisely the solutions λ to the equation <em>det(A - λ.x) = 0</em>. Here <em>det()</em> is the determinant of matrix formed by <em>A - λ.I</em> in which <em>I</em> is a <em>n</em>×<em>n</em> identity matrix. This equation is called the <em>characteristic equation</em> of <em>A</em>.

For a more detailed description including complex eigenvalues, refer to my article "<a href="http://www.coertvonk.com/technology/hp41/complex-eigenvalues-4532">Complex Eigenvalues for HP-41cv/cx</a>"
<h3>Method</h3>
The program uses the iterative power method to determine the largest eigenvalue. This value is removed from the matrix using the deflation method of Hotelling [1]. The remaining eigenvalues are determined in a similar way. Note that accumulation of rounding errors will affect the accuracy of successive eigenvalues.

The power method is an iterative method for approximating eigenvalues. This method is perhaps not the most respected method, and can only be used when:
<ul>
	<li>There are no two identical eigenvalues.</li>
	<li>The start vector is not the null vector.</li>
	<li>The matrix does not contain complex eigenvalues. (The method will typically work well with a strongly dominated diagonal).</li>
</ul>
If desired, the eigenvectors can be calculated from the original matrix A. (The deflation method spoils the eigenvector, but not the eigenvalue.)
<h3>Examples</h3>
<ol>
	<li>Matrix A
<a href="http://www.coertvonk.com/technology/hp41/eigenvalues-4606/attachment/eigw-1" rel="attachment wp-att-4607"><img class="alignnone size-full wp-image-4607" title="eigw-1" alt="" src="http://www.coertvonk.com/wp-content/uploads/eigw-1.png" width="79" height="37" /></a>
<table border="1">
<tbody>
<tr>
<td><em>keystrokes
</em></td>
<td><em>display</em></td>
</tr>
<tr>
<td><span class="hp41-key">FIX</span> 3</td>
<td class="hp41-display"></td>
</tr>
<tr>
<td><span class="hp41-key">XEQ</span> "EW"</td>
<td class="hp41-display">DIM?</td>
</tr>
<tr>
<td>2 <span class="hp41-key">R/S</span></td>
<td class="hp41-display">INV.MATRIX:</td>
</tr>
<tr>
<td></td>
<td class="hp41-display">1:1=0.000?</td>
</tr>
<tr>
<td>8 <span class="hp41-key">R/S</span></td>
<td class="hp41-display">1:2=0.000?</td>
</tr>
<tr>
<td>4 <span class="hp41-key">R/S</span></td>
<td class="hp41-display">2:1=0.000?</td>
</tr>
<tr>
<td>3 <span class="hp41-key">R/S</span></td>
<td class="hp41-display">2:2=0.000?</td>
</tr>
<tr>
<td>6 <span class="hp41-key">R/S</span></td>
<td class="hp41-display">INV.STARTV.:</td>
</tr>
<tr>
<td></td>
<td class="hp41-display">1:1=0.000?</td>
</tr>
<tr>
<td>1 <span class="hp41-key">R/S</span></td>
<td class="hp41-display">2:1=0.000?</td>
</tr>
<tr>
<td>1 <span class="hp41-key">R/S</span></td>
<td class="hp41-display">EPS=0.001?</td>
</tr>
<tr>
<td><span class="hp41-key">R/S</span></td>
<td class="hp41-display">10.500</td>
</tr>
<tr>
<td></td>
<td class="hp41-display">:</td>
</tr>
<tr>
<td rowspan="1" colspan="1"></td>
<td class="hp41-display" rowspan="1" colspan="1">10.605</td>
</tr>
<tr>
<td rowspan="1" colspan="1"></td>
<td class="hp41-display" rowspan="1" colspan="1">EW=10.606</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-key">R/S</span></td>
<td class="hp41-display" rowspan="1" colspan="1">INV.STARTV.:</td>
</tr>
<tr>
<td rowspan="1" colspan="1"></td>
<td class="hp41-display" rowspan="1" colspan="1">1:1=0.838?</td>
</tr>
<tr>
<td rowspan="1" colspan="1">1 <span class="hp41-key">R/S</span></td>
<td class="hp41-display" rowspan="1" colspan="1">2:1=0.546?</td>
</tr>
<tr>
<td rowspan="1" colspan="1">1 <span class="hp41-key">R/S</span></td>
<td class="hp41-display" rowspan="1" colspan="1">EPS=0.001?</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-key">R/S</span></td>
<td class="hp41-display" rowspan="1" colspan="1">-0.230</td>
</tr>
<tr>
<td rowspan="1" colspan="1"></td>
<td class="hp41-display" rowspan="1" colspan="1">3.393</td>
</tr>
<tr>
<td rowspan="1" colspan="1"></td>
<td class="hp41-display" rowspan="1" colspan="1">3.394</td>
</tr>
<tr>
<td rowspan="1" colspan="1"></td>
<td class="hp41-display" rowspan="1" colspan="1">EW=3.394</td>
</tr>
<tr>
<td rowspan="1" colspan="1"><span class="hp41-key">R/S</span></td>
<td class="hp41-display" rowspan="1" colspan="1">EINDE</td>
</tr>
</tbody>
</table>
The computed eigenvalues <em>10.606</em> and <em>3.394</em> can be verified through:
<a href="http://www.coertvonk.com/technology/hp41/eigenvalues-4606/attachment/ew-2" rel="attachment wp-att-4735"><img class="alignnone size-full wp-image-4735" title="ew-2" alt="" src="http://www.coertvonk.com/wp-content/uploads/ew-2.png" width="538" height="120" /></a>

This is also verified through the characteristic polynomial. The eigenvalues of <em>A</em> are precisely the solutions <em>λ</em> to the equation listed below with <em>I</em> is the<em> n×n</em> identify matrix.
<a href="http://www.coertvonk.com/technology/hp41/eigenvalues-4606/attachment/ew-4" rel="attachment wp-att-4746"><img class="alignnone size-full wp-image-4746" title="ew-4" alt="" src="http://www.coertvonk.com/wp-content/uploads/ew-4.png" width="107" height="16" />
</a>
Therefore:
<a href="http://www.coertvonk.com/technology/hp41/eigenvalues-4606/attachment/ew-3" rel="attachment wp-att-4747"><img class="alignnone size-full wp-image-4747" title="ew-3" alt="" src="http://www.coertvonk.com/wp-content/uploads/ew-3.png" width="228" height="233" /></a>
The solutions to this equation are the eigenvalues <em>λ</em><sub>i</sub>.
The JavaScript calculator "Eigenwerte und Eigenvektoren berechnen" provides another verification [7].</li>
</ol>
<h3>Listing</h3>
<ul>
	<li>Requires
<ul>
	<li>X-Functions module on the HP-41cv</li>
	<li>Advantage ROM</li>
</ul>
</li>
	<li>Available as
<ul>
	<li><a href="http://coertvonk.com/wp-content/hp-41/eigw100.txt">source code</a></li>
	<li><a href="http://coertvonk.com/wp-content/hp-41/eigw100.raw">raw code</a> for the V41 emulator</li>
	<li><a href="http://coertvonk.com/wp-content/hp-41/eigw100.pdf">bar code</a> for the HP Wand (HP82153A)</li>
</ul>
</li>
	<li>Size
<ul>
	<li>39 registers</li>
</ul>
</li>
	<li>Registers:
<ul>
	<li>alfa, X, Y, Z, T, L</li>
	<li>R00: epsilon</li>
	<li>R01: loop counter</li>
	<li>R02: eigenvalue</li>
</ul>
</li>
	<li>Long jumps:
<ul>
	<li>41</li>
	<li>95</li>
</ul>
</li>
</ul>
<pre class="brush: hpfocal; gutter: false; toolbar: off; tab-size: 8">;  /---------------------------------------------------------------------\
;  |                      E i g e n v a l u e s                          |
;  |                                                                     |
;  |                            for the HP-41                            |
;  \---------------------------------------------------------------------/
;
;                                   1.00
;                               Coert Vonk
;
;            http://www.coertvonk.com/technology/hp41/eigenvalues-4606

01      LBL "EW"
02       E-4            ; default eps
03      STO 00
04      CF 08
05      "DIM ?"         ; invoer dimensie
06      PROMPT
07      ABS
08      INT
09      STO 01
10      ENTER^
11      ENTER^
12       E3
13      /
14      +
15      "INP. MATRIX:"
16      AVIEW
17      "B"
18      XROM 22,29      ; MATDIM: creeer B-matrix
19      "A"
20      XROM 22,29      ; MATDIM: creer A-matrix
21      XROM 22,61      ; MEDIT: invoer A-matrix

22      LBL 00
23      "A"
24      XROM 22,18      ; DIM?
25      INT
26      "INP. STARTV.:"
27      AVIEW
28      "W"             ; creer W-vector
29      XROM 22,29      ; MATDIM
30      "V"             ; creer V-vector
31      XROM 22,29      ; MATDIM
32      XROM 22,61      ; MEDIT: invoer V-vector
33      XROM 22,19      ; FNRM
34      "STARTV. ERR"
35      X=0?
36      AVIEW
37      X=0?
38      PSE             ; als startvector
39      X=0?            ; de nulvector is
40	GTO 00		; dan opnieuw
41	XEQ 03
42	RCL 00
43	"EPS="
44	ARCL X
45	&gt;"?"
46	PROMPT		; invoer epsilon
47	STO 00
48	LBL 01
49	"W"
50	XROM 22,57      ; SUM
51	XROM 22,18      ; DIM?
52	INT
53	/
54	VIEW X		; tussenresultaat v/d e.g. laten zien
55	STO 02
56	RCL 00
57	XROM 22,33      ; MIN
58	+
59	XROM 22,30      ; MAX
60	X&lt;=Y?		; test of er aan de nauwkeurigheid eps word voldaan
61	GTO 00		; zo  ja, spring
62	XEQ 03		; zo nee, ga verder
63	GTO 01

; toon de gevonden e.w.

64	LBL 00
65	RCL 02
66	"EV="
67	ARCL X
68	PROMPT
69	DSE 01		; alle ew nog niet gevonden?
70	GTO 04		; dan spring naar 04
71	"V"
72	PURFL		; maak de extended-memory weer schoon
73	"W"
74	PURFL
75	"A"
76	PURFL
77	"B"
78	PURFL
79	"EINDE"		; we're done
80	PROMPT
81	GTO E

; zeef de gevonden eigenwaarde uit de laatst gebruikte matrix (A)

82	LBL 04
83	 E
84	"X,V,W"
85	XROM 22,25      ; MAT*
86	"W"
87	XROM 22,59      ; TRNPS
88	"V,W,B"
89	XROM 22,24      ; M*M
90	RCL 02
91	"X,B"
92	XROM 22,25      ; MAT*
93	"A,B,A"
94	XROM 22,27      ; MAT-
95	GTO 00

; voer een iteratie slag uit volgens de powermethode
; zodat v:=A*v en w:=e.w. vector

96	LBL 03
97	"A,V,W"
98	XROM 22,24      ; M*M
99      "W,V"
100     XROM 22,28      ; MAT/
101     1.001
102     XROM 22,18      ; DIM?
103     RCL Y
104     "V,W"
105     XROM 22,49      ; MSWAP
106     "V"
107     XROM 22,19      ; FNRM
108     1/X
109     "X,V"
110     XROM 22,25      ; MAT*
111	RTN

112	END</pre>
<h3>References</h3>
<table border="0">
<tbody>
<tr>
<td dir="" id="" lang="" scope="" align="" valign="top">[1]</td>
<td dir="" id="" lang="" scope="" align="" valign="top"></td>
<td dir="" id="" lang="" scope="" align="" valign="top">Eigenwaarden
Coert Vonk, 27 September 1986
HP User News, SEP86 N9, blz. 48-50</td>
</tr>
<tr>
<td dir="" id="" lang="" scope="" align="" valign="top">[2]</td>
<td dir="" id="" lang="" scope="" align="" valign="top"></td>
<td dir="" id="" lang="" scope="" align="" valign="top">Matrixrekenen
Dictaat Lineaire Algebra, blz. 51 e.v.
Ir. A. van der Knaap
HTS Dordrecht, the Netherlands</td>
</tr>
<tr>
<td dir="" id="" lang="" scope="" align="" valign="top">[3]</td>
<td dir="" id="" lang="" scope="" align="" valign="top"></td>
<td dir="" id="" lang="" scope="" align="" valign="top">Wiskunde voor het HBO Deel 2, blz. 153 e.v.
R. van Asselt
ISBN 90 11 008480</td>
</tr>
<tr>
<td dir="" id="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top">[4]</td>
<td dir="" id="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top"></td>
<td>Dictaat Lineaire Algebra 4e druk, blz. 152 ev.
G. W. Decnop &amp; H. van Iperen
ISBN 90 65 620362</td>
</tr>
<tr>
<td dir="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top">[5]</td>
<td dir="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top"></td>
<td dir="" id="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top">Eigenvalues and eigenvectors
Wikipedia
<a href="http://en.wikipedia.org/wiki/Eigenvalues_and_eigenvectors">http://en.wikipedia.org/wiki/Eigenvalues_and_eigenvectors</a></td>
</tr>
<tr>
<td dir="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top">[6]</td>
<td dir="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top"></td>
<td dir="" id="" lang="" rowspan="1" colspan="1" scope="" align="" valign="top">Eigenwerte und Eigenvektoren berechnen
Arndt Brünner
<a href="http://www.arndt-bruenner.de/mathe/scripts/engl_eigenwert2.htm">http://www.arndt-bruenner.de/mathe/scripts/engl_eigenwert2.htm</a></td>
</tr>
</tbody>
</table>]]></description>
		<wfw:commentRss>http://www.coertvonk.com/technology/hp41/eigenvalues-4606/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<enclosure url="http://www.coertvonk.com/wp-content/uploads/hp41.png" length="226487" type="image/jpg" />
<media:content xmlns:media="http://search.yahoo.com/mrss/" url="http://www.coertvonk.com/wp-content/uploads/hp41.png" width="300" height="300" medium="image" type="image/jpeg">
<media:copyright>Coert Vonk</media:copyright>
</media:content>
	</item>
	</channel>
</rss>
