tag:blogger.com,1999:blog-60688338122647120772024-03-09T02:20:13.092-08:00Dave's HacksDavehttp://www.blogger.com/profile/07363645951602549336noreply@blogger.comBlogger11125tag:blogger.com,1999:blog-6068833812264712077.post-28967473250002079292016-01-24T04:54:00.002-08:002016-02-01T09:21:04.238-08:00Inside the arm1v - the ALU control logicThis is one of a number of posts on my work on reverse engineering the armv1 processor. The first in the series, and an index of the other articles can be found <a href="http://daveshacks.blogspot.co.uk/2015/12/inside-alu-of-armv1-first-arm.html">here</a>.<br />
<br />
My first post in this series described in some detail a one-bit slice of the ALU, and identified quite a number of control signals that feed all 32 bit slices which determine how the ALU operates. Now that I've reverse-engineered the overall instruction decoding and sequencing mechanism we now have enough context to make a start on reverse-engineering the circuitry that generates the ALU's control signals. This turns out to be more complex than I first expected and a full understanding of what's happening will probably have to wait until other parts of the processor have also been reverse-engineered.<br />
<br />
Let's make a start by setting the context. The ALU circuit from my earlier post is reproduced below; we'll need to refer to it as we proceed.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWY7umxIy0YhMfbqkop7rFvfFYdqvtmRKOZ96sUyHk8swDoQ6OOaY8XlLQ1ze5vz8FRcSXgoiFFw0Az1cqpZjGzHZRUyfuoiOUzds5oN3tePn_1uO2jLnMNsECEOjUtMvx4yBLhMCif8o/s1600/alu.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="342" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWY7umxIy0YhMfbqkop7rFvfFYdqvtmRKOZ96sUyHk8swDoQ6OOaY8XlLQ1ze5vz8FRcSXgoiFFw0Az1cqpZjGzHZRUyfuoiOUzds5oN3tePn_1uO2jLnMNsECEOjUtMvx4yBLhMCif8o/s640/alu.PNG" width="640" /></a></div>
<br />
<br />
The location of this circuitry, and it's control circuitry, on the silicon are as follows:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj684KGj4DBQ5pnDaHwJFF2Ty33gCHF4hhdxp3ix-rFaUOlVjfCKghhrYduk9iVq4Iq4jt4KiVJbSnKPo6aDQCMUkCB-B8hsQi6RvJkIC0waXFL1GUkObfFdYBL283KGwALLnIb-cj0tg0/s1600/alu-control-context.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj684KGj4DBQ5pnDaHwJFF2Ty33gCHF4hhdxp3ix-rFaUOlVjfCKghhrYduk9iVq4Iq4jt4KiVJbSnKPo6aDQCMUkCB-B8hsQi6RvJkIC0waXFL1GUkObfFdYBL283KGwALLnIb-cj0tg0/s400/alu-control-context.PNG" width="395" /></a></div>
<br />
Let's now zoom in on the ALU control area:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEii-U_2Fy2vA2YH9ZeSuZqNWNDWPi82etkzC3o43PInGRs69iyOyCLF8VE4A0fMCU9qbHUViN4pmsgwuF4qSCMU7qEfLQ1z4eTBAzuessXszZwHtrCOxDvByeTi1gvEVi7Amc0Brj20Uec/s1600/alu-control-zoomed.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="396" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEii-U_2Fy2vA2YH9ZeSuZqNWNDWPi82etkzC3o43PInGRs69iyOyCLF8VE4A0fMCU9qbHUViN4pmsgwuF4qSCMU7qEfLQ1z4eTBAzuessXszZwHtrCOxDvByeTi1gvEVi7Amc0Brj20Uec/s400/alu-control-zoomed.PNG" width="400" /></a></div>
<br />
The ALU Control Logic comprises two distinct areas - (1) a bunch of "ad-hoc" gates and drivers sitting just above the ALU itself, and (2) just above them, a Programmable Logic Array which is referred to as PLA-1 in an earlier blog. In the same area is the logic which implements the Program Status Register which is not discussed here.<br />
<br />
The overall circuit is as follows:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHNtwAtaCKCBLgbsR0RBQuU3GCcoVi3WErEnQv1cBn6jHwI33uG_O9FlXQ5RYyr7CSxH421mbgRagIBOi1WZE2tRORjyLgn9AaI8PP0kGQVP5Dw855NgnueChkNE8iomljCKn2Jil8DGk/s1600/alu-control-circuitry.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="516" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHNtwAtaCKCBLgbsR0RBQuU3GCcoVi3WErEnQv1cBn6jHwI33uG_O9FlXQ5RYyr7CSxH421mbgRagIBOi1WZE2tRORjyLgn9AaI8PP0kGQVP5Dw855NgnueChkNE8iomljCKn2Jil8DGk/s640/alu-control-circuitry.PNG" width="640" /></a></div>
<br />
The circuit diagram is laid out roughly as it is in the silicon - a bunch of control signals come in from above and feed PLA-1; the buffered PLA-1 outputs, and a couple of outputs from the instruction-decoder, then feed downwards to provide the control signals to all 32 bit slices that form the ALU. Not surprisingly, these control signals tally exactly with the signals in the ALU circuit at the beginning of this blog.<br />
<br />
The Carry Logic on the left (highlighted in blue) feeds the Carry bit from the PSR Logic (node 8083) to bit 0 of the ALU. The Carry bit is delayed by a single clock cycle using a dynamic latch (I've used a D latch symbol for ease of drawing) and conditioned by two outputs of the PLA as per the following truth table:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhql78FVFwJ8T7CkiqCEZdMA7ustGRSj9_GVUCq2ZlxpzBm1vgjzHMjv7X9BWy7FtszHI0-uvDZCGgP3TVGvNjKsAG3ld_G3U_EMhOSmhvf2YqvxsqQ9de3Op7EgWjR2YYl6zU_3LJH8kk/s1600/carry-conditioning.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhql78FVFwJ8T7CkiqCEZdMA7ustGRSj9_GVUCq2ZlxpzBm1vgjzHMjv7X9BWy7FtszHI0-uvDZCGgP3TVGvNjKsAG3ld_G3U_EMhOSmhvf2YqvxsqQ9de3Op7EgWjR2YYl6zU_3LJH8kk/s1600/carry-conditioning.PNG" /></a></div>
This shows that the PLA-1 outputs can either pass the Carry bit straight to bit 0 of the ALU, or force the Carry line to be either 0 or 1.<br />
<br />
The Dynamic Register Control circuitry on the RHS (highlighted in orange) shows that the two dynamic latches in the ALU (one on each operand path) are controlled by outputs on PLA-2 (the instruction decoder), with latching occurring on the trailing edge of the Phase 1 clock. the Operand 1 latch is also operated one clock cycle after the PLA-2 signals (8062, 8061, 8060) are all simultaneously low. We'll try to make sense of the purpose of this part of the circuit later.<br />
<br />
<span style="font-size: large;">PLA-1 Content - Input Decoding</span><br />
<br />
After all this context setting it's now time to look at what's in PLA-1. The PLA layout is very similar to the instruction decoder PLA-2 <a href="http://daveshacks.blogspot.com/2016/01/inside-armv1-instruction-decoding-and.html">described earlier</a>:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf1m_Ocj0Uq4rHTeruk1ZfhyphenhyphenLNFkgAATP6o1Pamj4Clvn9XN76FZouajnZq933GRlrbnyG5jK-xN6micxZpY-okynDY4QhYW6Yv1dKEDlJ5lcNgobU8rfzC2FMmvVkWgYEjcC_KFTTwYI/s1600/pla-1-image.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf1m_Ocj0Uq4rHTeruk1ZfhyphenhyphenLNFkgAATP6o1Pamj4Clvn9XN76FZouajnZq933GRlrbnyG5jK-xN6micxZpY-okynDY4QhYW6Yv1dKEDlJ5lcNgobU8rfzC2FMmvVkWgYEjcC_KFTTwYI/s640/pla-1-image.PNG" width="387" /></a></div>
<br />
The 8 input selection signals enter the PLA from the lower right and the signals, and their inverted versions, feed 16x vertical columns. Which transistors are fitted (or missing) determine which one of the 31 rows within the PLA is selected. There are further details about the operation of this circuit in the <a href="http://daveshacks.blogspot.com/2016/01/inside-armv1-instruction-decoding-and.html">earlier blog post</a>.<br />
<br />
Let's start with the row selection logic on the RHS of the PLA, a raw dump of which is below (with the top row of the table corresponding to the top row in the PLA):<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgT9N8kPBEwBuQN_Efa-e22pUO-o3u4ENHMfarC5wQ2SItbdEExlbMIafmlyB-cZ62hwExF4t7mj5YKO56o172VCOCIRmlts1qWOcMmjD7cgcjhz3z7e0XTxr4nJunduW7FQpksvbVRlsQ/s1600/pla-1-right-content.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgT9N8kPBEwBuQN_Efa-e22pUO-o3u4ENHMfarC5wQ2SItbdEExlbMIafmlyB-cZ62hwExF4t7mj5YKO56o172VCOCIRmlts1qWOcMmjD7cgcjhz3z7e0XTxr4nJunduW7FQpksvbVRlsQ/s400/pla-1-right-content.PNG" width="160" /></a></div>
<br />
The content displayed in this format doesn't give us much insight into what is happening. However, after a little study the following pattern emerges:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwWDXzdpmlNRWLEmaBzd1OR16usctShbvPKLU5oEUNEsRaioIHyH3_wr70g0zAVV2WXTQ6wfZQZMAtMPBKQrKM_zHXu_y92h9U30_b1H2BZsdtP7rZEu6_f-1oyFN12-48JzTFAsjuh8I/s1600/pla-1-right-content2.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwWDXzdpmlNRWLEmaBzd1OR16usctShbvPKLU5oEUNEsRaioIHyH3_wr70g0zAVV2WXTQ6wfZQZMAtMPBKQrKM_zHXu_y92h9U30_b1H2BZsdtP7rZEu6_f-1oyFN12-48JzTFAsjuh8I/s640/pla-1-right-content2.PNG" width="188" /></a></div>
<br />
It becomes clearer that the 3x inputs from PLA-2 (8062, 8061, 8060) form a "command" that narrows down which row will be selected. (Note that I've shown these 3x signals in the order that they enter PLA-1; similarly the earlier description shows these signals in the order that they exit PLA-2 - <b>but they are in a different order! </b>This is the way the chip is wired! So you need to remember to swap the bit ordering when you compare the data between the two PLAs!)<br />
<br />
Let's start by looking closer at the first command: "111" from PLA-2, which narrows the selection to rows 15-30. If we refer to the PLA-2 logic table & find which rows generate a "111" (remembering to reverse the bits, which happens to not matter in this case), we find it appears on three rows: 1, 3, and 4 (highlighted in light blue).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9xRbyz-h6xs52XJQr5vvnwd0LW5MHotYSu4w2XALNGFhF1VQ1JMELgCi-DFd6cetqQmlpZ-lMBpPL5SIO8PPklrf8wFrTiIhjNLW_TtOQMNb3FWTBn-bHJla04bJGRu-U451QEX6XdeQ/s1600/alu-decoder.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="324" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9xRbyz-h6xs52XJQr5vvnwd0LW5MHotYSu4w2XALNGFhF1VQ1JMELgCi-DFd6cetqQmlpZ-lMBpPL5SIO8PPklrf8wFrTiIhjNLW_TtOQMNb3FWTBn-bHJla04bJGRu-U451QEX6XdeQ/s640/alu-decoder.PNG" width="640" /></a></div>
<br />
All three rows are associated with the last (or only) cycle of a DP (Data Processing) instruction. So, returning to the PLA-1 table above, the signals on the Instruction Bus b24 to b21 are from a DP instruction. The DP instruction format is:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9BiuIHlneNQ9nRWErnVgSRtINbVin0Er1IiadGiGLHUgrNyVQboDwcIPZDFR68a40TnCDu6-kBwtCQ0EyE2fjh8MX9uQE5eZY6AmEgxKDLDmUhp7qatyW7ybkAnQY18BjiX49RXaU4F8/s1600/instruction-types.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="311" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9BiuIHlneNQ9nRWErnVgSRtINbVin0Er1IiadGiGLHUgrNyVQboDwcIPZDFR68a40TnCDu6-kBwtCQ0EyE2fjh8MX9uQE5eZY6AmEgxKDLDmUhp7qatyW7ybkAnQY18BjiX49RXaU4F8/s400/instruction-types.PNG" width="400" /></a></div>
<br />
And, as expected, we see that b24 to b21 correspond to the "Operation Code" - AND, OR, etc. So we can conclude that rows 15 to 30 of PLA-1 correspond to each ALU operation.<br />
<br />
By following a similar process and taking each of the remaining commands in turn we can gain some understanding of what rows 0..14 are for. However this analysis reveals lots of specific details - there is a lot of complexity here. The annotated PLA-1 row-selection table is as follows:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifGSgXRkrnKkIXGGhmvIZKTiuGlxjZnQwnFY7-1NZE9oYw-z_-L1xp2BaowaxtDxF_yPoZ0gXeS3FUY0ZghgYT_xzlT-gpx_0WPlN3FUtG-U9lJs1Snsni_4S2Ehp-UP45lo_tK45Ck_A/s1600/alu-decoder-2.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="513" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifGSgXRkrnKkIXGGhmvIZKTiuGlxjZnQwnFY7-1NZE9oYw-z_-L1xp2BaowaxtDxF_yPoZ0gXeS3FUY0ZghgYT_xzlT-gpx_0WPlN3FUtG-U9lJs1Snsni_4S2Ehp-UP45lo_tK45Ck_A/s640/alu-decoder-2.PNG" width="640" /></a></div>
<br />
What's clear from this table is that the ALU is being used for a lot more than the DP instructions that are visible to the programmer - almost half of this table is for other purposes! In the main the use of Instruction Register bits 24..21 makes sense given the context. The one exception is for command "000" (rows 0, 1 above); the Instruction Register bits are only valid & meaningful on a couple of the 9 rows this command is used. I suspect that this command is sometimes used as a "no-op".<br />
<br />
We can also perhaps gain some insight into what the signal "From Trap Ctrl (8158)" is. It only influences the row decoding for rows 6, 7 which is associated with LDR and LDM instruction execution. We know from the instruction descriptions that there are special rules in cases where a data fetch abort occurs:<br />
<br />
<ul>
<li>for the LDR instruction: "The data fetch may abort, and in this case, the base and destination modifications are prevented", </li>
<li>for the LDM instruction: "If an abort occurs...the final cycle is altered to restore the modified base register") </li>
</ul>
<br />
Perhaps this logic is to implement this functionality?<br />
<br />
<span style="font-size: large;">PLA-1 Content - Output Values</span><br />
<br />
Now that we've made an initial analysis of the input decoding, it's time to see what sense we can make of the output values. The table below is laid out to reflect the physical layout and therefore shows the output values on the LHS. There are also some notes on the left.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwyt5G6e7bwC2gUtAErYHltKQI_xPBeq4Mq_YGxMq4NIPahiyBrfr5KQEQegxv_h5robyFQ9j-4-9ELb-3Fr9y5P8RvDTKL1yn-ioQm7Tu1mtDd2K0R7-FzbOPQJEt3UDN8i_l41pFIjg/s1600/alu-decoder-full.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="394" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwyt5G6e7bwC2gUtAErYHltKQI_xPBeq4Mq_YGxMq4NIPahiyBrfr5KQEQegxv_h5robyFQ9j-4-9ELb-3Fr9y5P8RvDTKL1yn-ioQm7Tu1mtDd2K0R7-FzbOPQJEt3UDN8i_l41pFIjg/s640/alu-decoder-full.PNG" width="640" /></a></div>
<br />
There is an awful lot of information contained in this table!<br />
<br />
Let's start with the DP rows - 15 to 30:<br />
<br />
<ul>
<li>The good news is that on rearranging the order of the 6 right-most output columns, these values exactly correspond to the table that appeared in my <a href="http://daveshacks.blogspot.co.uk/2015/12/inside-alu-of-armv1-first-arm.html">first post on the ALU</a>! Whew!</li>
</ul>
<ul>
<li>If we now look at the output columns for 8087, 8088, we know from the earlier circuit diagram that these values determine what signal is fed to the Carry In on bit 0 of the ALU. And we only need to look at those rows where the output signal "/Enable C chain" (8116) is 0 (since the Carry signal is ignored otherwise). The comments on the left captures the results. The Carry In signal is set to exactly the values we would expect for associated op-code.</li>
</ul>
<br />
<br />
<ul>
<li>The first output, "To INST SKIP logic (8065)" is interesting in that it is only zero for the 4x comparison op-codes. About these op-codes the documentation states: "They are used only to perform tests and to set the condition codes on the result, and therefore should always have the S bit set" (we can see from the DP instruction format above that the S bit is defined as "Set Condition Code", 0 = Do not alter condition codes, 1 = Set condition codes). I suspect that this output from the PLA is used by the INST SKIP logic to detect if this is an invalid instruction.</li>
</ul>
<ul>
<li>The output "To PSR Logic (8064)" appears to control when the PSR is updated. Since 8064 is high for all the DP op-codes, and low for all other ALU operations, it probably controls when the Carry, Overflow, Negative, and Zero flag can be updated (subject of course to the S bit, as described earlier). </li>
</ul>
<ul>
<li>The output "To PSR Logic (8059)" is only high when an arithmetic operation (as opposed to a logical operation) is taking place. It therefore selects where the Carry flag is updated from - either the ALU output, or the result of the shift operation, and whether the Overflow flag is updated or not. See p2-32 of the <a href="http://bitsavers.informatik.uni-stuttgart.de/pdf/acorn/VTI_ARM_Databook_1990.pdf">VTI arm data book (1990)</a> for a more complete description of the rules regarding how the PSR bits are updated.</li>
</ul>
<br />
Now that we've completed analysing the DP instructions, let's move the remainder of the table - rows 0 to 14.<br />
<br />
To analyse rows 0 to 14 of the PLA-1 output table I assumed that the ALU would be carrying out similar operations to the DP instructions we've already been looking at. I therefore expected to see the same output settings on these rows as the rows we've already analysed. The results of this comparison work are shown in the Notes on the left of the table above. A summary is:<br />
<br />
<ul>
<li><b>Matches</b>: There are 8 rows with exact matches, and select a variety of ALU op-codes: MOV, ADD, SUB, RSB (reverse substract).</li>
<li><b>Variants</b>: A further 5 rows match, apart from the Carry In selection. These are described further below.</li>
<li><b>Unknowns</b>: Two rows have identical values, but don't match any DP instruction.</li>
</ul>
<div>
Let's look further at the variants. Although they appear on 5 rows, there are just two versions:</div>
<div>
<ul>
<li>ADD (but Cin = 1). The normal ADD has a Cin = 0, so this variant has the result = Op1 + Op2 + 1 (where Op1 and Ap2 are the two operands presented to the ALU).</li>
<li>RSB (but Cin = 0). The normal RSB has a Cin = 1, so this variant has the result = Op2 - Op1 - 1. </li>
</ul>
<div>
We can make educated guesses as to what is happening on each of these rows. For instance, on row 2, we are executing a Branch or Branch and Link instruction, and are almost certainly calculating the destination address by adding the PC to the PC-relative offset which appears within the instruction (we've seen in an <a href="http://daveshacks.blogspot.co.uk/2015/12/inside-armv1-read-bus.html">earlier article</a> how there is logic in the Read Bus B that extracts the 24 bit offset).</div>
</div>
<div>
<br /></div>
<div>
<span style="font-size: large;">Conclusion</span></div>
<div>
<br /></div>
<div>
It turns out that the ALU control logic is more complex than I expected. What is clear is that the chip designers really maximised the use of the ALU! </div>
<div>
<br /></div>
<div>
Whilst I've completely reverse-engineered the control circuitry, I've only made a start on unraveling what is actually going on. A full understanding requires some more analysis of the circuitry itself, and on getting a wider view on what is happening elsewhere on the chip. My list of "to-do" items includes:</div>
<div>
<ol>
<li>What exactly is the "unknown" ALU command we discovered above?</li>
<li>What values appear at the inputs to the ALU (Operand 1 and operand 2) for each of the rows above (this requires other parts of the processor to be reverse-engineering first). This will also give us a better understanding of why the variants to the ADD, RSB opcodes are introduced.</li>
<li>What exactly is being latched into the ALU's dynamic registers, and what is the sequencing associated with this? And why does the circuit above have the specific logic to introduce a one cycle delay for when DP instructions are executed?</li>
</ol>
<div>
<br /></div>
</div>
<br />
<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />Davehttp://www.blogger.com/profile/07363645951602549336noreply@blogger.com9tag:blogger.com,1999:blog-6068833812264712077.post-42972751338557405182016-01-18T08:15:00.000-08:002016-01-24T12:22:55.770-08:00Inside the armv1 - decoding barrel-shifter commandsThis is one of a number of posts on my work on reverse engineering the armv1 processor. The first in the series, and an index of the other articles can be found <a href="http://daveshacks.blogspot.co.uk/2015/12/inside-alu-of-armv1-first-arm.html">here</a>.<br />
<br />
Today I'm going to solve a puzzle I have been pondering for some time - how the processor implements instructions that reference 4 registers.<br />
<br />
If we look at the data processing (DP) instruction format in more detail, we see that there are the following instruction types:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM_F5MsOxlIThcjqdor0xkAmpSC2KKOnIsvmlTBWC0UdBckAmxuLpSszyN7kJ-GcM__03bWgt77Srvy25B7O7q7i8yBZfkQnky5J-axiPPWb-OkJXy5Vc1xjEXE1AjN9l9l-GuesQwpxE/s1600/instruction-types.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="497" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM_F5MsOxlIThcjqdor0xkAmpSC2KKOnIsvmlTBWC0UdBckAmxuLpSszyN7kJ-GcM__03bWgt77Srvy25B7O7q7i8yBZfkQnky5J-axiPPWb-OkJXy5Vc1xjEXE1AjN9l9l-GuesQwpxE/s640/instruction-types.PNG" width="640" /></a></div>
<br />
If we set Bit 15 to zero (Operand 2 in a register), and Bit 4 to one (Shift amount in a register) we get the following layout (made from copying/pasting portions of the image above):<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAB03mfHVtmC3o6FnZaMBkUaL5KefNRldIyv4vUMXF9NE2M_fBV2A6HNqL6aBBuIK-O0SVPr-px2iYPAhThbMKdewOglAILaAyrMTbBdbvhNg5kUd4dCV0cmjKyEeva1lpwRhb-OD8fUo/s1600/instruction-types-register-shift.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="424" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAB03mfHVtmC3o6FnZaMBkUaL5KefNRldIyv4vUMXF9NE2M_fBV2A6HNqL6aBBuIK-O0SVPr-px2iYPAhThbMKdewOglAILaAyrMTbBdbvhNg5kUd4dCV0cmjKyEeva1lpwRhb-OD8fUo/s640/instruction-types-register-shift.PNG" width="640" /></a></div>
<br />
This layout plainly shows this this single instruction references 4 registers simultaneously - Rd (the destination register), Rn (one of the ALU operands), Rm (the second ALU operand), and Rs (which gives the amount by which Rm is first shifted).<br />
<br />
However various architecture descriptions of the arm's Data Processing instructions only refer to there being two input operands and one output register. This matches the descriptions of two data read buses (referred to as "Bus A" and "Bus B" or "read bus A" and "read bus B"), and also matches there being just 3 sets of register select logic (which was explored in detail in an earlier post). So how does the processor execute an instruction which references 4 registers?<br />
<br />
A clue to solving this mystery was in my last post, where I analysed how the instruction decoder works. By referencing the first table in that post we see that the instruction decoder treats as a special case all Data Processing instructions where the shift amount is in a register. These instructions execute in 2 cycles, one more cycle that all other Data Processing instructions. It would be safe to bet that the first cycle extracts the shift amount from the Rs register and holds the value somewhere, and on the second cycle actually carries out the ALU operation.<br />
<br />
Let's now move to the processor itself to verify that our guess is correct. The area of the chip that we're interested in is highlighted in red below. Ken Shirriff has already given an overview of how the barrel shifter works <a href="http://www.righto.com/2015/12/reverse-engineering-arm1-ancestor-of.html">here</a>:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTcpVpmCCNO_GKgaxhHmQU5RFuXAN_17or_I49_JGYX66UHm4H-TwADNo_IhdMPGEQoyf5gnP_ixJh5HCWLAcioeFqkBkASATja3fyTs8qV6D3Kt6XdX2wm_sIF0T1VZtxaDp0G93mL64/s1600/barrel-decoder.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTcpVpmCCNO_GKgaxhHmQU5RFuXAN_17or_I49_JGYX66UHm4H-TwADNo_IhdMPGEQoyf5gnP_ixJh5HCWLAcioeFqkBkASATja3fyTs8qV6D3Kt6XdX2wm_sIF0T1VZtxaDp0G93mL64/s640/barrel-decoder.PNG" width="630" /></a></div>
<br />
<br />
If we zoom in a little further, we see that there are two distinct sections in this area:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgX99dfOYYmSrsHy7N5YrvSo-XVwXMIqZ5CY-CC8QPRd-UFX5wJ7sqMVzQ3huXIpYq-1q_6zQsn-mDm2d04b3oaejpbHQjghjltsm9GZ7JqlmgKWWBQfhZtRo7c9wk122tdOhsGv3Tmgtk/s1600/barrel-decoder-detail.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgX99dfOYYmSrsHy7N5YrvSo-XVwXMIqZ5CY-CC8QPRd-UFX5wJ7sqMVzQ3huXIpYq-1q_6zQsn-mDm2d04b3oaejpbHQjghjltsm9GZ7JqlmgKWWBQfhZtRo7c9wk122tdOhsGv3Tmgtk/s640/barrel-decoder-detail.PNG" width="614" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
The lower area generates the column drive signals to the barrel shifter itself. The shift-amount and shift-type is via signals originating in the upper "Barrel Shifter Decode Selection" logic. We won't look at the driver logic in any further detail in this post. Instead we turn to the upper section, and start by zooming in some more:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNN2723tUDots50LoGCpL_DphXRaoYdy3QEkq8v9Rch-sS1_qcBtGUMaWiwu5AAHNj-l2jj5bXFrmt5_Js2qLrxjeTZyg0UOHnoo7VJX3MsUkboA25fDTSgqI7AyQaurQAoG400Wzjymc/s1600/barrel-decoder-io.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNN2723tUDots50LoGCpL_DphXRaoYdy3QEkq8v9Rch-sS1_qcBtGUMaWiwu5AAHNj-l2jj5bXFrmt5_Js2qLrxjeTZyg0UOHnoo7VJX3MsUkboA25fDTSgqI7AyQaurQAoG400Wzjymc/s640/barrel-decoder-io.PNG" width="608" /></a></div>
<br />
The layout of this upper section is spectacular in that all the inputs and outputs to the logic are very readily apparent, and are marked on the diagram:<br />
<br />
<ul>
<li>The I-Bus inputs b11..b5 correspond to the Shift Amount (b11..b7) and Shift Type (b6..b5) that we saw in the instruction layout we looked at above. </li>
<li>The outputs on the RHS - Shift Amount (5 bits) and Shift Type (2 bits) are the signals that feed the Barrel Shifter Driver Logic that we saw earlier. </li>
<li>The 3x outputs from the PLA (nodes 8287, 8288, b286) that enter the area from above correspond to columns 2, 3, 4 of the PLA output table I included in my last blog.</li>
<li>Two signals derived from the lowest two address outputs lines enter the area from above and to the right.</li>
<li>4x signals associated with Carry processing enter/exit from the lower edge.</li>
</ul>
<div>
The main logic areas are also apparent:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9thV7bVFikwTYbuQHDK9OwrgXHvhO9YKkm4BzztoNHkXN34nIVrBB9319_D3wKtg-aq0yZX_BqichsNZqxmgpBrnQXVE1JXyZu1U4XOYW75byB8Jn7cdOOb-ffLx7foHmUR96kzeWk0Y/s1600/barrel-decoder-functional.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9thV7bVFikwTYbuQHDK9OwrgXHvhO9YKkm4BzztoNHkXN34nIVrBB9319_D3wKtg-aq0yZX_BqichsNZqxmgpBrnQXVE1JXyZu1U4XOYW75byB8Jn7cdOOb-ffLx7foHmUR96kzeWk0Y/s640/barrel-decoder-functional.PNG" width="584" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
We've found the 8-bit wide dynamic latch that stores the register-sourced shift-amount from the Read Bus!</div>
<div>
<br /></div>
<div>
The other key logic is the group of seven 6-way multiplexers, whose outputs feed via the seven drivers to the rest of the barrel-shifter logic.</div>
<div>
<br /></div>
<div>
The 3 to 8 decoder is driven from the 3x PLA outputs (nodes 8287, 8288, b286) and 6 of its outputs select which of the 6-way multiplexer inputs is chosen. A further output controls the Dynamic latch, and the final 3 to 8 decoder output is not implemented.</div>
<div>
<br /></div>
<div>
The remaining logic that is not highlighted in the diagram is complex and convoluted; it's task is to ensure that the correct shift results occur, even when a shift amount greater than 32 is selected. This includes ensuring that the Carry bit is set appropriately and that the sign bit is extended in the correct manner. The rules are described on page 2-34 of the <a href="http://bitsavers.informatik.uni-stuttgart.de/pdf/acorn/VTI_ARM_Databook_1990.pdf">VTI arm databook (1990)</a>. I won't dwell further on this part of the circuit.</div>
<div>
<br /></div>
<div>
The dynamic latch circuitry and associated latch processing is straightforward:</div>
<div>
<br /></div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPIUU_7ZmtRPk7aiebPMdQC7fpJXV8srXHf3SEWcRdJUQm1JkhRa3jIUOIZDGO3Qy4xZpArnzTdCLt4613Etr0bWdZr1LF463nnpeUqaeitHohiiYNdAZAtyjo_K6mWU2p0r_MahDbbPg/s1600/barrel-register.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="237" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPIUU_7ZmtRPk7aiebPMdQC7fpJXV8srXHf3SEWcRdJUQm1JkhRa3jIUOIZDGO3Qy4xZpArnzTdCLt4613Etr0bWdZr1LF463nnpeUqaeitHohiiYNdAZAtyjo_K6mWU2p0r_MahDbbPg/s320/barrel-register.PNG" width="320" /></a></div>
</div>
<br />
<br />
The data on the Read Bus is latched during phase 1 of the clock only when output 7 of the 3-to-8 decoder has been selected (i.e. all 3x inputs from the PLA are high). The latched data (or zero) is then available on one of the 6 inputs to the multiplexer. Zero is selected depending on the complex logic referred to earlier.<br />
<br />
The output driver circuitry for each of the 7 signals is just two inverters in series.<br />
<br />
The multiplexer circuitry, and decoding circuitry, is identical in form to the read bus input multiplexer I described in my <a href="http://daveshacks.blogspot.co.uk/2015/12/inside-armv1-register-bank-register.html">earlier blog on register selection</a>, and won't be repeated here.<br />
<br />
Just the following "glue logic" circuits generate additional inputs to the multiplexer:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXyd1bo2Jw55-MKNB5qWyBKlO0P2OVifmx9EBBZEQlsO0CfW7xea1ff5kIoQDX4qfPs0o5Ene59o-Q4rgflESo06dWv4hFQpxpejG12oIZdJYfRDrpKaLwIG-CS3GZILbcbRybYq5gJZQ/s1600/barrel-additional-logic.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="351" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXyd1bo2Jw55-MKNB5qWyBKlO0P2OVifmx9EBBZEQlsO0CfW7xea1ff5kIoQDX4qfPs0o5Ene59o-Q4rgflESo06dWv4hFQpxpejG12oIZdJYfRDrpKaLwIG-CS3GZILbcbRybYq5gJZQ/s400/barrel-additional-logic.PNG" width="400" /></a></div>
<br />
<div>
Note how the Shift Type in I-Reg b6 and I-Reg b5 are potentially adjusted, dependent on complex logic, in a similar manner to how the shift-amount described earlier might be adjusted.</div>
<br />
The table below summarises the multiplexer's operation, and lists what the 7x outputs to the Barrel Shift Driver Logic are for each of the 8 combinations on the 3 signals from the PLA.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2ACmOgF8gvB2svo6w_sHtyWuRFPmbVmVGWoahANrmFsul1t9zRQljUc0o3GoqM7zochyphenhyphenO4q-99kamkCZVpRsyggbftTEnE609cYn9sKtxnIw6l0yEsh28te11PsrMaCJZ7XwlWlVeYhI/s1600/barrel-mux.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="148" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2ACmOgF8gvB2svo6w_sHtyWuRFPmbVmVGWoahANrmFsul1t9zRQljUc0o3GoqM7zochyphenhyphenO4q-99kamkCZVpRsyggbftTEnE609cYn9sKtxnIw6l0yEsh28te11PsrMaCJZ7XwlWlVeYhI/s640/barrel-mux.PNG" width="640" /></a></div>
<br />
If we compare these PLA values, and the barrel-shifter outputs, with the values in the PLA output table from my previous article, it starts to makes sense.<br />
<br />
Let's take row 1 of the PLA table as the first example. This row decodes a Data Processing instruction where Operand 2 is a register and the shift amount is immediate (i.e. the amount is in the instruction). The PLA values fed into the table above are "001" (row 1). This selects that the Shift Amount and Shift Type sent to the Barrel Shifter Driver Logic is b11..b5 of the DP instruction, exactly as we would expect.<br />
<br />
Now let's examine an instruction that has the shift amount in a register - the situation I began this blog with. We see from the PLA table that this instruction type takes two cycles to execute (rows 2 and 3). The PLA values fed into the table above on the first cycle are "111" (row 7), which is a command to latch the content of the register which is present on the read bus. The PLA values on the second cycle are "000" (row 0), which feed the (possibly modified) values of the latch (for the shift amount) and the instruction's Shift Type to the Barrel Shifter Driver Logic.<br />
<br />
We can now deal with the remaining PLA input types:<br />
<br />
<ul>
<li>"010" - this appears in a number of lines in the PLA output table where the result of the ALU is not used, and ensures the Carry bit, etc. are not inadvertently affected. It can be regarded as a no-op.</li>
<li>"011" - appears only on row 27 of the PLA output table, and corresponds to the first instruction cycle of a Branch or Branch and Link instruction. In these cases the immediate value in the instruction is a word address, and the Barrel Shifter is instructed to shift this value left by two to convert it to a correct memory address.</li>
<li>"100" - appears only on row 4 of the PLA output table, and corresponds to a DP instruction where operand 2 is immediate. In this case the value to be rotated is in the lowest 8 bits of the instruction, and is to be rotated right by twice the amount in b8..11 of the instruction (see the instruction format at the beginning of the blog). The "glue" logic chooses a Shift Type of "11" (Rotate Right) when the shift amount is non-zero or "00" (LSL) for when a 0 shift is selected.</li>
<li>"101" - appears on row 7 and row 12 of the PLA output table. These both correspond to the last cycle of a LDR (Load Register from memory) instruction. Here, the Shift Amount is x8 the value appearing on Address line a0, a1. These address lines are only non-zero if a byte access has occurred, so this means that the lowest 8 bytes of data that has just been read from memory is rotated into it's correct position before being output from the barrel-shifter.</li>
</ul>
I ignored the reserved/undocumented instruction in the analysis above. However, even though our reverse-engineering of the chip is far from complete, from the information available we already know quite a lot about variant 1 of the reserved instruction:<br />
<br />
<ul>
<li>Cycle 0 (row 15): selects "111" to save a register value in the barrel-shifter latch.</li>
<li>Cycle 1 (row 16): selects "000", which shifts the number now on the read bus by the amount in the latch</li>
<li>Cycle 2 (row 17): selects "001", perform a further shift, by the amount, and type specified in the instruction.</li>
<li>Cycle 3 (row 18): selects "101", which corresponds the byte rotate operation associated with a LDR instruction.</li>
</ul>
<div>
From this set of steps we can make a guarded guess that this instruction is loading data from memory, and that, since it takes one more cycle than a standard LDR instruction, the address is calculated using the content of one register as a shift amount, in addition to the typical LDR address calculation. Our being able to accurately predict what the reserved instructions do will be a good test of the accuracy of the reverse-engineering!</div>
<div>
<br /></div>
<div>
<span style="font-size: large;">Conclusion</span></div>
<div>
<br /></div>
<div>
We've now reverse-engineered the main logic associated with controlling the barrel-shifter. There remains some logic still to reverse-engineer for us to fully understand all the edge cases, but fortunately this logic is very isolated and does not detract from our wider understanding of how the barrel-shifter works and is controlled. We have also found that the barrel-shifter is put to extensive use for a variety of tasks, not just for the Data Processing (DP) instructions. We also have garnered some "teaser" information about one of the reserved instructions.</div>
<div>
<br /></div>
<div>
<br /></div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />Davehttp://www.blogger.com/profile/07363645951602549336noreply@blogger.com8tag:blogger.com,1999:blog-6068833812264712077.post-83623146375922825222016-01-10T09:58:00.000-08:002016-01-24T12:23:12.005-08:00Inside the armv1 - instruction decoding and sequencingThis is one of many posts on my work on reverse engineering the armv1 processor. The first in the series, and an index of the other articles can be found <a href="http://daveshacks.blogspot.co.uk/2015/12/inside-alu-of-armv1-first-arm.html">here</a>.<br />
<br />
Today, we'll explore the area that I labelled PLA2 in an earlier article:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9b8oUWQaV8YNC1LI06VD8Kr9vAAlnqYoKFJnTiTfN8Y5Vdi9FsMxRMkc7QlCKWOP_6MkV0FX9rQSD5Ct3FgBLZcwN0xRolqtTQnh_GJ0wIAAqyMpDcUdE_4-xoeYasQMcrGh2K4v-nYA/s1600/silicon-regions.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9b8oUWQaV8YNC1LI06VD8Kr9vAAlnqYoKFJnTiTfN8Y5Vdi9FsMxRMkc7QlCKWOP_6MkV0FX9rQSD5Ct3FgBLZcwN0xRolqtTQnh_GJ0wIAAqyMpDcUdE_4-xoeYasQMcrGh2K4v-nYA/s640/silicon-regions.PNG" width="628" /></a></div>
<br />
<br />
We know that PLA2 is an important part of the chip, partly because a substantial portion of silicon has been allocated for it, and partly because in our reverse-engineering efforts we have already found lots of signals tracing back to it. I had been putting off looking at it because I feared it would be a "sea of logic" and contain lots of ad-hoc and difficult to understand calculations. However my interest was piqued when by chance I noticed whilst stepping through various instructions that only a single row within the PLA was active at a time - clearly there was more structure to the logic than I was expecting. It became even more interesting when I realised that the main inputs to the PLA were the "special" I-Reg signals that I'd found earlier my <a href="http://daveshacks.blogspot.co.uk/2015/12/inside-armv1-read-bus.html">earlier</a> post: bits 4, 20, 24, 24, 26, 27 of the I-Reg are separately wired directly (and only) to the PLA input!<br />
<br />
Before we embark any further, let's zoom in on the PLA layout:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQMrefpjPWmjkohpfummsaEuujPjCq4gTPpj_RBD3vkF_W4I1tLpQi49ep4-4QAUVNX0k-j30ydmoxWIyTKCr_CH5Ugs3gluUx2NZZxpKCjfoAFvA1_HURMXjG9-f1GACDxk7VmYmRZu4/s1600/pla-2.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQMrefpjPWmjkohpfummsaEuujPjCq4gTPpj_RBD3vkF_W4I1tLpQi49ep4-4QAUVNX0k-j30ydmoxWIyTKCr_CH5Ugs3gluUx2NZZxpKCjfoAFvA1_HURMXjG9-f1GACDxk7VmYmRZu4/s640/pla-2.PNG" width="595" /></a></div>
<br />
Ten input signals arrive at the top right and the signals, and their inverted versions, feed the 20x vertical columns on the right and intersect 42 horizontal rows. At each intersection there can be one of three options:<br />
<br />
<ol>
<li>A transistor for the non-inverted signal, OR</li>
<li>A transistor for the inverted signal, OR</li>
<li>No transistor</li>
</ol>
<div>
By default the horizontal line is pulled high, and if any transistor on any vertical intersections is turned on, the horizontal line is pulled low. The way the transistors are cunningly placed ensures that only one horizontal line is pulled low at any time.</div>
<br />
<br />
By knowing the source of at least some of the inputs and working through where the transistors are placed it was possible to build up the logic table below:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjO7zEloC8JYICfou_B3zmca06HMsGvvW9u-Dpsq0F0B1nc-Qq-LeF8c7Dnq3Eb2ny6H6BG_A099sWdEvQB-W1Hq1dQ1mWvXz8i377quCEj_z-GERCIFmRZtE8fQcBtpPtI6UFjsSsv0yk/s1600/pla2-decoding.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="470" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjO7zEloC8JYICfou_B3zmca06HMsGvvW9u-Dpsq0F0B1nc-Qq-LeF8c7Dnq3Eb2ny6H6BG_A099sWdEvQB-W1Hq1dQ1mWvXz8i377quCEj_z-GERCIFmRZtE8fQcBtpPtI6UFjsSsv0yk/s640/pla2-decoding.PNG" width="640" /></a></div>
<br />
On the left of the table is where the transistors are in the layout. An 'x' marks where no transistor was fitted and is a "don't care" in the decoding. On the right I've broken out the logic represented by the transistor placements in a step-by step manner:<br />
<br />
The first column on the right shows only the top row is active when the "Init" input is 0; every other column input on this row is "don't care". All remaining rows require the "Init" input to be 1 in order to be selected.<br />
<br />
The second column breaks down the case of "Init" = 0 - in this case the Interrupt signal divides the remaining columns into two sections rows 1-38 for Interrupt = 0, and rows 39-41 for Interrupt = 1.<br />
<br />
Note that I've made a best-guess at the names for these first two input bits based on what signals are present during experiments with reset and interrupt processing.<br />
<br />
The third column divides the input into 7 major instruction types, depending on the "special" I-Reg inputs that I mentioned earlier. The following columns then break the instructions into finer and finer categories.<br />
<br />
By studying the table it's possible to see how the decoding options have been constructed so that every input combination on ever decodes to a single output - brilliant.<br />
<br />
You'll notice that most instructions decode to several rows in the table, with just input signals FSM 0, 1 differentiating them (e.g. LDM decodes to lines 21-24). Again the signal names FSM 0, 1 are mine and allude to the operation appearing to be not unlike a Finite State Machine. Each row is a different stage/cycle in the instruction's execution. Most instructions simply step through each row on successive clock cycles and therefore the number of rows in the table above shows how long it takes each instruction to execute. There is one exception to this, which is for the LDM/STM instruction pair. These instructions load/store between 1 to 16 registers to memory, depending on a 16 bit bit-pattern. In these cases the processor stays in a single state "looping" until all registers have been loaded/saved. This can be seen in the animation below which shows the execution of an LDM instruction which loads 8 registers.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxrKVMoGqoiTJpjCKNJnLZXpdz21yLiQRDietKxZ57EGu1iqQhltq6-NmUGzMvnR7lsDyMu08Hwn_WHcK1KL4E3hKW5-DNPsRuJIkh9CFmXPyJlDhWdnkFuC3CWRbYa5qYwBnbY6P9x0I/s1600/ldm-anim.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxrKVMoGqoiTJpjCKNJnLZXpdz21yLiQRDietKxZ57EGu1iqQhltq6-NmUGzMvnR7lsDyMu08Hwn_WHcK1KL4E3hKW5-DNPsRuJIkh9CFmXPyJlDhWdnkFuC3CWRbYa5qYwBnbY6P9x0I/s400/ldm-anim.gif" width="400" /></a></div>
<br />
On the first cycle it "executes" row 21, then row 22, then loops on row 23 for each register, and finally "executes" row 24 before the processor moves to the next instruction.<br />
<br />
There is a huge amount that can be learnt from studying the decoding table above:<br />
<br />
First, only two instruction variants execute in a single cycle; many take 2 or 3 cycles.<br />
<br />
Second, it's surprising to see that Coprocessor instructions are being decoded; this functionality is not otherwise present on this chip and only introduced on its successor, the VL86C010 (more details on this chip are available <a href="http://bitsavers.trailing-edge.com/pdf/acorn/VTI_ARM_Databook_1990.pdf">here</a>).<br />
<br />
Third, rows 15-20 decode some instructions that are not documented. What's more, this part of the "instruction space" is explicitly declared as "undefined(reserved)" on page 2-49 of the VL86C010 documentation. Perhaps with some more reverse-engineering we'll be able to confirm what these instructions do on this chip.<br />
<br />
The left side of the PLA determines what the output signals will be. The presence/absence of a transistor at an individual row/column intersection determines the output on that column. The content of the left side is shown below:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOn7_UHSshx7RxrCPG8CGvhDrV3Zhktku-dE_9dmkuzSewf7ZPbieXWU6qnQAk_Yq67xZYCpDU9G-2eWpg_hY3fFpySuSMN6UklCr3mqfQSMRhni-51aI7tFsXK-w2-Ae0A_pOgHPn4f8/s1600/pla2-output.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="456" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOn7_UHSshx7RxrCPG8CGvhDrV3Zhktku-dE_9dmkuzSewf7ZPbieXWU6qnQAk_Yq67xZYCpDU9G-2eWpg_hY3fFpySuSMN6UklCr3mqfQSMRhni-51aI7tFsXK-w2-Ae0A_pOgHPn4f8/s640/pla2-output.PNG" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
(The vertical coloured stripes mark those outputs that I have reverse-engineered to date).<br />
<br />
The output signals control other parts of the chip in a wide variety of ways. The simplest example is where output 8630 (about the middle column in the table above) which is connected directly to the chip's "opc" output pin. The opc pin indicates when the processor is fetching an instruction, so it is perhaps not surprising that this signal is set on the first cycle of most instructions in the table above. (There's interesting exceptions with the branch, software-interrupt, and co-processor instructions).<br />
<br />
Another example is that outputs 8040, 8041, 8042 select where Read Bus A's register number is chosen from. As was described in an <a href="http://daveshacks.blogspot.co.uk/2015/12/inside-armv1-register-bank-register.html">earlier article</a> these 3 bits will select between 5 different sources for these bits, and it's reassuring to scan down the columns above and note that only 5 different values are used throughout.<br />
<br />
Preliminary analysis indicates that PLA outputs 8309, 8310 influence how the FSM input signals are generated, which is why I've I refer to them as Finite State Machine variables.<br />
<br />
<span style="font-size: large;">Conclusion</span><br />
<br />
This analysis has given me a great insight into the way the processor's instructions are decoded and sequenced. The content of the PLA can almost be regarded as a set of instructions for a micro-instruction machine with very wide instructions (33 bits from the PLA plus 32 bits from the I-Register).<br />
<br />
The PLA is implemented using approx. 1,100 transistors.<br />
<br />
<br />Davehttp://www.blogger.com/profile/07363645951602549336noreply@blogger.com15tag:blogger.com,1999:blog-6068833812264712077.post-23689627905437404012016-01-03T05:09:00.000-08:002016-01-24T12:23:27.753-08:00Inside the armv1 - the Read Bus B, ALU Output Bus, and Address BusThis is my fifth post describing the armv1. My earlier posts can be found here:<br />
<br />
<ul>
<li><a href="http://daveshacks.blogspot.com/2015/12/inside-alu-of-armv1-first-arm.html">Inside the ALU of the armv1 - the first ARM microprocessor</a></li>
<li><a href="http://daveshacks.blogspot.com/2015/12/inside-armv1-register-bank.html">Inside the armv1 Register Bank</a></li>
<li><a href="http://daveshacks.blogspot.com/2015/12/inside-armv1-read-bus.html">Inside the armv1 Read Bus</a></li>
<li><a href="http://daveshacks.blogspot.com/2015/12/inside-armv1-register-bank-register.html">Inside the armv1 Register Bank - register selection</a></li>
</ul>
<div>
Ken Shirriff has also written about the arm internals <a href="http://www.righto.com/2015/12/reverse-engineering-arm1-ancestor-of.html">here</a>.</div>
<div>
<br /></div>
<br />
In this blog I'll finish describing the remaining buses - Read Bus A, the ALU Output Bus, and the Address Bus. I covered Read Bus A in an earlier post. To help set the context I reproduce the chip floorplan (but remember, this diagram incorrectly labels read bus A and read bus B the wrong way around):<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4YPuaQt0O_Buliq5BfjY5JJrdhapg-lsevEX7K8EF6RaV_MM-LiBb17nn3DPIqFy8hHZ4ATN-CgEx4r5_IxazTau3iPL3EfoCA7-P70hy0T-jLWJgUBn3v711Nja-gGY5ikP19PdK4dU/s1600/floorplan.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="368" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4YPuaQt0O_Buliq5BfjY5JJrdhapg-lsevEX7K8EF6RaV_MM-LiBb17nn3DPIqFy8hHZ4ATN-CgEx4r5_IxazTau3iPL3EfoCA7-P70hy0T-jLWJgUBn3v711Nja-gGY5ikP19PdK4dU/s400/floorplan.PNG" width="400" /></a></div>
<span style="font-size: large;">Read Bus A</span><br />
<br />
This should be a simple bus, as according to the floorplan, the output of the second read port of the register bank should just feed the ALU port. But it turns out it's not quite so simple:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9vQ0vlwC0fjbDitdCVIkMsiJ6rrriAoQReh4Ij0EoT37lilVM52UlCVQtH5tv3m-JwWmhFLJ0LAGShv-LLalUVy3YOGOk_qb4o-9Oj1OCNhYV-J4fs_gqAACmfVWtB-6WjLTVVUZWEfo/s1600/read-bus-b.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9vQ0vlwC0fjbDitdCVIkMsiJ6rrriAoQReh4Ij0EoT37lilVM52UlCVQtH5tv3m-JwWmhFLJ0LAGShv-LLalUVy3YOGOk_qb4o-9Oj1OCNhYV-J4fs_gqAACmfVWtB-6WjLTVVUZWEfo/s400/read-bus-b.PNG" width="400" /></a></div>
<br />
<br />
It turns out that the bottom 8 bits also feeds the Shift Decoder logic. This path is needed for the processor to implement the shift-option where a register specifies the number of bits by which the input operand is shifted.<br />
<br />
The other surprise is that there is an option for b0 to b5 to be sourced from the BIT CTR logic. This path is to implement the LDM/STM instructions - the first register to be loaded/saved needs to be offset from the base-register by the number of registers selected (depending on the instruction options).<br />
<br />
Otherwise Read Bus A is like Read Bus B in that it relies on a precharge (driven by the phi 2 clock), and is inverted logic.<br />
<br />
<span style="font-size: large;">ALU Output Bus, Incrementer, and Address Bus</span><br />
<span style="font-size: large;"><br /></span>
The reverse-engineered circuitry associated with the ALU Output Bus, Incrementer, and Address Bus is as follows. This is the circuit associated with bit 3:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNDZHYGfbzRS2LW3q2BQ9PC2jdqHkB0NnQttLfpAixcLxM5x6yvNUf2dULXV8Ks8SSEgkJj8HM11rP-AHhmEfUh9fg0_UGi_GaStOixevW44K4KPj8RB0Qxm97utFW42aDb8XpMzrLPOs/s1600/address-bus.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="362" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNDZHYGfbzRS2LW3q2BQ9PC2jdqHkB0NnQttLfpAixcLxM5x6yvNUf2dULXV8Ks8SSEgkJj8HM11rP-AHhmEfUh9fg0_UGi_GaStOixevW44K4KPj8RB0Qxm97utFW42aDb8XpMzrLPOs/s640/address-bus.PNG" width="640" /></a></div>
<br />
Note that the Address Bus/Incrementer circuitry has two extra connections into the r15 (PC) register cells: an additional read signal, and an additional write signal. The new write signal operates in exactly the same way as described in my earlier post (shorts the output of one of the inverters).<br />
<br />
The incrementer circuitry is in the centre of the diagram and comprises the 3x exclusive-nor gates, and 2-input nor gate. The control line input (7091) determines whether the circuit increments or decrements the input value (there's more about this control line below).<br />
<br />
As with ALU described in an earlier blog, the input values to the incrementer are captured and stored by the transmission gate during the phase 1 clock time. The Carry In/Carry Out logic is slightly different for odd/even bits. This is also as described in the ALU and is to eliminate an inverter per bit and so reduce propagation delays. The Carry In signal on the first bit of the incrementer is hard-wired to 1.<br />
<br />
Also note that the lowest 2 bits and the highest 6 bits of the PC are absent, leaving just 24 bits with circuit above. For the remaining 8 bits the incrementer isn't populated and the associated multiplexer input bits are set to zero.<br />
<br />
The input to the incrementer is chosen by a 4-way multiplexer. The multiplexer is shown in simplified form here as the details are very similar to what we've seen already (e.g. Read Bus Decoding).<br />
<br />
The circuit above is a little more complex than I was expecting. By experimenting with some sample programs the following becomes apparent:<br />
<br />
<ul>
<li>When an instruction updates the PC (e.g. mov pc, r0), the register is updated directly through the write-select line as with any other register write; however in addition, the write value is also selected via input 1 of the multiplexer so that it can be latched by the transmission gate and be incremented ready for fetching the next instruction.</li>
<li>When a LDM/STM instruction executes (Load/Store multiple registers), the transmission gate captures the starting load/store address and the incrementer updates the address for each of the registers to be loaded/stored. Only when the last register is loaded/saved is the transmission gate re-initialised with the PC value.</li>
</ul>
<br />
The 0-input to the multiplexer varies depending on the bit, as shown in the table below.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiS7AZxTKUV4vg0zkQpccbZgEYZg8W_cUMa8foIx9k-bWhzZ9hOYEBKCuCO_Lou0BXL1H11-qndKLaR9AOVwlFQdsIF6sFIydEmowGgSq97iBGp04lViUxqXjGDowXAClJlZaa5toAjjlc/s1600/pc-bit.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiS7AZxTKUV4vg0zkQpccbZgEYZg8W_cUMa8foIx9k-bWhzZ9hOYEBKCuCO_Lou0BXL1H11-qndKLaR9AOVwlFQdsIF6sFIydEmowGgSq97iBGp04lViUxqXjGDowXAClJlZaa5toAjjlc/s1600/pc-bit.PNG" /></a></div>
<br />
These 3x inputs come via inverters from the TRAP CTRL region of the chip and are associated with selecting the interrupt dispatch address as per the Vector Table below:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlPQrUXFAxGIWY0Uheg2FDjWzVTNvd97CAJ3l-6dNdTSe91zIXELDPebWJ5pwXap6lsY6yc6JFi4_8IUVdfyKradWvzFAACbbkdGGihiQ3d9zsThdgp7LV-bfIn88lIX9LJ7ENU8dNUcY/s1600/vector-table.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlPQrUXFAxGIWY0Uheg2FDjWzVTNvd97CAJ3l-6dNdTSe91zIXELDPebWJ5pwXap6lsY6yc6JFi4_8IUVdfyKradWvzFAACbbkdGGihiQ3d9zsThdgp7LV-bfIn88lIX9LJ7ENU8dNUcY/s1600/vector-table.PNG" /></a></div>
<br />
<br />
Reverse engineering of the control signal 7091 is especially puzzling. The circuit is:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyHhCvAd9gNUYv4rnA8Y80WNTNJQeWsmx51gJJhAjqFadLUxpE8CopzS8wQYvreYFbefPFeBy7bpS1hJgqfQ3PVImDdl4PRORPXf47rmtPVaSxcO6fQ6Zk8_oqf8TwX95r6i2oAamgY84/s1600/control-signal-7091.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="192" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyHhCvAd9gNUYv4rnA8Y80WNTNJQeWsmx51gJJhAjqFadLUxpE8CopzS8wQYvreYFbefPFeBy7bpS1hJgqfQ3PVImDdl4PRORPXf47rmtPVaSxcO6fQ6Zk8_oqf8TwX95r6i2oAamgY84/s400/control-signal-7091.PNG" width="400" /></a></div>
<br />
This circuit really is a complex way of generating a 1 output! If this control signal is genuinely always 1 then the incrementer circuit could be substantially simpler - 2 of the exclusive nor gates could be eliminated altogether. On reviewing the chip layout itself it becomes stranger still (the image below is rotated 90 degrees):<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNXnPZCjlO4yTfmYp_m11PbBC9gxxRcQxdLe60VGhkT5-gm5ps-zq-7exVi_695gb9I86e9XbvTMiLYXd01CgC1x2cMmj05tO9Swl-jrrVR5M_2ROFcwQ3vwmzw67ox4qcp1O3jt6KRCM/s1600/control-signal-7091-ctd.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="152" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNXnPZCjlO4yTfmYp_m11PbBC9gxxRcQxdLe60VGhkT5-gm5ps-zq-7exVi_695gb9I86e9XbvTMiLYXd01CgC1x2cMmj05tO9Swl-jrrVR5M_2ROFcwQ3vwmzw67ox4qcp1O3jt6KRCM/s640/control-signal-7091-ctd.PNG" width="640" /></a></div>
<br />
The 0 input signals are routed a long way from the transistors themselves, even though a ground signal is right nearby, and the output, which goes nowhere, is routed in a similar area. Is it possible that part of the circuit was intended for some additional functionality which was partially implemented and then disabled at a late stage in the layout process? Any suggestions would be welcome.<br />
<br />
<span style="font-size: large;">Address Output Pins</span><br />
<br />
The circuitry associated with the address output pins is very straightforward:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggEh40Is7X3m-dwnyQUI1LTUtV374zWWLez3eyEIsR2tCyvCDdqtObp6zFLSKfp2Oiy80KhTFFmdW95FgVnJr_gg90KTKFxwUbM4Vqh3d6mhdDowj-v2lfknPz-p4A3Y6Xsv-yGimCGvU/s1600/address-pad.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="251" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggEh40Is7X3m-dwnyQUI1LTUtV374zWWLez3eyEIsR2tCyvCDdqtObp6zFLSKfp2Oiy80KhTFFmdW95FgVnJr_gg90KTKFxwUbM4Vqh3d6mhdDowj-v2lfknPz-p4A3Y6Xsv-yGimCGvU/s400/address-pad.PNG" width="400" /></a></div>
With aen_internal held low the address pins go into tri-state mode.<br />
<br />
<span style="font-size: large;">Conclusion</span><br />
<br />
We've now reverse engineered all the remaining internal data and address buses and learnt how the incrementer circuit is used both the update the PC and to implement the LDM/STM instruction. We're reverse-engineered about 2,200 transistors in the circuits above.<br />
<br />
<br />
<br />Davehttp://www.blogger.com/profile/07363645951602549336noreply@blogger.com9tag:blogger.com,1999:blog-6068833812264712077.post-25723635819414408332015-12-31T06:38:00.001-08:002016-02-13T05:06:21.303-08:00Inside the armv1 Register Bank - register selectionIn an earlier post I reverse engineered the register bank, but stopped once I had identified the b3..b0 inputs for each of the 3 sets of register select logic. This information was summarised in a table which I've copied below:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrnyD7fwQh5XC-qLCoAgi7akUza2dCyWVRCJiE8EYj1ijq4xo7Oiqtp-un_f8T2MXdhjuaIQfOrNa3Ql_liS5iCLvczEJLN8KaF1-Woo8kOBa9b8QdEwprtVzEr0wU1ENaFhr2q1u_DnE/s1600/select-lines.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="130" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrnyD7fwQh5XC-qLCoAgi7akUza2dCyWVRCJiE8EYj1ijq4xo7Oiqtp-un_f8T2MXdhjuaIQfOrNa3Ql_liS5iCLvczEJLN8KaF1-Woo8kOBa9b8QdEwprtVzEr0wU1ENaFhr2q1u_DnE/s400/select-lines.PNG" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
Now that we have identified the Instruction Register it becomes practical to identify how these signals are derived.<br />
<br />
Let's start with Read Bus B, bit 3:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEherwHYIYBjuYjU3lm9tMPrVRoWucib-16OkT6LM1dTEnplCBrCCJ6xQw_UZrI-CzAgTfpVbe5Fk_q7U2joWIXo18hvxXhfKcN9746w8RA-bc3eT0fC58IuWWhz4hokf1m-rypDD3NJ1Tk/s1600/read-bus-a-ip-mux.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="358" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEherwHYIYBjuYjU3lm9tMPrVRoWucib-16OkT6LM1dTEnplCBrCCJ6xQw_UZrI-CzAgTfpVbe5Fk_q7U2joWIXo18hvxXhfKcN9746w8RA-bc3eT0fC58IuWWhz4hokf1m-rypDD3NJ1Tk/s400/read-bus-a-ip-mux.PNG" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
This circuit is a 5 way input multiplexer (there are many similarities to the Read Bus Decoding logic we found earlier). The 5x AND gates forming the selection logic feed the multiplexer logic for all 4 bits.<br />
<br />
The result, which includes all 4 bits can be summarised in the table below:<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggCnSNelxGReOYCRT3dxSQtZH3nkkjTjYKpeVn4VBShzDjXJwflhhCj28KSqN9XvXQ9BmBP3jQcqE5zW_k15fxogPvAom5sQ9meFWHO_oXB2TaVVbmkx0KV5FlRqKwx0mwHcneivh1Ylw/s1600/read-bus-b-table.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="101" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggCnSNelxGReOYCRT3dxSQtZH3nkkjTjYKpeVn4VBShzDjXJwflhhCj28KSqN9XvXQ9BmBP3jQcqE5zW_k15fxogPvAom5sQ9meFWHO_oXB2TaVVbmkx0KV5FlRqKwx0mwHcneivh1Ylw/s400/read-bus-b-table.PNG" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
So the various PLA-2 outputs between them select whether Read Bus B has r14 (probably for the Branch and Link instruction), one of 3 different bit-regions of the currently executing instruction, or the output of the priority encoder. This last option will be for the LDM/STM load/store multiple registers instruction.<br />
<br />
Read Bus A is also fed from a 5 way input multiplexer, but the selection logic is much simpler:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHw2gLhOnXElBcWFJC9yYvfgOsCliDgfodXmXTtsYjGBR6u7r6_MT7SA1cfvsXgb90ZbBL_GA1SDR_MPZKW_06F82LWXlZyFUT4z9Vv9TUsRyuQNX8CfgGdqoxbKQPqQ1ubDSHmHcztHU/s1600/read-bus-b-decoding.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="242" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHw2gLhOnXElBcWFJC9yYvfgOsCliDgfodXmXTtsYjGBR6u7r6_MT7SA1cfvsXgb90ZbBL_GA1SDR_MPZKW_06F82LWXlZyFUT4z9Vv9TUsRyuQNX8CfgGdqoxbKQPqQ1ubDSHmHcztHU/s400/read-bus-b-decoding.PNG" width="400" /></a></div>
<br />
Two of the multiplexer "channels" comprise N-FETs (those driven by the inverters in the circuit above), with the and remaining "channels" constructed of P-FETs, The multiplexing operation across all 4 bits is:<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5zwNI0KC1s0AUQ21rBO-kW_2P5q6zkaIzopcNujl2ggZdCjf9PAVggeuzB7FQNJ9AXIqt_raKBxfeTgTU83Aiw81ho9Vw4tG3SkZsJEzbAWHo8HL2FtwpLEvV94slXBzBxlMyoJ0L9cE/s1600/read-bus-a-inputs.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="66" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5zwNI0KC1s0AUQ21rBO-kW_2P5q6zkaIzopcNujl2ggZdCjf9PAVggeuzB7FQNJ9AXIqt_raKBxfeTgTU83Aiw81ho9Vw4tG3SkZsJEzbAWHo8HL2FtwpLEvV94slXBzBxlMyoJ0L9cE/s400/read-bus-a-inputs.PNG" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
The Write Bus is fed from a 5 way input multiplexer too, with the following circuit:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKjlddrECGOZsHLbXvQqtwT5dikQuCOWmPZA34oMjwXooq8cZyn9fc8Rg4lt39NDI7f_MAHWSf8xif78HEuLX2DeE7IV5XbkJWAi2KcEkVdpXDRjj_2Y2lXodlU8C0Ws_-42-CYLjpEJk/s1600/write-bus-mux.PNG" imageanchor="1"><img border="0" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKjlddrECGOZsHLbXvQqtwT5dikQuCOWmPZA34oMjwXooq8cZyn9fc8Rg4lt39NDI7f_MAHWSf8xif78HEuLX2DeE7IV5XbkJWAi2KcEkVdpXDRjj_2Y2lXodlU8C0Ws_-42-CYLjpEJk/s400/write-bus-mux.PNG" width="400" /></a></div>
<br />
The results of it's multiplexing across all 4 bits is:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL5k_PcMPUmmPYNzouFBlXvXMbkKCbHcQ9Uq_We14gMX4bosz1eYkSfvP29LZWHSCLm2I0pxJYsPOqf-9CMvGyRj-C9g1EjoH2CXWi6ZS8xW3hIQPH-ZcJIlaXBhR4hw1Bz3zSaONS61Y/s1600/write-bus-inputs.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="88" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL5k_PcMPUmmPYNzouFBlXvXMbkKCbHcQ9Uq_We14gMX4bosz1eYkSfvP29LZWHSCLm2I0pxJYsPOqf-9CMvGyRj-C9g1EjoH2CXWi6ZS8xW3hIQPH-ZcJIlaXBhR4hw1Bz3zSaONS61Y/s400/write-bus-inputs.PNG" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
Let's drill down on the priority-encoder signals.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPHfpk4ndZIFaV0imp6TlbOYZLy5xyOLROm4D2Cxpczfd1MpiXFfR5imERL1R_sErrHwU9z8Rh8KxfXhU4xK7FhmpG2Kcg3RgST5Y37gDlez7hrvkgusXpwV3Trl10Vwyf9oreSzSAjko/s1600/priority-encoder-delay.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="193" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPHfpk4ndZIFaV0imp6TlbOYZLy5xyOLROm4D2Cxpczfd1MpiXFfR5imERL1R_sErrHwU9z8Rh8KxfXhU4xK7FhmpG2Kcg3RgST5Y37gDlez7hrvkgusXpwV3Trl10Vwyf9oreSzSAjko/s400/priority-encoder-delay.PNG" width="400" /></a></div>
<br />
So the 4 bit wide priority-encoder signal is delayed slightly before being used as input the Read Bus A multiplexer and Write Bus multiplexer. The circuit for the remaining 3 of the 4 bits is identical.<br />
<span style="font-size: large;"><br /></span>
<span style="font-size: large;">Conclusion</span><br />
<br />
This analysis has significantly clarified our understanding of how the registers selection works - the PLA-2 outputs control which fields from the Instruction Register are used to select the 3x register bank inputs/outputs. There are a few exceptions where r14 or r15 is selected or the data from the priority encoder is used.<br />
<br />
Only approximately 150 transistors are used to implement these circuits.Davehttp://www.blogger.com/profile/07363645951602549336noreply@blogger.com4tag:blogger.com,1999:blog-6068833812264712077.post-64749511833476951222015-12-30T08:06:00.001-08:002016-02-14T02:29:52.507-08:00Inside the armv1 Read BusHaving explored the Register Bank last time, a good next step is to explore where its two read port outputs go. In this blog we'll start with Read Bus B, as that will also lead us the Data Bus and the data line pins. As a reminder from my earlier blogs, the floorplan is in the following diagram although, as we will see, there are several detailed differences in the actual chip. Also remember, as pointed out in the last blog, this diagram incorrectly swaps the read bus A and read bus B.<br />
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4YPuaQt0O_Buliq5BfjY5JJrdhapg-lsevEX7K8EF6RaV_MM-LiBb17nn3DPIqFy8hHZ4ATN-CgEx4r5_IxazTau3iPL3EfoCA7-P70hy0T-jLWJgUBn3v711Nja-gGY5ikP19PdK4dU/s1600/floorplan.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="368" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4YPuaQt0O_Buliq5BfjY5JJrdhapg-lsevEX7K8EF6RaV_MM-LiBb17nn3DPIqFy8hHZ4ATN-CgEx4r5_IxazTau3iPL3EfoCA7-P70hy0T-jLWJgUBn3v711Nja-gGY5ikP19PdK4dU/s400/floorplan.PNG" width="400" /></a></div>
<div>
<br /></div>
<div>
This exploration will end up covering a lot of ground - we'll find the Instruction Register and the instruction bus that feeds off it, and how data is routed in and out of the chip via the data bus. The diagram below highlights the areas of the chip we'll end up exploring.<br />
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheyQpLyHIrcAyZQtOqP1xkJUemXyYwB0B24LQA8C-eQ3iB_paKox49YRKuBK3zwu_fzpyKMu5TPlo7LyOXUXofQcugyQ_AofC6LiLLDGqH7vkuhWijs39K48wrw0cdN7OuP6p_fjMdUjc/s1600/read-register-a.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheyQpLyHIrcAyZQtOqP1xkJUemXyYwB0B24LQA8C-eQ3iB_paKox49YRKuBK3zwu_fzpyKMu5TPlo7LyOXUXofQcugyQ_AofC6LiLLDGqH7vkuhWijs39K48wrw0cdN7OuP6p_fjMdUjc/s320/read-register-a.png" width="313" /></a></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<br /></div>
<div>
To help navigate our way around the more complex logic, I've labelled the different areas in a zoomed in area of the top of the larger rectangle.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKRp5iQ5x4bW6fFLu0XDoR0W4kt1iHUqxkka4kLDmWpeCx3CsEjN2efgiGzfgJWl5L46jCfLocdPj_kqPpsLMU7pmjQodtJ893eEfyWyBnNkFwvGXWt13_MWQCihrI4oHQZ6bbYGPZrpA/s1600/read-register-a-zoomed.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="337" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKRp5iQ5x4bW6fFLu0XDoR0W4kt1iHUqxkka4kLDmWpeCx3CsEjN2efgiGzfgJWl5L46jCfLocdPj_kqPpsLMU7pmjQodtJ893eEfyWyBnNkFwvGXWt13_MWQCihrI4oHQZ6bbYGPZrpA/s640/read-register-a-zoomed.png" width="640" /></a></div>
<div>
<br /></div>
<div>
The logic for each bit associated with the Read Data Bus is laid out horizontally, and with the bits stacked on top of each other vertically - bit 31 at the top, and bit 0 at the bottom. Read Data Bus bit 31 is highlighted in red, and the areas labelled 1, 2, 3, 4 highlight the logic gates associated with bit 31. The logic is almost identical for all 32 bits, and the associated drive circuitry highlighted at the top. Also highlighted as area 5 is the logic associated with one of the data pins; we'll reverse-engineer that logic too.</div>
<div>
<br /></div>
<div>
We'll start by following where bit 0 of Read Bus B leads us, and then see how the remaining bits of the bus differ.</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDUUb6N41AOp3tiwxRfggZwtpKgUPysYGv14PmNq6Colp0tmlKVQpkwZR9L-Q41CkSpuvWFTNzUk-SNzezXplkG2FkE9bbaDI51DLdyzkr-NY6B-mDbvm_rp8Xxr7YamZyLDI17ZzS26Q/s1600/read-bus-a-bit0.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="366" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDUUb6N41AOp3tiwxRfggZwtpKgUPysYGv14PmNq6Colp0tmlKVQpkwZR9L-Q41CkSpuvWFTNzUk-SNzezXplkG2FkE9bbaDI51DLdyzkr-NY6B-mDbvm_rp8Xxr7YamZyLDI17ZzS26Q/s640/read-bus-a-bit0.PNG" width="640" /></a></div>
<br /></div>
<div>
This circuit relies on stray capacitance on the bus line for its operation. During the second half of every clock cycle (when phi 2 is high) the FET in the above circuit pulls the bus line high, charging it to a high state. In the subsequent first half of the next cycle, one of three possible signals may pull the bus line low, discharging any stray capacitance. The state of the bus line is then read by either the Barrel Shifter or by Circuit 4, which processes the Data Out signal. The signal on the Read Bus is inverted logic - 0v represents a logical 1.</div>
<div>
<br /></div>
<div>
The signal input to the bus is one of the following:</div>
<div>
<ol>
<li>The output of the Read Bus B from the Register Bank, as described in the last blog.</li>
<li>Data from Circuit 1, which is described below, and can be either the content of the Instruction Register, or data from the Data pins.</li>
<li>Data for when the PC is being read. The armv1 architecture is such that the program counter (PC, which is R15 in the register bank), has special meanings assigned to some of its bits. These bits are not stored in the register bank, but elsewhere. Bits b0..b1 give the processor state, and bits b26..b31 are the Condition Code Register. The logic above is to read these registers at the appropriate time. This data path is in the thin vertical rectangle in the diagram above. This logic will be explored in a later post.</li>
</ol>
<div>
Complexity arises with how the circuit differs for each bit. We've already dealt with how input 3 varies. However the enable (8106) for the data from Circuit 1 also varies in a complex way. There are 5 (!) enable lines across all 32 bits of Read Bus A:</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJxcmqrnNbS0M0fb08Auz2tNYxoe2aqhDmjFPKUgTh1_MPTenQcLX5jEZdinzDx04OQsOFdw5PagSSv_z0332TdhE-PxRO40MJEuBJpE99xEzGQ28oGhZ2OwaLL5MEH4W10eEZ7c2cWD8/s1600/read-bus-a-decoding.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJxcmqrnNbS0M0fb08Auz2tNYxoe2aqhDmjFPKUgTh1_MPTenQcLX5jEZdinzDx04OQsOFdw5PagSSv_z0332TdhE-PxRO40MJEuBJpE99xEzGQ28oGhZ2OwaLL5MEH4W10eEZ7c2cWD8/s1600/read-bus-a-decoding.png" /></a></div>
<div>
<br /></div>
<div>
One use of this circuitry is for when a byte-read takes place - the 8 bits of data just read appear on different bit ranges depending on the lower two address bits. The enable signals above allow the valid data to put onto the Read Bus (the barrel shifter then rotates the bits to the correct position). I don't yet understand why the second and third enable signals drive just 4 bits each. The circuitry to create these 5x enable signals is in the DATA CTL area - the red rectangle at the top right of the chip:<br />
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUpQR1yBzW6O70foauK9yBKLh25ORQaL6omfZ47XkdIRIUhXgYE_qsheXDrfJ-m8hMWIkvAFSnhjKLTFhBfbqJR9LeC1wCAV-eGAjTkIShSzbmBwKbXj_xWN8bnUuFkxUXvKz4aSRMCfc/s1600/read-bus-a-decoder.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUpQR1yBzW6O70foauK9yBKLh25ORQaL6omfZ47XkdIRIUhXgYE_qsheXDrfJ-m8hMWIkvAFSnhjKLTFhBfbqJR9LeC1wCAV-eGAjTkIShSzbmBwKbXj_xWN8bnUuFkxUXvKz4aSRMCfc/s640/read-bus-a-decoder.PNG" width="598" /></a></div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
</div>
As can be seen from the diagram, each enable output is dependent on the result of a 4:1 multiplexer. Each multiplexer has 3 of its 4 inputs that are hardwired to either a 0 or 1. The fourth multiplexer input is dependent on additional logic, including the bw output pin. The bw output pin indicates whether the current memory read/write operation is for a byte transfer or a 32 bit word transfer (high for word, low for byte). The truth table below is another way to see the operation.</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgy95jjs847JdiuPET_D8rgetQaEMP24X4-hog6z4w_gIYRI1hav5wT_3l-2jAZaRENPWiSIkKjoiHW0t2JFlqSawGyjV75GdJQTTP3_t3a6nO5v1renEu35OFFnJn3W2uby66SRdnpUkA/s1600/read-bus-a-decoder-truth-table.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="228" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgy95jjs847JdiuPET_D8rgetQaEMP24X4-hog6z4w_gIYRI1hav5wT_3l-2jAZaRENPWiSIkKjoiHW0t2JFlqSawGyjV75GdJQTTP3_t3a6nO5v1renEu35OFFnJn3W2uby66SRdnpUkA/s640/read-bus-a-decoder-truth-table.PNG" width="640" /></a></div>
<br /></div>
<div>
The top three rows demonstrate that the first three inputs (phi 1 clock, 8186, and 8272) must have values 1, 1, 0 respectively for there to be any output. The next three lines show the outputs for three of the possible permutations of 8105, 8104. I suspect that these are for instruction decoding:<br />
<ul>
<li>the first to extract the 8 bit immediate value for one variant of the Data Processing instruction.</li>
<li>the second to extract the 12 bit offset for the Single Data Transfer instruction.</li>
<li>the third to extract the 24 bit offset for Branch instructions.</li>
</ul>
<br />
The next 4 rows in the table are to select each byte in turn. It's almost certain 8195, 8194 are connected to Address line 1, 0.<br />
<br />
<span style="font-size: large;">Circuit 1 - Data In and I-Reg Multiplexing</span><br />
<br /></div>
<div>
Now that we have the circuit for the enable signal for Circuit 1 let's look at Circuit 1's internal logic, and its associated driver circuit.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSFdQTgyEVaDvgicSDJ6PBpJ37BSqmzfI3m6EUKnL6ra81C9fhV8sI1y38wKRmT_zfOn4wKPEinSoavgyh31A5bS4TLPC2ou0xGhplDOwo4mFO1yJbwqWj_QicBHz32_MFpyxH2GTrmF4/s1600/read-bus-a-circuit-1.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSFdQTgyEVaDvgicSDJ6PBpJ37BSqmzfI3m6EUKnL6ra81C9fhV8sI1y38wKRmT_zfOn4wKPEinSoavgyh31A5bS4TLPC2ou0xGhplDOwo4mFO1yJbwqWj_QicBHz32_MFpyxH2GTrmF4/s400/read-bus-a-circuit-1.PNG" width="398" /></a></div>
<br /></div>
<div>
So this circuit puts either Data In or I-Reg onto Read Bus B, depending on two control signal from elsewhere - signal 8111 or 8187.<br />
<br />
The back-coupled FETs that signal 8111 feeds into warrants a little more discussion. This back-coupled FET pattern is used in many places throughout the processor, including in the ALU. This pattern appears to have two distinct uses:<br />
<br />
<ul>
<li>It can be used ax a multiplexer, as shown further down in the same circuit. </li>
<li>Or in this case it can be used as a "latch". Whilst the phi 1 clock is high both FETs are turned on and the 8111 signal passes through the FETs to the input to the AND gate. When the phi 1 clock goes low the two FETs are turned off and the input to the AND is left floating. The stray capacitance of the node means the voltage will be maintained for a short period, until any charge is dissipated through leakage. The capacitance must be large enough, and the leakage small enough, for the correct logic value to be maintained until the next clock cycle. This is presumably why the processor has a maximum clock cycle time of around 10 microseconds; any longer and the correct value would not be held.</li>
</ul>
So, in summary, signal 8111 is "latched" during the phi 1 clock time so that it can be processed during the phi 2 clock time.<br />
<br />
<br />
<span style="font-size: large;">Circuit 2 & 3 - The Instruction Register (or I-Reg)</span></div>
<div>
<br /></div>
<div>
The Instruction -Register logic is as follows:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhv1nJ-5tvdnlLChwjcjI2WGDHwrwsz1YeTobzQYouBfv6OfvXoBxHc37bncQ0h2mNQJKOIqcQVl-rRVhtL1zc5-i3pnmAaVB7wdIhaILZmeYzoFn6txzlu2VevUpFToVlazZxECS8BEwo/s1600/instruction-register.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="618" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhv1nJ-5tvdnlLChwjcjI2WGDHwrwsz1YeTobzQYouBfv6OfvXoBxHc37bncQ0h2mNQJKOIqcQVl-rRVhtL1zc5-i3pnmAaVB7wdIhaILZmeYzoFn6txzlu2VevUpFToVlazZxECS8BEwo/s640/instruction-register.PNG" width="640" /></a></div>
<br />
The Instruction Register itself is the cross-coupled inverter on the right, although it's difficult to see with the FET multiplexers at each inverter's input. The pair of multiplexers that feed the lower cross-coupled inverter determine whether the register maintains its current (looped back) state or whether it is updated from a delayed copy of Read D0. Input 8187 selects which multiplexer is selected. The 3x input signals that control this circuit will be explored subsequently, but a quick look shows that input 4585 is derived from the opc pin, which indicates that the processor is fetching an instruction, so we're definitely on the right track!<br />
<br />
The I-Reg outputs form a bus that runs right across the chip, pretty much as illustrated in the floorplan at the beginning of this blog. However, there are a few exceptions:<br />
<br />
<ul>
<li>A few outputs are not connected. These are bits 25, 26, and 27.</li>
<li>There are 6x I-Register outputs that are fed from the opposite side of the cross-coupled inverters. These are bits 4 (7887), 20 (7888), 24 (7889), 25 (7890), 26 (7891), 27 (7892). These all feed into inverters and the inverted outputs join the other I-Reg signal bus. The inverters are in the area marked "3 Outputs" in the earlier image.</li>
</ul>
<br />
<span style="font-size: large;">Circuit 4 - Data Out (DOUT) Processing</span></div>
<div>
<br />
The final circuit connected to Read Bus A is the Data Out (DOUT) processing logic which in the area marked as "4" in the earlier image:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaBTmlR9xVwcCgcig3RDx9jvW0PFa7d9XqKup9c7M10VpjkmSCEwe-Dq67MUfr-3cSHNH0dzjTM4kSEzu1Zpb6zC71Rn5nO9yozzLtBMYxvfPom58HBBNppYxwX4mC9z_geIO74OpMoHw/s1600/data-out.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaBTmlR9xVwcCgcig3RDx9jvW0PFa7d9XqKup9c7M10VpjkmSCEwe-Dq67MUfr-3cSHNH0dzjTM4kSEzu1Zpb6zC71Rn5nO9yozzLtBMYxvfPom58HBBNppYxwX4mC9z_geIO74OpMoHw/s640/data-out.PNG" width="579" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
This logic interfaces the Read Bus with the processor's data bus. Normally all 32 bits of the Read Bus are presented to the data pins; however during a byte-write, the data in the lowest byte is also presented on 3 the upper bytes too.<br />
<br />
The logic for the 8 lowest bits is the identical, and passes the signal to the other bits via an 8-bit wide bus, and also towards the Read/Write pin on nbus signals.<br />
<br />
The logic for bits 8-31 is also identical. The signal is multiplexed in from either the Read Bus B input or from the 8-bit wide bus fed by bits 0..7. The bw (byte not word) input signal selects between the two inputs. We've already encountered the bw input signal in the Read Bus B decoding logic.<br />
<br />
<span style="font-size: large;">Circuit 5 - Data Lines 0 to 31</span><br />
<br />
The final circuit to explore is associated with each data line, and is highlighted in the diagram above as circuit 5.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaKTdGvh85UmThmSIMqAvGicgq1H9pPuYVYvkwPtrMGU7oTFovMhnYumN4g4zwbkinlyk96GK5Yj1rLdW5UFfLRF28e4KaaFB_uvWthnxf_L1i_CM2yZGXdDshDJ_tpl0frhCCCiYLFOU/s1600/data-lines.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaKTdGvh85UmThmSIMqAvGicgq1H9pPuYVYvkwPtrMGU7oTFovMhnYumN4g4zwbkinlyk96GK5Yj1rLdW5UFfLRF28e4KaaFB_uvWthnxf_L1i_CM2yZGXdDshDJ_tpl0frhCCCiYLFOU/s400/data-lines.PNG" width="362" /></a></div>
<br /></div>
<div>
This circuit identifies the destination of the nbus signal referred to in the Data Out logic, and the source of the Read D0 signal that's seen in the Data In logic, and the Instruction Register logic.<br />
<br />
We also see the R/W pin, and the dbe (data bus enable) pin having a part to play in the logic.<br />
<br />
<span style="font-size: large;">Conclusion</span><br />
<span style="font-size: large;"><br /></span>
We have finally completed our exploration of the Read Bus B logic, and in the process identified the Instruction Register (I-Reg) and how data is read and written to the data pads. We've also seen some of the complexities of dealing with byte/word reads and writes and how reading r15 (the PC) is a special case. Around 2,200 transistors are used to implement these circuits.<br />
<br />
To have located the Instruction Register is an important step forward as it is its content that drives much of the processor's control logic. But all that is for future blog posts.<br />
<br />
But let's not get lost in the details. Overall, the circuitry described in this post accomplishes some simple routing, which are summarised in the diagram below, which is a little more explicit than the floorplan diagram above. Yes, there are extra details that aren't shown in the diagram, but it helps to keep this overview in mind too.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCGjLKh9EpfuBQkgRpqgeJgEC1OylcwAtDOaQSguV-c7Tu4rhlc5HhoS7g7eehea4eV6H1e8uzp19wPNUuqiWfDMJo0xtmtLxm-GRaGTQ-HfzQa8KWPzIyBkClOO9dfKso8NXTUWZ33w4/s1600/read-bus-dataflows.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="301" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCGjLKh9EpfuBQkgRpqgeJgEC1OylcwAtDOaQSguV-c7Tu4rhlc5HhoS7g7eehea4eV6H1e8uzp19wPNUuqiWfDMJo0xtmtLxm-GRaGTQ-HfzQa8KWPzIyBkClOO9dfKso8NXTUWZ33w4/s400/read-bus-dataflows.PNG" width="400" /></a></div>
<br />
<br />
<br />
<br />
<br /></div>
Davehttp://www.blogger.com/profile/07363645951602549336noreply@blogger.com3tag:blogger.com,1999:blog-6068833812264712077.post-88943051401109115892015-12-28T03:53:00.001-08:002016-02-10T07:42:14.868-08:00Inside the armv1 Register BankReverse engineering the armv1 chip feels a lot like completing a jig saw puzzle. I start with the more obvious "chunks", and then gradually fill in the gaps that are left. A very big "chunk" on the armv1 chip just crying out to be reverse-engineered is the register bank, and that's where I'll start today before moving on to look at the main data paths.<br />
<div>
<br /></div>
<div>
Architectural descriptions of the armv1 tell us that the chip contains a bank of 25 registers, each 32 bits wide. Of these 25 registers, only 16 are visible to the programmer at a time and are referenced in the instructions as registers number 0 to 15, with register 15 being the Program Counter or PC. The extra registers are there to support the four modes that the processor runs in - supervisor, interrupt, fast interrupt, and user mode. For instance the fast interrupt mode has it's own copy of five of the registers - r10, r11, r12, r13, and r14.</div>
<div>
<br /></div>
<div>
We also know from the architecture that the register bank has two read buses and one write bus. We also know from my last blog that one of the read buses goes directly to the ALU, and that the output of the ALU goes to the write bus. This is nicely illustrated in the following block diagram:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHJvNT79tSX0oLIgWPzvaIQxYaEjcRLHLHxzcCpAegzHFDBcD8SFNaUarQDPTDe04rb6ucMQx8Rf_bxQOr4QnppnitPi2PM_IX-x7oRkGo0cVUDrfbmyASNzUXc9ybBJcl2Rbs6gOkJZc/s1600/floorplan.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="368" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHJvNT79tSX0oLIgWPzvaIQxYaEjcRLHLHxzcCpAegzHFDBcD8SFNaUarQDPTDe04rb6ucMQx8Rf_bxQOr4QnppnitPi2PM_IX-x7oRkGo0cVUDrfbmyASNzUXc9ybBJcl2Rbs6gOkJZc/s400/floorplan.PNG" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
(Please note that it has recently been noticed that this historical diagram has incorrectly labelled read bus A and read bus B the wrong way around; all other documents name them the other way around. This blog series has therefore been updated to label the buses correctly)<br />
<br />
Now that we have a bit more context it's time to zoom into the details on the chip, starting at the lowest level of detail - a single bit. Each of the 32 bits of all 25 registers is the same - a cross-coupled inverter, with three separate select lines. The silicon layout is as follows:</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhDOlagwaRmhoU2Umn0TjHNn_vpns7LxO-GeBAshcT070ciMWfIsM-fq1r_nq4Rbf1PIePpzk43zMXi4zb-4syI9p5MbuvrVEfhvWiY8B4AZcXZ7eljEtxqVTP_4Ut0JpPFtnbkI5dstA/s1600/register-cell.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhDOlagwaRmhoU2Umn0TjHNn_vpns7LxO-GeBAshcT070ciMWfIsM-fq1r_nq4Rbf1PIePpzk43zMXi4zb-4syI9p5MbuvrVEfhvWiY8B4AZcXZ7eljEtxqVTP_4Ut0JpPFtnbkI5dstA/s400/register-cell.PNG" width="337" /></a></div>
<br /></div>
<div>
The equivalent circuit is:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsRxQt_A4BsB8np9_pyi587X-RmlUSMS1OKR_nGcvLmfDUjiKdyIT0A_RqEpmUQ3hgwLB8EEgjeFt402FKj9MlY76oE4ck8aw4lSL5AZsbXSK_3FK8dSHMhORCLM6K4LfUXMnFA-Itf6E/s1600/register-cell-circuit.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="262" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsRxQt_A4BsB8np9_pyi587X-RmlUSMS1OKR_nGcvLmfDUjiKdyIT0A_RqEpmUQ3hgwLB8EEgjeFt402FKj9MlY76oE4ck8aw4lSL5AZsbXSK_3FK8dSHMhORCLM6K4LfUXMnFA-Itf6E/s400/register-cell-circuit.PNG" width="400" /></a></div>
<br /></div>
<div>
What is interesting about this circuit is that the write circuit <b>shorts </b>the output of one of the inverters! The write select transistor and the Write Bus driver transistors are comparatively large, and much larger than the transistors in the inverter, ensuring that they will "win". Once the inverter's output has been overpowered, the cross-coupled inverters will quickly transition to the new state, ensuring that the short condition lasts only a very short time. The 3x select lines per register run vertically, as shown in the chip detail above. Likewise, the 32 bits per register (x3, one for each bus) run horizontally.</div>
<div>
<br /></div>
<div>
<span style="font-size: large;">Select Line Decoding</span></div>
<div>
<br /></div>
<div>
The three select lines for each of the 25 register are generated by the decode circuitry above the register bank. The similarities in the decoding between the three select lines, and between the registers is visually very apparent:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4s8omWszKhubsY8GNF5Wvn7SRAp-LhxgmmwLYY7IftYIqSaul6MV5oo1Lo2FthrRNaqdY429Bu7-p1TIr4q-Jvn-MAWgeFe43Gn1mVJP-HfAQ61iS-8rB_cmLuoLpFMFAVt5w9jL8Iho/s1600/register-select.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="246" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4s8omWszKhubsY8GNF5Wvn7SRAp-LhxgmmwLYY7IftYIqSaul6MV5oo1Lo2FthrRNaqdY429Bu7-p1TIr4q-Jvn-MAWgeFe43Gn1mVJP-HfAQ61iS-8rB_cmLuoLpFMFAVt5w9jL8Iho/s400/register-select.PNG" width="400" /></a></div>
<div>
<br /></div>
<div>
I'll start by describing the decode circuitry for Read Bus B, and later show how the decoding for Read Bus A and the Write Bus differ only slightly. There are two steps to the decoding process, first decoding the register number, and then the processor state/mode. Decoding by the register number is via the following circuit:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj98otXLYrOH1OsOlodGs917DYt6obkFaIUZZBHcO8bX9RsIaOj_n9VDczT9X5MwHRop43IrloOxRGuwgreMOvmgofcRkjAU_sP39SEQhFuVBh-djHCZm6xGVH4TOK05nigD1cooPps4m0/s1600/register-decoding.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="317" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj98otXLYrOH1OsOlodGs917DYt6obkFaIUZZBHcO8bX9RsIaOj_n9VDczT9X5MwHRop43IrloOxRGuwgreMOvmgofcRkjAU_sP39SEQhFuVBh-djHCZm6xGVH4TOK05nigD1cooPps4m0/s320/register-decoding.PNG" width="320" /></a></div>
<div>
<br /></div>
<div>
I've laid out the diagram so such that the horizontal lines match the chip layout. The b3, b2, b1, b0 inputs select the register; the logic to set these values will be reverse-engineered in a later blog. Note that each input to the NAND gate has only one connection (not 2 as shown in the diagram) - it will be connected either to an input bit or its inverse.</div>
<div>
<br /></div>
<div>
The subsequently decoding based on processor state/mode is as follows:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjR01d-U_iF-H4DaqGGkdNxuFhq6mx_iKMw8a-kFE0KDttPz-F49oDDXmMhboaY0xunl5wWhJPTMFtoYYO0cV2tm1mazl3CZLm9WqHLxyu1z5gamaa5R1OhIqaxmqsmSBtmdi3Ldk3DEYw/s1600/register-decoding-mode.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="332" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjR01d-U_iF-H4DaqGGkdNxuFhq6mx_iKMw8a-kFE0KDttPz-F49oDDXmMhboaY0xunl5wWhJPTMFtoYYO0cV2tm1mazl3CZLm9WqHLxyu1z5gamaa5R1OhIqaxmqsmSBtmdi3Ldk3DEYw/s400/register-decoding-mode.PNG" width="400" /></a></div>
<br /></div>
<div>
Again, the diagram is laid out so that the horizontal lines match the chip layout. The C NOR input is connected to just one of the 5 horizontal lines that select the processor modes. The output of the AND gate feeds to the register array. Note that the horizontal lines also feed the Read Bus B and Write Select logic.</div>
<div>
<br /></div>
<div>
The settings for the 25x sets of decoders are summarised in the table below:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhA7V9Es-9KKc6JBpoZQ3z4JSJ_WU0JtgebDgcOTVHbRzggwfPtTehErJEokzak3-MBLQD_DHXuKM1bA3bAeAVIBAg109RNmAq_lb113yp31Bn6k0AICLDUxdND7eXheNFA8b5S3jwNLA0/s1600/register-decoding-table.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="155" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhA7V9Es-9KKc6JBpoZQ3z4JSJ_WU0JtgebDgcOTVHbRzggwfPtTehErJEokzak3-MBLQD_DHXuKM1bA3bAeAVIBAg109RNmAq_lb113yp31Bn6k0AICLDUxdND7eXheNFA8b5S3jwNLA0/s640/register-decoding-table.PNG" width="640" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
The decoding for the Read Bus A and Write Select is very similar. The registers selection logic is almost identical, with only the source of the b3..b0 input signals differing, as shown in the table below:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMtD6f1XnGarPhb569FLKrCGayRr4_4UFypCyHhdzo_wdf9Q9fClPsStPTWCynJLI02fp8dPOpFnlanLS5WpWEMI9qVUshCzruObF_ZrOe11fZ0_mGRBIngyUzqeE-mD7nwoqiz9039Jc/s1600/select-lines.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="130" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMtD6f1XnGarPhb569FLKrCGayRr4_4UFypCyHhdzo_wdf9Q9fClPsStPTWCynJLI02fp8dPOpFnlanLS5WpWEMI9qVUshCzruObF_ZrOe11fZ0_mGRBIngyUzqeE-mD7nwoqiz9039Jc/s400/select-lines.PNG" width="400" /></a></div>
<br /></div>
<div>
There are only minor differences in the processor state/mode decoding.The updated circuits are shown below:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoiYGD4ZFvWQtwVmBDZu5fIgU2HoPA14bw-Fxh6Wdfay2S1ST0ZDxXxDvatTQSHk0IkE8lr2UV-mRTh9q64px-6q4FlDk0GBLJjs08d9Y9E8GmftolXUf5tC96YTN6-S0w4rXfJWj5v_Q/s1600/register-decoding-differences.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoiYGD4ZFvWQtwVmBDZu5fIgU2HoPA14bw-Fxh6Wdfay2S1ST0ZDxXxDvatTQSHk0IkE8lr2UV-mRTh9q64px-6q4FlDk0GBLJjs08d9Y9E8GmftolXUf5tC96YTN6-S0w4rXfJWj5v_Q/s400/register-decoding-differences.PNG" width="400" /></a></div>
<br /></div>
<div>
Note that the write decoding is driven from the phi 2 clock, whereas both sets of read decoding is driven from the phi 1 clock. We'll need to pick up on the timing-related aspects later.</div>
<div>
<br /></div>
<div>
Finally, r15, the Program Counter, has some slight variations from the above; these need to be investigated later.</div>
<div>
<br /></div>
<div>
<span style="font-size: large;">Conclusion</span></div>
<div>
<br /></div>
<div>
We now have a complete breakdown of the register bank and how the three ports - two read, and one write - operate. A little over 6,000 transistors are needed for its implementation. There are very few external signals that control its operation, and these will be clarified later as we continue with the reverse engineering.<br />
<br /></div>
<div>
<br /></div>
Davehttp://www.blogger.com/profile/07363645951602549336noreply@blogger.com3tag:blogger.com,1999:blog-6068833812264712077.post-92084011371795408032015-12-19T10:39:00.002-08:002016-01-28T01:38:27.734-08:00Inside the ALU of the armv1 - the first ARM microprocessorThis is the first in a series of posts on the armv1. The full list of posts is:<br />
<ul style="background-color: white; margin: 0.5em 0px; padding: 0px 2.5em;">
<li style="color: #222222; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13.2px; line-height: 18.48px; margin: 0px 0px 0.25em; padding: 0px;"><a href="http://daveshacks.blogspot.com/2015/12/inside-alu-of-armv1-first-arm.html" style="color: #888888; text-decoration: none;">Inside the ALU of the armv1 - the first ARM microprocessor</a></li>
<li style="color: #222222; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13.2px; line-height: 18.48px; margin: 0px 0px 0.25em; padding: 0px;"><a href="http://daveshacks.blogspot.com/2015/12/inside-armv1-register-bank.html" style="color: #888888; text-decoration: none;">Inside the armv1 Register Bank</a></li>
<li style="color: #222222; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13.2px; line-height: 18.48px; margin: 0px 0px 0.25em; padding: 0px;"><a href="http://daveshacks.blogspot.com/2015/12/inside-armv1-read-bus.html" style="color: #888888; text-decoration: none;">Inside the armv1 Read Bus</a></li>
<li style="color: #222222; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13.2px; line-height: 18.48px; margin: 0px 0px 0.25em; padding: 0px;"><a href="http://daveshacks.blogspot.com/2015/12/inside-armv1-register-bank-register.html" style="color: #888888; text-decoration: none;">Inside the armv1 Register Bank - register selection</a></li>
<li style="color: #222222; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13.2px; line-height: 18.48px; margin: 0px 0px 0.25em; padding: 0px;"><a href="http://daveshacks.blogspot.co.uk/2016/01/inside-armv1-instruction-decoding-and.html">Inside the armv1 - instruction decoding and sequencing</a></li>
<li style="color: #222222; font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13.2px; line-height: 18.48px; margin: 0px 0px 0.25em; padding: 0px;"><a href="http://daveshacks.blogspot.com/2016/01/inside-armv1-decoding-barrel-shifter.html">Inside the armv1 - decoding barrel-shifter commands</a></li>
<li style="margin: 0px 0px 0.25em; padding: 0px;"><span style="color: #222222; font-family: arial, tahoma, helvetica, freesans, sans-serif;"><span style="font-size: 13.2px; line-height: 18.48px;"><a href="http://daveshacks.blogspot.co.uk/2016/01/inside-arm1v-alu-control-logic.html">Inside the arm1v - the ALU control logic</a></span></span></li>
</ul>
<div style="background-color: white; color: #222222; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 13.2px; line-height: 18.48px;">
Ken Shirriff has also written a series of ARM posts arm internals <a href="http://www.righto.com/search/label/arm">here</a>.</div>
<br />
I really enjoyed reading Ken Shirriff's blogs about reverse engineering the 8085, (e.g. <a href="http://www.righto.com/2013/01/inside-alu-of-8085-microprocessor.html">Inside the ALU of the 8085 microprocessor</a>), and immediately thought of his articles when I saw that the guys over at visual6502.org <a href="http://blog.visual6502.org/2015/11/the-visual-arm1.html">announced </a>that they had released the mask level details and full simulation of the very first arm chip - the armv1.<br />
<br />
With that in mind I embarked on my own attempt to reverse-engineer parts of the armv1. Some background knowledge of the processor's architecture is helpful, and googling for "ARM Architecture Reference Manual" will lead you to very detailed descriptions of the more modern versions of the processor. By just looking at the masks and knowing a little about the processor's architecture it's possible to make some good guesses at what some of the blocks are.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBYkS1CkrWqfInyNxZ_lo2OVXa06C9yeLE5YD_ff7vA7Erdz21EsR6_xbUO5DxSlsUrCckVJDNI7wSd3FQ945CYQtAdhaEQRfo598_Hw2_DSB-yASeTuWJ7gfNdEqcCBudFgsNKY9T3Pk/s1600/silicon-regions.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBYkS1CkrWqfInyNxZ_lo2OVXa06C9yeLE5YD_ff7vA7Erdz21EsR6_xbUO5DxSlsUrCckVJDNI7wSd3FQ945CYQtAdhaEQRfo598_Hw2_DSB-yASeTuWJ7gfNdEqcCBudFgsNKY9T3Pk/s640/silicon-regions.PNG" width="630" /></a></div>
<br />
<br />
The barrel shifter is especially obvious when you go to the interactive <a href="http://visual6502.org/sim/varm/armgl.html">visual6502.org</a> website and zoom in on that portion of the chip and see the diagonal traces. Also, from the architecture description, we know each data-processing (ALU or arithmetic logic unit) instruction selects 3 registers: one destination register (where the ALU result goes), and a register for each of the two operands - Operand 1 and Operand 2. It is therefore a reasonable guess that the Register file has 3 sets of register selection logic, which is verified by the 3 layers of gates of very similar pattern directly above the Register file.<br />
<br />
From the architecture description we know that ALU is controlled by 16x opcodes:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioOoou56cLt8UTVi6H2Q74stgwdo-2uzLhS-lv1j_ecg-1JknXuvw2lFw4ri9OvC5JEjYklhdpvq1teU5H3oqjK7ytH650GdI_JH42wY7QwVQs-PykkSAF2pFIjJir9JnYOBxSacvWFjI/s1600/opcodes.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="492" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioOoou56cLt8UTVi6H2Q74stgwdo-2uzLhS-lv1j_ecg-1JknXuvw2lFw4ri9OvC5JEjYklhdpvq1teU5H3oqjK7ytH650GdI_JH42wY7QwVQs-PykkSAF2pFIjJir9JnYOBxSacvWFjI/s640/opcodes.PNG" width="640" /></a></div>
<br />
<br />
So my first step was to ensure I'd found the right area for the ALU. From the architecture description I know that the two inputs to the ALU are:<br />
<ul>
<li>Operand 1: the content of register n, as selected by the Rn field of the instruction.</li>
<li>Operand 2: the output of the barrel shifter (most operations select a shift of 0).</li>
</ul>
<div>
I therefore started by reverse-engineering the barrel-shifter and identifying the barrel-shifter's output. By following the output I knew it would lead to the ALU.</div>
<div>
<br /></div>
<div>
The steps I took to reverse-engineer the ALU were to identify each of the transistors and how they are connected (using the netlists on the <a href="http://visual6502.org/sim/varm/armgl.html">visual6502.org</a> website), converting these into gate circuits, translating these into a schematic, and finally verifying I had captured it correctly by cross checking the simulator's output against the circuit in the schematic.<br />
<br />
The portion of the die associated with a single bit slice of the ALU is here:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0EjzgZC-jhkbXlFpfdBS3Ne93R1-1qYCKMCMElydrGZ468cWjosyw-835-rHP8LAdRKd5u16XemsVBjdw4CP-9E-09IqHBoZhU-BOAmv_Uibvm0ewQU3aBq0F34qC8KSDQzA4MGI00ZA/s1600/alu-substrate.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="90" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0EjzgZC-jhkbXlFpfdBS3Ne93R1-1qYCKMCMElydrGZ468cWjosyw-835-rHP8LAdRKd5u16XemsVBjdw4CP-9E-09IqHBoZhU-BOAmv_Uibvm0ewQU3aBq0F34qC8KSDQzA4MGI00ZA/s640/alu-substrate.PNG" width="640" /></a></div>
<br /></div>
<div>
<br /></div>
<div>
An example of the translation of transistors into a gate (which corresponds to the upper left circuit of the ALU) is as follows:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXBVJRNNqoxTt0dyycCgXzeHhzfEWuv3xW1LuoEX6BB_EQC7hZK2c75OgHzF3XXP5GgKJObBPvtjQAFMPB4QNH9tj7evZd2otynGZJ_aW0y8OEYbUk8vaRea5B5Mr3h5Hcgwzsx-oFxi4/s1600/equiv.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="185" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXBVJRNNqoxTt0dyycCgXzeHhzfEWuv3xW1LuoEX6BB_EQC7hZK2c75OgHzF3XXP5GgKJObBPvtjQAFMPB4QNH9tj7evZd2otynGZJ_aW0y8OEYbUk8vaRea5B5Mr3h5Hcgwzsx-oFxi4/s400/equiv.PNG" width="400" /></a></div>
<div>
<br /></div>
<br />
The full ALU circuit contains 70+ transistors for each of the 32 bits, or over 2,200 transistors in total.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcTALkL2-elYaP6-03DU3LJmpntuZe1z3d9n7md-KAxl-CSxlQhIMc33NrTIyzSV7PKQ_g2kQn7nP4MJvma72-nszIc2MlfpCG07uPmFWoxrzcaPtmT-ofKekJQUi5Wbly-W7aNESxCnw/s1600/alu.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="342" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcTALkL2-elYaP6-03DU3LJmpntuZe1z3d9n7md-KAxl-CSxlQhIMc33NrTIyzSV7PKQ_g2kQn7nP4MJvma72-nszIc2MlfpCG07uPmFWoxrzcaPtmT-ofKekJQUi5Wbly-W7aNESxCnw/s640/alu.PNG" width="640" /></a></div>
<br />
This diagram corresponds to a single bit in the ALU, so this is replicated 32 times to form the full ALU. On the physical silicon these are stacked one on top of the other, although physically the circuit is swapped left for right, as the inputs to the ALU are from the right-hand-side and exit on the left-hand-side.<br />
<br />
In the schematic above the control signals (7500, 2370, etc. - these are their net numbers) are shown coming into the circuit from above and below; on the physical silicon all these control signals originate from above the ALU.<br />
<br />
The eagle-eyed will also notice that the Carry propagation and Zero calculation circuits alternates slightly between each bit, with b0, b2, etc identical, and b1, b3, etc. identical. The end result is the same but the reason for the difference is to keep the execution path as fast as possible by eliminating an inverter per bit; note that the Carry Out and Zero Out signals are opposite polarity to the inputs.<br />
<br />
The 16x different ALU operations are selected by the appropriate setting of the control signals as shown in the table below.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjElAwjfuui-w46zLRsylQsuAo7pqrfOa9xjaZ0-rMMu4JrbwNytBHqPDd_NZH62g2_uYhgiSWZzwLdYRsO3cii9dEcHiozCLTpXBVcBWex_pqEm0UN3eIjQLjqvGCAAj4lhBFNAdwD5R4/s1600/control-signals.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="254" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjElAwjfuui-w46zLRsylQsuAo7pqrfOa9xjaZ0-rMMu4JrbwNytBHqPDd_NZH62g2_uYhgiSWZzwLdYRsO3cii9dEcHiozCLTpXBVcBWex_pqEm0UN3eIjQLjqvGCAAj4lhBFNAdwD5R4/s640/control-signals.PNG" width="640" /></a></div>
The schematic and the table above give a huge amount of detail! However it can be broken down into smaller, more digestible pieces.<br />
<br />
First, note that 2370, 2371, 7484, and 7485 all have the same setting for each opcode; they, and the associated FET transistor isolation circuitry, can be ignored (their purpose is for another discussion).<br />
<br />
Second, note that 7393 is only high when it's an arithmetic operation - it purpose is to enable/disable the Carry chain.<br />
<br />
Third, Control signal 7500, and the 3x gates at the top left of the schematic, determine whether Operand 1 is inverted on entry to the rest of the ALU (note that the input signal is already inverted, so the 'normal' setting is for it to be 1 to invert it again).<br />
<br />
Fourth, control signals 7489 and 7499 select whether Op 2, or its inverted version, is selected through the upper path and to point (A) marked on the schematic.<br />
<br />
Similarly, control signals 7487 and 7488 select whether Op 2, or its inverted version, is selected through the lower path and generates signal (B) on the schematic.<br />
<br />
The instructions that require a subtraction - sub (subtract), rsb (reverse subtract), and cmp (compare) - do so by converting the associated operand into its twos-complement form by inverting all the bits and adding 1 by feeding a '1' into bit 0 of the carry chain (7326) and then performing an add operation.<br />
<br />
The various logic operations (and, or, exclusive or, and bit clear) are selected by selecting the appropriate polarity of each input operand and choosing the right combination of 7489, 7499 and 7487, 7488. For example, note that the only difference in the control signals between the 'and' opcode and 'bic' opcode (bit clear), is that the values on 7489 and 7499 are swapped causing the inverted form of Operand 2 to be fed into the upper calculation path. This is while both 7487 and 7488 are forced high causing signal (B) to be low irrespective of the input.<br />
<br />
The table below shows for all of the opcodes some of the intermediate results, and the outputs for one combination of input bits.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgc923Fyknm6qVVlxezXxDeI_Mbx8dwpFdpk3LB6VaoWV1SiiondHYfmoGm9JWSNhApa_GSSnds64KDgkAuEsve9zp_8L_ELKMLb4SdhEcvX7rJGoFFf3uEaPNJ-QmhDM1L_s1W96Qttug/s1600/sample-signals.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="222" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgc923Fyknm6qVVlxezXxDeI_Mbx8dwpFdpk3LB6VaoWV1SiiondHYfmoGm9JWSNhApa_GSSnds64KDgkAuEsve9zp_8L_ELKMLb4SdhEcvX7rJGoFFf3uEaPNJ-QmhDM1L_s1W96Qttug/s640/sample-signals.PNG" width="640" /></a></div>
<br />
So how are the control signals generated? They're created by PLA-1, but how that part of the circuit works is for another day.<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<br />Davehttp://www.blogger.com/profile/07363645951602549336noreply@blogger.com7tag:blogger.com,1999:blog-6068833812264712077.post-67147943902522495942013-03-16T08:33:00.000-07:002016-01-25T12:16:37.869-08:00im-me Arduino & Java code<span style="font-family: "arial" , "helvetica" , sans-serif;">I've had some people asking me to provide the arduino and Java source code that I wrote for my hacking.</span><br />
<br />
<br />
<div style="background-color: white; color: #222222; font-family: arial, sans-serif;">
It's been ages since I was doing this work, but here's what I can remember, and the code that I used. You'll need to know some electronics, arduino programming, and Java to get all this to work for yourself.</div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif;">
<br /></div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif;">
Yes, I used the Arduino to program the im-me as I mentioned here: <a href="http://daveshacks.blogspot.co.uk/2010/01/im-me-hacking.html" style="color: #1155cc;" target="_blank">http://daveshacks.<wbr></wbr>blogspot.co.uk/2010/01/im-me-<wbr></wbr>hacking.html</a> You'll need to breadboard a voltage-level converting circuit as I described there.</div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif;">
<br /></div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif;">
I initially got the interface into the im-me working just with the Arduino, and once I got it working reliably later moved most of the logic into a Java application running on my windows PC. The arduino sketch that I used at the time is here: <a href="https://www.dropbox.com/s/1tca3see5loka1c/cc1110debug.pde">https://www.dropbox.com/s/1tca3see5loka1c/cc1110debug.pde</a>. You'll see from the code how it evolved from being standalone and controlled by commands I typed in via the UART, to being a simple interface to the Java application. I recommend that you start your journey by reverting the code to arduino-only to begin with (e.g. rename loop1() to loop()). Once you get standalone mode working you can then add back the Java piece.</div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif;">
<br /></div>
<div style="background-color: white;">
<span style="color: #222222; font-family: "arial" , sans-serif;">A zip containing all my Java-related code is here: </span><span style="color: #1155cc; font-family: "arial" , sans-serif;"><u><a href="https://www.dropbox.com/s/cwaqlmy6drdoh3o/debugger.zip">https://www.dropbox.com/s/cwaqlmy6drdoh3o/debugger.zip</a></u></span><span style="color: #222222; font-family: "arial" , sans-serif;">. You'll see quite a bit of java code that's similar to that in the arduino sketch - this relates to how I moved more and more functionality from the arduino to Java. Just ignore the references to CypressUsb - this relates to some work I was doing with the im-me dongle. This is code I used to experiment with, and is far from polished! Good luck reading, understanding, and tweaking it to work for yourself.</span></div>
Davehttp://www.blogger.com/profile/07363645951602549336noreply@blogger.com8tag:blogger.com,1999:blog-6068833812264712077.post-65358111131644552902010-01-31T10:38:00.000-08:002010-01-31T10:38:08.276-08:00im-me LCD Interface HackedGood news everyone, I've reverse engineered the im-me's LCD Display interface and now have working code it drive it. Here's a photo showing a variation on "Hello World":<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEBnscHf-E3ZKim8VO-uv7sifo5veUkfPq0vd7XGb7qaZoZmPnBm05vubJ2-iGHBb9clpjuIIeEU8A5y1HsioTO48-xYnK9L9CVp0OtXViIvX17UqmWki90vA9aGNAJ7-lfBUKkrNaF7o/s1600-h/DSC02982.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEBnscHf-E3ZKim8VO-uv7sifo5veUkfPq0vd7XGb7qaZoZmPnBm05vubJ2-iGHBb9clpjuIIeEU8A5y1HsioTO48-xYnK9L9CVp0OtXViIvX17UqmWki90vA9aGNAJ7-lfBUKkrNaF7o/s320/DSC02982.JPG" width="320" /></a></div><br />
It was quite a journey and took much longer to reverse engineer than I expected. First I'll describe the steps I took, and then I'll summarise the interface.<br />
<br />
I started by using an oscilloscope to probe the 5x wires interfacing the CC1110 to the LCD interface. The signal waveforms gave some clues, but not the complete picture. For instance it was pretty clear from the photo below that the upper trace with the 8 regular pulses was the SPI clock (P0_5, SCK) , and that the lower trace was the data from Master to Slave (P0_3, MOSI - Master Out Slave In):<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOPAupoNZqvJCXffZxZ87Cf61lIdqJ_JGnmsJrW7r60j4Va3TQOCvGIX4kxJEpsJ8oZNOLmJAU9lMUCgQzYWCWbgc63ElF1EvkEJC0HOBODUYK-rQDYJ7Bg0ig_fhu-m7BhOk5cswydaU/s1600-h/spi-clock.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOPAupoNZqvJCXffZxZ87Cf61lIdqJ_JGnmsJrW7r60j4Va3TQOCvGIX4kxJEpsJ8oZNOLmJAU9lMUCgQzYWCWbgc63ElF1EvkEJC0HOBODUYK-rQDYJ7Bg0ig_fhu-m7BhOk5cswydaU/s320/spi-clock.jpg" /></a></div><br />
<br />
This waveform also told me that the clock SPI clock speed was 2.5MHz, and that the data changes on the trailing edge of the clock (it's difficult to see the faint transitions in the photo above). So the LCD must be reading the data on the leading edge of the clock.<br />
<br />
I pondered how I could spy on the SPI traffic, and concluded that the simplest way to deal with the high speed and the 2.5v signal levels would be to use a second im-me! I used fine wire-wrap wire to connect the SCK and MOSI signals from a fully-functioning im-me to my spy im-me, and wrote a simple program to capture the traffic. The spy program was simple - it would read the data into a memory buffer, and stop when it was full. I'd then use the debug interface to read the results out of the buffer. To write the spy program I used for guidance TI's Design Note <a href="http://focus.ti.com/general/docs/litabsmultiplefilelist.tsp?literatureNumber=swra223a">DN113</a> and the code in <a href="http://www.ti.com/litv/zip/swrc117">CC1110, CC2510 Basic Software Examples</a>. Although the program started capturing SPI output, the results were inconsistent each time I ran it; data was being dropped. It turns out that on reset the CPU runs on an internal RC clock which is half the speed of the Xtal Oscillator; I added some code to the spy program to select the higher speed clock source and it started giving consistent results.<br />
<br />
By interacting with the fully-functioning im-me I was able to get a wide variety of spy traffic and to piece together a lot of how it worked. For instance there seemed to be commands to direct the on-screen cursor, and the graphics was being written 8 vertical bits at a time per byte transferred. It was also clear from the addressing that the data was being sent MSB first (the spy program was reading it LSB first). <br />
<br />
But there was a problem - I couldn't understand how the LCD could distinguish between the command bytes and the data bytes. I would have expected either escape characters to enter/exit data mode, or byte-lengths for the data, but there were none.<br />
<br />
I resorted to the internet, and searched for SPI LCD interface specifications for clues. After many blind alleys I found that Sitronix's range of <span id="goog_1264956246238"></span><a href="http://www.sitronix.com.tw/product_line.htm#ST75xx">SPI-based LCD Driver IC<span id="goog_1264956246239"></span>s</a>. The <a href="http://www.sitronix.com.tw/sitronix/product.nsf/Doc/ST7565S?OpenDocument">ST7565S</a> was particularly interesting because (a) it supports a similar size LCD to the im-me, (b) it has an on-board PSU requiring capacitors wired exactly like the capacitors surrounding the LCD connector on the im-me, (c) many of the commands I had decoded from the SPI spy were identical.<br />
<br />
The ST7565S data sheet also gave me the final clue I needed - an additional wire to the driver IC (A0) indicates whether the byte is a command or data - solving the problem I was struggling with earlier. With a quick modification to the spy program I was able to confirm that P0_2 is the output from the CC1110 to the LCD driver's A0 input.<br />
<br />
So the connections (from the top of the connector to the bottom) are, using ST7565S terminology:<br />
<br />
<ul><li>P0_4 - /CS -- hold low while transferring data (SSN in SPI terminology).</li>
<li>P1_1 - /RESET (I think) -- Pulse low at power up, keep high all the time otherwise</li>
<li>P0_2 - A0 -- Low for a command byte, high for a data byte</li>
<li>P0_5 - SCL -- SPI clock (SCK in SPI terminology)</li>
<li>P0_3 - SI -- Serial Data (MOSI in SPI terminology)</li>
</ul><div>(Note, my guesses for these signals in my original post were wrong).</div><div><br />
</div><div>Now that I had confirmed what the signals and commands were, it was easy to write a small test program for the im-me that would bring the LCD to life. The test program verifies all basic operation. It also exercises commands documented in the ST7565 data sheet that the im-me doesn't use (Display reversed, and Display start line set). It doesn't yet demonstrate contrast adjust (Electronic Volume Mode Set), and I haven't tested Power Save mode either.</div><div><br />
</div><div>The only thing remaining unexplained is a couple of commands in the initialisation sequence that don't appear in the ST7565 data sheet.</div><div><br />
</div><div>Here's the test program's source code I developed using the <a href="http://sdcc.sourceforge.net/">sdcc compiler</a>.</div><div><br />
</div><div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">#include <cc1110.h></cc1110.h></span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">#include "cc1110-ext.h"</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">#define LOW 0;</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">#define HIGH 1;</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">void sleepMillis(int ms) {</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">int j;</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">while (--ms > 0) { </span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> <span class="Apple-style-span" style="white-space: normal;">for (j=0; j<1200;j++); // about 1 millisecond</span></span></span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">};</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">}</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">void xtalClock() { // Set system clock source to 26 Mhz</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> SLEEP &= ~SLEEP_OSC_PD;</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// Turn both high speed oscillators on</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> while( !(SLEEP & SLEEP_XOSC_S) );</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// Wait until xtal oscillator is stable</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> CLKCON = (CLKCON & ~(CLKCON_CLKSPD | CLKCON_OSC)) | CLKSPD_DIV_1;</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// Select xtal osc, 26 MHz</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> while (CLKCON & CLKCON_OSC);</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// Wait for change to take effect</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> SLEEP |= SLEEP_OSC_PD;</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// Turn off the other high speed oscillator (the RC osc)</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">}</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// IO Port Definitions:</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">#define A0 </span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">P0_2</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">#define SSN </span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">P0_4</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">#define LCDRst </span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">P1_1</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">#define LED_RED </span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">P2_3</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">#define LED_GREEN </span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">P2_4</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// plus SPI ports driven from USART0 are:</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// MOSI</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">P0_3</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// SCK</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">P0_5</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">void setIOPorts() {</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">//No need to set PERCFG or P2DIR as default values on reset are fine</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> P0SEL |= (BIT5 | BIT3 );<span class="Apple-style-span" style="white-space: pre;"> <span class="Apple-style-span" style="white-space: normal;">// set SCK and MOSI as peripheral outputs</span></span></span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">P0DIR |= BIT4 | BIT2;</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// set SSN and A0 as outputs</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">P1DIR |= BIT1;</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// set LCDRst as output</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">P2DIR = BIT3 | BIT4;</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// set LEDs as outputs</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">LED_GREEN = LOW;</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// Turn the Green LED on (LEDs driven by reverse logic: 0 is ON)</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">}</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// Set a clock rate of approx. 2.5 Mbps for 26 MHz Xtal clock</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">#define SPI_BAUD_M 170</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">#define SPI_BAUD_E 16</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">void configureSPI() {</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">U0CSR = 0; <span class="Apple-style-span" style="white-space: pre;"> <span class="Apple-style-span" style="white-space: normal;">//Set SPI Master operation</span></span></span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> <span class="Apple-style-span" style="white-space: pre;"> <span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: medium; white-space: normal;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">U0BAUD = SPI_BAUD_M;</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// set Mantissa</span></span></span></span></span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">U0GCR = U0GCR_ORDER | SPI_BAUD_E; // set clock on 1st edge, -ve clock polarity, MSB first, and exponent</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">}</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">void tx(unsigned char ch) {</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="white-space: pre;"> </span>U0DBUF = ch;</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="white-space: pre;"> </span>while(!(U0CSR & U0CSR_TX_BYTE)); // wait for byte to be transmitted</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="white-space: pre;"> </span>U0CSR &= ~U0CSR_TX_BYTE; // Clear transmit byte status</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">}</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">void txData(unsigned char ch) {</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">A0 = HIGH;</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">tx(ch);</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">}</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">void txCtl(unsigned char ch){</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">A0 = LOW;</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">tx(ch);</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">}</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">void LCDReset(void) {</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">LCDRst = LOW;</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// hold down the RESET line to reset the display</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">sleepMillis(1);</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">LCDRst = HIGH;</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">SSN = LOW;</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// send the initialisation commands to the LCD display</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">txCtl(0xe2);</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// RESET cmd</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">txCtl(0x24);</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// set internal resistor ratio</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">txCtl(0x81);</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// set Vol Control</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">txCtl(0x60);</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// set Vol Control - ctd</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">txCtl(0xe6);</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// ?? -- don't know what this command is</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">txCtl(0x00);</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// ?? -- don't know what this command is</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">txCtl(0x2f);</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// set internal PSU operating mode</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">txCtl(0xa1);</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// LCD bias set</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">txCtl(0xaf);</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// Display ON</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">SSN = HIGH;</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">}</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">void LCDPowerSave() { // not tested yet; taken from spi trace</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">txCtl(0xac);</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// static indicator off cmd</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">txCtl(0xae);</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// LCD off</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">txCtl(0xa5);</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// Display all Points on cmd = Power Save when following LCD off</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">}</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">void setCursor(unsigned char row, unsigned char col) {</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">txCtl(0xb0 + row);</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// set cursor row</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">txCtl(0x00 + (col & 0x0f));</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// set cursor col low</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">txCtl(0x10 + ( (col>>4) & 0x0f));</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// set cursor col high</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">}</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">void setDisplayStart(unsigned char start) {</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">txCtl(0x40 | (start & 0x3f)); // set Display start address</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">}</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">void setNormalReverse(unsigned char normal) { // 0 = Normal, 1 = Reverse</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">txCtl(0xa6 | (normal & 0x01) );</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">}</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">unsigned int i;</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">unsigned char row;</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">unsigned char col;</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">unsigned char displayStart;</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">static const unsigned char helloWorld[] = {</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">0x7f, 0x08, 0x08, 0x08, 0x7f, 0x00, </span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">//H</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">0x38, 0x54, 0x54, 0x54, 0x18, 0x00,</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">//e</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">0x00, 0x41, 0x7f, 0x40, 0x00, //0x00,</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">//l</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">0x00, 0x41, 0x7f, 0x40, 0x00, //0x00,</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">//l</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">0x38, 0x44, 0x44, 0x44, 0x38, 0x00,</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">//o</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">0x00, 0x00, 0x00, 0x00, 0x00, //0x00,</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">0x7f, 0x08, 0x08, 0x08, 0x7f, 0x00, </span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">//H</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">0x20, 0x54, 0x54, 0x54, 0x78, 0x00,</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">//a</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">0x38, 0x44, 0x44, 0x44, 0x20, 0x00,</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">//c</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">0x7f, 0x10, 0x28, 0x44, 0x00, //0x00,</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">//k</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">0x20, 0x54, 0x54, 0x54, 0x78, 0x00,</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">//a</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">0x38, 0x44, 0x44, 0x48, 0x3f, 0x00,</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">//d</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">0x20, 0x54, 0x54, 0x54, 0x78, 0x00,</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">//a</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">0x0c, 0x50, 0x50, 0x50, 0x3c, 0x00,</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">//y</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">0x00, 0x00, 0x00, 0x00, 0x00, //0x00,</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">0x3f, 0x40, 0x38, 0x40, 0x3f, 0x00,</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">//W</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">0x38, 0x44, 0x44, 0x44, 0x38, 0x00,</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">//o</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">0x7c, 0x08, 0x04, 0x04, 0x08, 0x00,</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">//r</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">0x00, 0x41, 0x7f, 0x40, 0x00, //0x00,</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">//l</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">0x38, 0x44, 0x44, 0x48, 0x3f, 0x00//,</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">//d</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">//0x01, 0x02, 0x03, 0x04, 0x05, 0x06,</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// temp</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">//0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">//0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// total = 23*6 -6 = 138 - 6 = 132 pixels, or 22 chars</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">};</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">void main(void) {</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">xtalClock();</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// select the xtal clock for fastest transfer speed</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">setIOPorts();</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">configureSPI();</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">LCDReset();</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> while (1) {</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">SSN = LOW;</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">setDisplayStart(displayStart++);</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">setNormalReverse(displayStart); // screen will alternate between normal and reverse on each scroll</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">for (row=0; row<=8; row++) {</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// LCD is 65 pixels high, or 9 rows; clear all of them</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">setCursor(row, 0);</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">for (i=0; i<132; i++) {</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// clear every row on the line</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">txData(0x00);</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">};</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">if (row != 8) {</span></span><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">// Don't paint the 9th row as only the top row of its pixels are displayed</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">setCursor(row, row<<1); // indent each successive row by two pixels</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">for (col=0; col<sizeof col++)="" helloworld;="" {=""></sizeof></span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">txData(helloWorld[col]);</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">};</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">}</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">}</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">SSN = HIGH;</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">sleepMillis(1000);</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">LED_RED = !LED_RED;</span></span></div><div><span class="Apple-tab-span" style="white-space: pre;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> </span></span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">}</span></span></div><div><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">}</span></span></div><div><br />
</div></div>Davehttp://www.blogger.com/profile/07363645951602549336noreply@blogger.com9tag:blogger.com,1999:blog-6068833812264712077.post-20663073315370882062010-01-02T03:37:00.000-08:002010-01-31T10:39:32.540-08:00im-me hackingI came across <a href="http://hunterdavis.com/archives/333">this blog</a> describing hacking the <a href="http://www.girltech.com/electronics-imMe.aspx">im-me</a>, a small wireless console. It looked interesting, so I went ahead and bought a couple. For £8 you get a console and a USB radio dongle. It turns out that they are a bargain for what they contain, provided you can discover how to "re-purpose" the hardware.<br />
<br />
I became much more interested when I discovered <a href="http://travisgoodspeed.blogspot.com/2009/10/cc2430-debug-protocol-first-notes.html">Travis Goodspeed's blog</a> describing how to implement the debug port on a related processor. <br />
<div><br />
</div><div><span style="font-weight: bold;">The console</span></div><div><div><br />
</div><div>The console is really simple but powerful, containing:</div><div><ul><li>A <a href="http://focus.ti.com/docs/prod/folders/print/cc1110f32.html">CC1110F32</a> radio/processor: 32k flash, 4k ram, 900MHz transceiver, with a debug port exposed.</li>
<li>An 8x24 LCD display, with backlight. The LCD has an SPI interface.</li>
<li>A full qwerty keyboard.</li>
<li>A piezoelectric sounder.</li>
<li>A voltage regulator, and a small number of sundry SMD parts - transistors, Rs, and Cs.</li>
</ul><div><span style="font-weight: bold;">The Wireless USB Dongle</span></div><div><br />
</div><div>The dongle contains:</div><div><ul><li>A <a href="http://focus.ti.com/docs/prod/folders/print/cc1110f32.html">CC1110</a> radio/processor identical to that in the console.</li>
<li>A <a href="http://www.cypress.com/?id=182">CY7C63803</a> processor with USB interface.</li>
</ul><div>The FCC ID is Grantee code: <span style="color: red;">PIY</span>, product code: <span style="color: red;">L7281D1</span></div><div><br />
</div></div><div><b>The Console Debug Port</b><br />
<br />
The debug port on the CC1110 is conveniently wired out to some test pads that are accessible via holes in the bottom of the battery tray. Connections are (from left to right):<br />
<div><ul><li>(square pad) RESET_N</li>
<li>P2_1 = debug data</li>
<li>P2_2 = debug clock</li>
<li>+2.5 volts</li>
<li>Gnd</li>
</ul><div>Here's a photo showing the wires I've soldered to the test pads that connect to the Arduino via a breadboard. (I don't use the 2.5v connection as I supply power via the battery compartment, and rely on the on-board regulator to generate 2.5v.)</div><div><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-t4BF8zxuMiN9h7c8ZzrHDWhrNF7bKiOg_YG9Yiuo89_tthVsnSu_TigC3RlgA7FWa-rendOTLuCMDJxnc_r0CxFittXAcNobbnkZeKTJAyntEHOg6mqKH_puNOFBCqcFldWYcsr5F0I/s1600-h/DSC02958.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-t4BF8zxuMiN9h7c8ZzrHDWhrNF7bKiOg_YG9Yiuo89_tthVsnSu_TigC3RlgA7FWa-rendOTLuCMDJxnc_r0CxFittXAcNobbnkZeKTJAyntEHOg6mqKH_puNOFBCqcFldWYcsr5F0I/s320/DSC02958.JPG" /></a></div><div><br />
</div></div></div></div><div><div><div>I wanted to drive this port via an Arduino, but couldn't drive it directly since the CC1110 runs off 2.5v as compared to the Arduino's +5volts. The CC1110 is also intolerant of voltages more than 0.3v above VDD. The solution was simple - the outputs from the Arduino are fed into voltage dividers (The DATA pin on the CC1110 is both an input and output so I decided to use relatively high value 3.3K resistors to present minimal load when it is an output). To read the data line back into the Arduino, I wired the debug data pin to the Arduino's positive comparator input too, and set the comparator's negative input to about 1.7 volts. <br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtbRXJqfXQiL2SEVRCBQvZ6jsQWo9h8-p6AVWICCznG0RrgnQIRDQ-J-TxdX3Iot5-V_1IiC0XLMfX61njnGGE7CpHIzK3dqIjH-1iJeas5F7UXwTZFnft0f5-oOptfB88uLDo3cQUenU/s1600-h/IMAG0094.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtbRXJqfXQiL2SEVRCBQvZ6jsQWo9h8-p6AVWICCznG0RrgnQIRDQ-J-TxdX3Iot5-V_1IiC0XLMfX61njnGGE7CpHIzK3dqIjH-1iJeas5F7UXwTZFnft0f5-oOptfB88uLDo3cQUenU/s320/IMAG0094.jpg" /></a></div><br />
<br />
(A word of warning - keep the lead lengths short - I had variable results when I initially just used test leads to connect everything.)<br />
<br />
I wrote some Arduino interfacing code, using <a href="http://travisgoodspeed.blogspot.com/2009/10/cc2430-debug-protocol-first-notes.html">Travis's blog</a>, the <a href="http://focus.ti.com/lit/ug/swra124/swra124.pdf">official documentation</a> for the debug port, and <a href="http://sourceforge.net/projects/ccflasher/">CCFlasher </a>(another implementation) for inspiration. By executing the "READ_STATUS" command it became evident that the "DEBUG_LOCKED" bit is set. This bit prevents the firmware from being read out, so it's not surprising that it is set. However, a "CHIP_ERASE" can be executed, which erases the entire flash memory, and enables the full debug port capability, which is what I've done on one of my consoles. I'm now able to download data to the chip and to execute programs in RAM or in flash. The full hardware capabilities of the console are now at my disposal.<br />
<br />
The Arduino code is still very much work in progress, but provides some basic facilities to allow me to experiment via the Serial Monitor interface of the Arduino IDE. I'm now working on some facilities to allow me to download and flash programs more easily. More later...<br />
<br />
<b>Console CC1110 Processor Development</b><br />
<br />
Software development for the processor can be carried via this tool: <span style="color: #444444; font-family: Verdana, Helvetica, Arial, sans-serif; font-size: 13px; line-height: 18px;"><a href="http://www.google.com/url?q=http%3A%2F%2Fsupp.iar.com%2FDownload%2FSW%2F%3Fitem%3DEW8051-KS4&sa=D&sntz=1&usg=AFrqEzdQziHo1UW11Tk8PHYXqpF7gQNisg" style="border-bottom-color: rgb(187, 36, 45); border-bottom-style: dotted; border-bottom-width: 1px; color: #333333; text-decoration: underline;"><span style="background-color: white;">http://supp.iar.com/Download/SW/?item=EW8051-KS4</span></a> <span style="color: black; font-family: 'Times New Roman'; font-size: medium; line-height: normal;"><span style="font-size: medium;">This "kickstart" free version of the commercial tool can have its code size limits increased if you follow the guidelines in Section 9.1 of </span><span style="color: #444444; font-family: Verdana, Helvetica, Arial, sans-serif; font-size: 13px; line-height: 18px;"><a href="http://www.google.com/url?q=http%3A%2F%2Ffocus.ti.com%2Flit%2Fug%2Fswru236a%2Fswru236a.pdf&sa=D&sntz=1&usg=AFrqEzfG5FwhP_4XZheitCnYgwSKsVWlUw" style="color: black; text-decoration: underline;">http://focus.ti.com/lit/ug/swru236a/swru236a.pdf</a>.</span></span></span><br />
<span style="color: #444444; font-family: Verdana, Helvetica, Arial, sans-serif; font-size: small;"><span style="font-size: 13px; line-height: 18px;"><br />
</span></span><br />
<span style="color: #444444;"><span style="line-height: 18px;"><span style="color: black; line-height: normal;"><span style="font-family: Times, 'Times New Roman', serif;">The IDE can be configured to generate it's output in the simple Intel format, which is ideal for me to download to the processor with via the Arduino.</span></span></span></span><br />
<span style="color: #444444; font-family: Verdana, Helvetica, Arial, sans-serif; font-size: small;"><span style="font-size: 13px; line-height: 18px;"><br />
</span></span><br />
<span style="color: #444444; font-family: Verdana, Helvetica, Arial, sans-serif; font-size: small;"><span style="font-size: 13px; line-height: 18px;"><span style="color: black; font-family: 'Times New Roman'; font-size: medium; font-weight: bold; line-height: normal;">Console Keyboard</span></span></span><br />
<b><br />
</b><br />
The 40 odd keyboard buttons are wired as a matrix, but the designers use some tricks to minimise the number of i/o pins. The i/o pins used are:<br />
<br />
<ul><li>"row" pins: P0_1, P1_2, P1_3, P1_4, P1_5, P1_6, P1_7 - input and output. Normally high, regular very short pulses to 0v.</li>
<li>P0_6, P0_7 - input only.</li>
</ul><div>The key connections are shown in the table below.</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNAH9BUFCRDc1R6G0MP7MzH7OpNV0xon0FX0qhWOpOIo8FQ4MUFrUY3hEwFffr116RsB6rt9GiwmickV9snvBEqrpPjpz6xNTV0A1urojIR4lCO0_3wnxwpGk7cS-asOZNn6MujJqUzzc/s1600-h/keys.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNAH9BUFCRDc1R6G0MP7MzH7OpNV0xon0FX0qhWOpOIo8FQ4MUFrUY3hEwFffr116RsB6rt9GiwmickV9snvBEqrpPjpz6xNTV0A1urojIR4lCO0_3wnxwpGk7cS-asOZNn6MujJqUzzc/s400/keys.jpg" /></a></div><br />
One keyboard sensing algorithm would be:<br />
<ul><li>Set all keyboard i/o pins to inputs, with pullups to Vcc. Read all inputs, and if any pin is zero, it is because one of the keys connected to Gnd is pressed. For instance, if P1_2 is zero, it means the "O" key is pressed.</li>
<li>Set P0_1 as an output, and 0v. Read all inputs (except P0_1 of course), and if any any pin is zero, it is because one of the keys on the "P0_1" row is pressed. For instance, if P0_6 is zero, it means the "Menu" key is pressed. Return the P0_1 to an input.</li>
<li>In a similar manner, take each of P1_2, P1_3, P1_4, P1_6, P1_7 low in turn, checking each time for a key press.</li>
<li>Add bebounce logic - e.g. repeatedly go through the steps above, and only report a key-press if the same key is pressed on 2 consecutive loops. </li>
</ul><br />
<b>Console Radio</b><br />
<br />
Some information about the radio can be gathered from the FFC submission. FCC submission details are found by searching for PIY/L7281H1 on the <a href="http://www.fcc.gov/oet/ea/fccid/">FCC site</a>. There are internal photos, radio frequency details, and transmission spectra.<br />
<br />
The standard unit transmits/receives on up to 16 different frequencies between 908.45MHz and 920.6MHz. <br />
<br />
I've been using my trusty Tektronix 7L14 Spectrum Analyser to see how the units currently communicate. On startup the console polls on all 16 channels to make contact with the wireless USB dongle.<br />
<br />
Once communication has been established on one of the channels, the console and dongle continue to use just that channel thereafter. The console polls the dongle about every 0.2 seconds. Here's a typical sequence:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj05C-Rt8Pv4qA2YRVUEYfmUoCsKaEOVvuA3ErEKynjEWZqJqDsyY1-XDqLDGl5sDhweC8fdMZ5b26PAiv7qWmaDyOklfkjGryGqmjE7crBglIHVQ_BfC_X8q-pH0g_auWEmfXAYtzXKaw/s1600-h/DSC02968.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj05C-Rt8Pv4qA2YRVUEYfmUoCsKaEOVvuA3ErEKynjEWZqJqDsyY1-XDqLDGl5sDhweC8fdMZ5b26PAiv7qWmaDyOklfkjGryGqmjE7crBglIHVQ_BfC_X8q-pH0g_auWEmfXAYtzXKaw/s320/DSC02968.JPG" /></a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: left;">The console polls the dongle, and the dongle responds about 10 milliseconds later (the dongle is physically further away from the SA input and sothe signal is weaker). The dongle then sends a message (a poll?) about 3 milliseconds later. Finally the console replies to the poll after about 10 milliseconds. This sequence repeats every 0.2 seconds, but the total transmission time for the console is 4 milliseconds, so the portion of time spent transmitting (and therefore consuming battery power) is just 2%.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">If each poll/ack message is about minimal length, it corresponds to around 96 bits by the time you take into account the preamble, sync, length, address, data, and CRC. 96 bits transmitted in 2 ms is 50kbps. So the minimum radio tx/rx data rate is 50 kbps, but could easily be higher.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">The photo above also gives us a clue to the type of modulation being used. The fact that the signal strength remains the same during the transmission period indicates that the amplitude modulation options supported by the CC1110 - On-Off Keying (OOK) and Amplitude Shift Keying (ASK) - aren't being used.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">A plot of the transmission spectrum shows that transmission is on two frequencies 300kHz apart:</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiB8O7uyX2pgTUNkAPWjgOyNk0WoIGQ_83ci-w9W15-9lk14V-SAPwelHZDsocjDx7nUtxCcwgl7Rwj8U7j8e2fjKTr5WnTuxY5u9jTYBbnKYIz37lZZwQEYUnlMViEsnTJJnbAL6eBjAQ/s1600-h/DSC02970.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiB8O7uyX2pgTUNkAPWjgOyNk0WoIGQ_83ci-w9W15-9lk14V-SAPwelHZDsocjDx7nUtxCcwgl7Rwj8U7j8e2fjKTr5WnTuxY5u9jTYBbnKYIz37lZZwQEYUnlMViEsnTJJnbAL6eBjAQ/s320/DSC02970.JPG" /></a></div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">Zooming x10 into the twin peaks reveals this spectrum:</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgH_rzJlVk4_4DrEY7dnKgALPNqMpsQ9TZLmGnMz4xzi-q89tLsC0IDZnXZVUl16KEQj0zx7p9buycbAptgYoyOwgfpcX0QPxugVva-qVh78LokuJIq_sE3DPpUZ9xx9dRU9vsum0IqrX4/s1600-h/DSC02972.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgH_rzJlVk4_4DrEY7dnKgALPNqMpsQ9TZLmGnMz4xzi-q89tLsC0IDZnXZVUl16KEQj0zx7p9buycbAptgYoyOwgfpcX0QPxugVva-qVh78LokuJIq_sE3DPpUZ9xx9dRU9vsum0IqrX4/s320/DSC02972.JPG" /></a><br />
<div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">The smaller peaks at 50kHz intervals between the two main peaks are likely the result of the data rate setting, and gives further evidence that the data rate is 50kbps. The very narrow peaks also hint that there is no modulation smoothing, which rules out the chip's Minimum Shift Keying (MSK) and the Gaussian filtering option available with Frequency Shirt Keying (FSK). This leaves just the 2-FSK modulation option, with the deviation set at +/- 150kHz.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;"><b>LCD Interface</b></div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">The LCD is connected via a 20 way ribbon cable. The connector is on the left ofn the photo below:</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhc4qAK-Yovw5oNstAvAiJwZ4uClk1FpioNI4zN3BjvWMBclSEd1fMKhIdryTmsv49PMGGWHkwk1Fb8__ijIb8xxxOvhRARPooNPf8FHhUznTkjBZXRrSLL_713Gocvsj9A9iC1l_gNEjE/s1600-h/lcd-interface.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhc4qAK-Yovw5oNstAvAiJwZ4uClk1FpioNI4zN3BjvWMBclSEd1fMKhIdryTmsv49PMGGWHkwk1Fb8__ijIb8xxxOvhRARPooNPf8FHhUznTkjBZXRrSLL_713Gocvsj9A9iC1l_gNEjE/s320/lcd-interface.jpg" /></a><br />
<div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;"></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">The connections (from the top of the connector to the bottom) are, using ST7565S terminology:</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"></div><ul><li>P0_4 - /CS -- hold low while transferring data (SSN in SPI terminology).</li>
<li>P1_1 - /RESET (I think) -- Pulse low at power up, keep high all the time otherwise</li>
<li>P0_2 - A0 -- Low for a command byte, high for a data byte</li>
<li>P0_5 - SCL -- SPI clock (SCK in SPI terminology)</li>
<li>P0_3 - SI -- Serial Data (MOSI in SPI terminology)</li>
<li>+2.5v</li>
<li>Gnd</li>
<li>(the remaining 13 pins are connected via capacitors either together or to ground, and are part of a high voltage generator circuit in the LCD)</li>
</ul><div>All the data connections are easily accessible via the test points between the connector and the processor.</div><br />
<b>Other Processor Connections</b><br />
<br />
The only remaining i/o port connections on the processor are:<br />
<ul><li>P0_0 - decoupled voltage divider input (to measure 2.5v to detect battery low condition?)</li>
<li>P1_0 - digital output to transducer</li>
<li>P2_0 - digital input/output to backlight circuit?</li>
<li>P2_3 - digital output to status LED (red?)</li>
<li>P2_4 - digital output to status LED (green?)</li>
</ul><div><br />
</div><br />
</div></div></div></div>Davehttp://www.blogger.com/profile/07363645951602549336noreply@blogger.com183