<?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>DevBlog &#187; Trinity</title>
	<atom:link href="http://simonowen.com/blog/category/trinity/feed/" rel="self" type="application/rss+xml" />
	<link>http://simonowen.com/blog</link>
	<description>stuff and nonsense</description>
	<lastBuildDate>Thu, 19 Jan 2012 17:59:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>SAM/IP</title>
		<link>http://simonowen.com/blog/2007/12/11/samip/</link>
		<comments>http://simonowen.com/blog/2007/12/11/samip/#comments</comments>
		<pubDate>Tue, 11 Dec 2007 23:27:35 +0000</pubDate>
		<dc:creator>Simon</dc:creator>
				<category><![CDATA[SAM Coupe]]></category>
		<category><![CDATA[Trinity]]></category>

		<guid isPermaLink="false">http://simonowen.com/blog/2007/12/11/samip/</guid>
		<description><![CDATA[The SAM port of uIP seems to be on hold at the moment, so I&#8217;ve been looking at other IP stacks to use until it&#8217;s ready. The most appealing is Mark Rison&#8217;s CPC/IP, not least because it&#8217;s written in Z80 and should work without extensive changes. It also comes with a number of built-in client [...]]]></description>
			<content:encoded><![CDATA[<p>The SAM port of <a href="http://www.sics.se/~adam/uip/index.php/Main_Page">uIP</a> seems to be on hold at the moment, so I&#8217;ve been looking at other IP stacks to use until it&#8217;s ready.  The most appealing is Mark Rison&#8217;s <a href="http://www.cepece.info/cpcip/">CPC/IP</a>, not least because it&#8217;s written in Z80 and should work without extensive changes.  It also comes with a number of built-in client (telnet, finger, host, ping) and server (web, tftp, dns) modules.</p>
<p>So far I&#8217;ve modified the source so it assembles with <a href="http://www.intensity.org.uk/samcoupe/pyz80.html">pyz80</a>.  A global search and replace made quick work of changing the label format from &#8220;.label&#8221; to &#8220;label:&#8221;, but I had to change many data statements manually.  Strings were often combined with other single bytes in defb statements, but the Comet format used by pyz80 doesn&#8217;t allow that, requiring defm be used instead.</p>
<p>The existing code is nice and modular, but there are CPC-specific ROM calls sprinkled throughout them.  All those need to be changed before a test run on SAM, to avoid us unexpectedly jumping into the middle of nowhere!  I changed the stdio.z module to use SAM&#8217;s ROM calls for character output, leaving the cursor control and keyboard input doing nothing for now.  I also replaced the serial module with a dummy ethernet module, with no-op versions of the required interface functions.  They will be fleshed out with calls to the Trinity driver when the rest of the code is ready.</p>
<p>Those changes are enough for a basic run on SAM, without being connected to a real network.  Here&#8217;s what you see when it&#8217;s launched:<br />
<a href='http://174.120.254.194/~simon/blog/wp-content/uploads/2007/12/cpcip.png' title='CPC/IP on SAM'><img src='http://174.120.254.194/~simon/blog/wp-content/uploads/2007/12/cpcip_small.png' alt='CPC/IP on SAM' /></a></p>
<p>The program continues polling for serial and keyboard input in a main loop.  The CPC version uses a 300Hz timer to poll for new data from the serial link, which is buffered for later reading from the main loop.  Each received byte is passed into either the SLIP or PPP module (whichever was configured during the build), which builds up complete datagrams.  These are then passed into the &#8216;ip_handle&#8217; function inside ip.z for the processing.</p>
<p>The SAM implementation will read complete datagrams from the Trinity driver, so they can be passed straight into &#8216;ip_handle&#8217;.  This vastly simplifies the setup above, but introduces a new requirement: ARP.  SLIP and PPP push datagrams back into the link and let the remote end deal with routing.  With ethernet we need to determine the hardware addresses for delivery, for both local and routed traffic.</p>
<p>I&#8217;ll need to write a new arp.z module to sit between the Trinity driver and the IP module.  Outgoing traffic for hosts already in the ARP cache can be sent immediately.  Anything for as-yet-unknown targets must be buffered, and a who-has ARP request made for the address owner to reply.  Once a reply is received, an entry for it is added to the local ARP cache and data buffered for that host is sent.  If no reply is received (ideally after multiple attempts), data for the target will be discarded.  We must also reply to incoming ARP requests for our own address so other hosts can to talk to us.</p>
<p>I&#8217;m still torn between using the SAM ROM routines for I/O and something based on the terminal code I wrote for the <a href="http://simonowen.com/blog/2007/03/19/apple-1-emulator/">Apple 1 emulator</a>.  The ROM code would give the same output flexibility as in BASIC, but the general ROM code is a bit on the slow side.  My own code could be tailored for a specific mode, either mode 2 for speed or mode 3 for hi-res.  It might be easier to stick with the ROM code for now, and change it if it&#8217;s too slow.</p>
]]></content:encoded>
			<wfw:commentRss>http://simonowen.com/blog/2007/12/11/samip/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Trinity Ethernet</title>
		<link>http://simonowen.com/blog/2007/11/30/trinity-ethernet/</link>
		<comments>http://simonowen.com/blog/2007/11/30/trinity-ethernet/#comments</comments>
		<pubDate>Fri, 30 Nov 2007 00:09:54 +0000</pubDate>
		<dc:creator>Simon</dc:creator>
				<category><![CDATA[SAM Coupe]]></category>
		<category><![CDATA[Trinity]]></category>

		<guid isPermaLink="false">http://simonowen.com/blog/2007/11/30/trinity-ethernet/</guid>
		<description><![CDATA[After a break of a few of months, I&#8217;m almost back on the development wagon. I did the odd project tweak during that time but haven&#8217;t spent any quality time working on new features. Last month I picked up one of the first Quazar Trinty boards. Since then I&#8217;ve been working on the ethernet side, [...]]]></description>
			<content:encoded><![CDATA[<p>After a break of a few of months, I&#8217;m almost back on the development wagon.  I did the odd project tweak during that time but haven&#8217;t spent any quality time working on new features.</p>
<p>Last month I picked up one of the first Quazar Trinty boards.  Since then I&#8217;ve been working on the ethernet side, which is based around a MicroChip ENC28J60 chip.  The Trinity board also includes EEPROM and MMC/SD board features, but I&#8217;m leaving those for another time.  My first task was to write a simple network driver, to allow sending and receiving raw packets from BASIC.</p>
<p>Trinity uses the SAM port range &#038;DC to &#038;DF.  The first of these is the microcontroller, which acts as a central hub for all the board&#8217;s features.  The other ports are used for the EEPROM, Ethernet and MMC/SD card, and each needs to be enabled through the microcontroller before it can be used.  Port &#038;DE is used for ENC ethernet chip, and once enabled we can read and write to the chip directly.  Well, almost directly as the link uses the SPI bus.</p>
<p>If you&#8217;re as clueless about electronics as I am you probably won&#8217;t have come across the SPI (Serial Peripheral Interface) bus.  It&#8217;s a full duplex link where each byte written is paired with a read back from the device.  Since reads can&#8217;t be performed without a write, Trinity stores the value read for later.  Reading from SAM reads only the stored value, without accessing the ENC.</p>
<p>SPI introduces a lag between writing a value and reading any result generated by the write, since the stored value is what was read <em>before</em> the write completed.  An additional dummy (zero) write is needed for the actual result to be available for reading.  The lag also means block reads require a dummy write before reading each byte.  Fortunately, the latest Trinity firmware provides an auto-null-writing feature to simplify and optimise this.</p>
<p>The ENC itself has a banked register setup, arranged as 4 banks of 32 registers.  The final 5 registers in each bank are common across all banks, and are used for status registers and bank selection.  All ENC features are accessed through these registers, including reading and writing from the internal 8K data buffer.  The buffer is used for both transmitting and receiving, with a user-defined portion of it configured as a circular receive buffer.  The remaining space is unmanaged and available for transmission storage.</p>
<p>In its power-on state the ENC will see but not receive anything.  It has no hardware address set, no space allocated for the receive buffer, and the packet filter is set to ignore everything.  The driver initialisation is responsible for setting up all of those, and any other register where the defaults are not suitable.  Before we do that it&#8217;s wise to ask the Trinity microcontroller to reset the ENC chip back to a known state.</p>
<p>I started my experimentation from BASIC as it was quicker to tweak the ENC registers and see results than launching the assembler for each change.  Colin supplied a sample disk with macros to access the board, with most containing a couple of OUTs and maybe an IN.  I added to them for higher level functions, such as setting the MAC address and writing blocks of data to the ENC buffer.  Once I was happy this was working I was ready to port it to Z80.</p>
<p>I chose to use 6.5K of the 8K buffer for receiving, with 1.5K left for sending.  That&#8217;s just enough space to send a single full-size ethernet frame.  The packet filter was set to receive packets addressed to our MAC address, as well as anything broadcast to the whole subnet.  Writing a zero to the packet filter register disables it, so all local network traffic is seen.  Couple that with packet decoding and you have an easy network sniffer.</p>
<p>My driver development wasn&#8217;t all smooth sailing, with a few bumps along the way.  The first was my early attempts to write and read the MAC address values, to ensure my new Z80 code was working.  It turns out the subset of ENC registers starting with &#8216;M&#8217; (which includes the MAC registers) have an extra lag on top of SPI, and require double-reading before they return the correct result.  I was also stung by a documented ENC issue with the transmit logic getting stuck under certain conditions.  A bug in my work-around meant I would still occasionally hang during transmits.</p>
<p>Even with the driver initialised and reception enabled, we&#8217;re still not quite ready to handle a test ping from another machine on the network.  Responding to requests requires CRC calculations in the return packets, which involved more work than I wanted to do for a test setup.  That will be the job of of a full IP stack.  It&#8217;s marginally easier to send a ping request <em>from</em> SAM, since the request can be pre-calculated and it&#8217;s only the remote host that needs to worry about dynamic responses.</p>
<p>Even pinging an IP address from SAM is surprisingly involved:</p>
<ol>
<li>Use local IP and netmask to determine whether target IP is on our subnet (if not, send to gateway machine for further routing)</li>
<li>Check local ARP cache for the target IP (if found, goto 5)</li>
<li>Broadcast who-has ARP request to find the MAC of the IP</li>
<li>Wait for ARP reply, then add MAC to local ARP cache</li>
<li>Construct ECHO REQUEST ICMP packet</li>
<li>Send unicast packet to target MAC</li>
</ol>
<p>Fortunately, we can strip this down for the sake of a simple test.  We&#8217;re using a local target so step 1 is unnecessary.  We can also hard-code the MAC of the target machine, to also skip steps 2 to 4.  An ICMP ECHO request packet can then be constructed with fixed details and pre-calculated CRCs.  I used Ethereal on my PC to sniff a request sent with a zero CRC, which was expected to fail, then completed the correct CRC with what it reported.</p>
<p>To send a reply, the target machine will perform the same steps as above, with an ICMP ECHO REPLY packet.  As SAM is currently unable to reply to ARP requests we must use the &#8220;arp&#8221; command on the target machine to add a static entry linking SAM&#8217;s IP with its MAC address.  In my case that meant running the following command in Windows XP:</p>
<p><code>arp -s 10.0.0.88 02:A4:92:E4:D3:20</code></p>
<p>The test MAC address I used was formed from bits of the string &#8220;TRINITY&#8221;, with a few unused zero bits at the end.  Bits 0 and 1 of the first byte are flags, but the rest can be pretty much anything.  I&#8217;ve set flag bit 1 to mark the address as &#8220;locally administered&#8221;, to avoid the (rather unlikely!) clash with existing network devices.  To avoid clashes with other Trinity boards, Colin will be assigning unique addresses to each one sold.  For convenience, the MAC and other network settings will ultimately stored on the EEPROM.</p>
<p>The rigid setup above was enough to show that I could ping my PC from SAM, and have the echo reply read from the receive buffer.  What we needed now was a proper IP stack to plug my driver into&#8230;</p>
<p>While I was working on the driver, Adrian Brown was busy porting Adam Dunkels&#8217; <a href="http://www.sics.se/~adam/uip/index.php/Main_Page">uIP</a> stack from C to Z80.  He&#8217;s made quick work of it too, with ARP and ICMP already working well enough to ping from PC to SAM without the need for any of my cheating (ping times are typically 7-8ms).  Once TCP is ready we&#8217;ll have enough for some real applications!  Web server anyone?</p>
]]></content:encoded>
			<wfw:commentRss>http://simonowen.com/blog/2007/11/30/trinity-ethernet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Page Caching using disk: enhanced

Served from: simonowen.com @ 2012-02-04 03:11:54 -->
