tag:blogger.com,1999:blog-87562018879554233832024-03-19T05:32:12.615+01:00Tools for Art and MicrocomputersSome ideas about programming tools and techniques, microcomputers and free and open software than can be used when working with Art and MicrocomputersMagnus Lundinhttp://www.blogger.com/profile/17303004553752920522noreply@blogger.comBlogger17125tag:blogger.com,1999:blog-8756201887955423383.post-47625322248446000502016-12-11T19:21:00.000+01:002016-12-20T20:29:30.687+01:00Dynamic Systems and Mechanics with Free and Open tools<i>Note: This is at the moment only a work in progress blog post, I didn't plan to post this until it was a bit more complete and polished,&nbsp; but since its here I keep it public but I will keep modifying a bit when I got the time.</i><br />
<br />
<br />
Mixed control and mechanics problems like controlling an inverted pendulum, a robotic arm or a flying drones gives rise to mechanical problems that can be solved by standard methods but the calculations can get quite involved and translating the formulas into C code without errors needs very careful work.The free CAS system Maxima can help us in the calculations and also generate almost runnable code expressions. The following example shows how the equations of motion for an inverted pendulum can be derived with the aid of Maxima.<br />
<br />
<h3>
Deriving the equations of motion in Maxima<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "arial" , "helvetica" , sans-serif;"> </span></span></span></h3>
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "arial" , "helvetica" , sans-serif;">The first command tells Maxima that p1,p2, p3 and p4 are functions of t, this important for taking derivatives later. The next line is the Lagrangian.</span> </span></span><br />
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"></span></span><br />
<span style="font-size: small;"><span style="font-family: "courier new" , "courier" , monospace;">depends([p1,p2,q1,q2],t);</span></span><br />
<span style="font-size: small;"><span style="font-family: "courier new" , "courier" , monospace;">L:M*p1^2/2+1/2*m*((p1+l*p2*cos(q2))^2+(l*p2*sin(q2))^2+I*p2^2)-m*g*l*cos(q2);</span></span><br />
<br />
The equations of motion are given by<br />
\( \frac{d}{dt} \left [ \frac{\partial L}{\partial p_i} \right ] - \frac{\partial L}{\partial q_i} = F_i \)<br />
<br />
<br />
<span style="font-size: small;"><span style="font-family: "courier new" , "courier" , monospace;">eq1:ratsimp(diff(diff(L,p1),t)-diff(L,q1)=F);</span></span><br />
<span style="font-size: small;"><span style="font-family: "courier new" , "courier" , monospace;">eq2:ratsimp(diff(diff(L,p2),t)-diff(L,q2)=0);</span></span><br />
<span style="font-size: small;"><br /></span>
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"><br /></span></span>
<br />
<h3>
Rewriting the equations of motions as a dynamical system</h3>
<br />
<span style="font-size: small;"><span style="font-family: "courier new" , "courier" , monospace;">ds1:ev(solve([eq1,eq2],[diff(p1,t),diff(p2,t)]),[diff(q1,t)=p1,diff(q2,t)=p2]);</span></span><br />
<span style="font-size: small;"><span style="font-family: "courier new" , "courier" , monospace;">ds2:trigsimp(ds1);</span></span><br />
<br />
The resulting dynamical system where the definitions of p1 and p2 as derivatives of q1 and q2 has been inserted:<br />
<br />
\( \begin{align*}<br />
\frac{d}{d\,t}\,q1 &=p1 &\\<br />
\frac{d}{d\,t}\,p1 &=\frac{\left( F+l\,m\,{p2}^{2}\,\mathrm{sin}\left( q2\right) \right) \,I+{l}^{2}\,F+\left( {l}^{3}\,m\,{p2}^{2}−g\,{l}^{2}\,m\,\mathrm{cos}\left( q2\right) \right) \,\mathrm{sin}\left( q2\right) }{\left( I+{l}^{2}\right) \,M+m\,I+{l}^{2}\,m\,{\mathrm{sin}\left( q2\right) }^{2}} \\<br />
\frac{d}{d\,t}\,q2 &=p2 \\ <br />
\frac{d}{d\,t}\,p2 &=\frac{g\,l\,\mathrm{sin}\left( q2\right) \,M−l\,\mathrm{cos}\left( q2\right) \,F+\left( g\,l\,m−{l}^{2}\,m\,{p2}^{2}\,\mathrm{cos}\left( q2\right) \right) \,\mathrm{sin}\left( q2\right) }{\left( I+{l}^{2}\right) \,M+m\,I+{l}^{2}\,m\,{\mathrm{sin}\left( q2\right) }^{2}} <br />
\end{align*} \)<br />
<br />
<h3>
Converting our system into C code</h3>
The Maxima 'fortran' command gives us an output that quite easily can be changed into a usable C formula.<br />
<br />
<span style="font-size: small;"><span style="font-family: "courier new" , "courier" , monospace;">fortran(ds2); </span></span><br />
<br />
ds2(1) = ['diff(p1,t,1) = ((F+l*m*p2**2*sin(q2))*I+l**2*F+(l**3*m*<br />
1 p2**2-g*l**2*m*cos(q2))*sin(q2))/((I+l**2)*M+m*I+l**2*m*sin(q2)<br />
2 **2),'diff(p2,t,1) = (g*l*sin(q2)*M-l*cos(q2)*F+(g*l*m-l**2*m*p<br />
3 2**2*cos(q2))*sin(q2))/((I+l**2)*M+m*I+l**2*m*sin(q2)**2)]<span style="font-family: inherit;"><span style="font-family: inherit;"><span style="font-size: small;"><span style="font-family: "courier new" , "courier" , monospace;"> </span></span></span></span><br />
<br />
<br />
There are some Fortran constructs to remove, like line numbers and ** as the power operator, but all the elements of the formulas are in place.<br />
<br />
<br />
<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;">depends([p1,p2,q1,q2],t);</span></span><span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;">L:M*p1^2/2+1/2*m*((p1+l*p2*cos(q2))^2+(l*p2*sin(q2))^2+I*p2^2)-m*g*l*cos(q2);</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;">eq1:ratsimp(diff(diff(L,p1),t)-diff(L,q1)=F);</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;">eq2:ratsimp(diff(diff(L,p2),t)-diff(L,q2)=0);</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;">ds1:ev(solve([eq1,eq2],[diff(p1,t),diff(p2,t)]),[diff(q1,t)=p1,diff(q2,t)=p2]);</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;">ds2:trigsimp(ds1);</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;">fortran(ds2); </span></span><br />
<br />
<br />
<br />
A good discussion of using Maxima together with Octave/Matlab can be found here:<br />
<a href="http://math-blog.com/using-maxima-output-in-octave/">http://math-blog.com/using-maxima-output-in-octave/</a><br />
<br />
<br />
<br />
<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"></span></span>Magnus Lundinhttp://www.blogger.com/profile/17303004553752920522noreply@blogger.com0tag:blogger.com,1999:blog-8756201887955423383.post-42994772012150179762016-11-19T00:44:00.002+01:002016-11-20T21:27:57.653+01:00PSoC 5LP - DFB assembler and some more ACU techniques<h2 dir="ltr" id="docs-internal-guid-ad448870-79be-ef3b-f065-eb964ed33ee2" style="line-height: 1.38; margin-bottom: 6pt; margin-top: 18pt;">
<span style="background-color: transparent; color: black; font-family: "arial"; font-size: 21.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Saving ACU state and using per loop block addressing</span><span style="background-color: transparent; color: black; font-family: "arial"; font-size: 21.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> </span></h2>
<span style="font-family: "arial" , "helvetica" , sans-serif;"></span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"></span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"></span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;">Working with the DFB assembler for a while reveals how clever and powerful the architecture is, the ACU registers and the ACU RAM can be used to generate address patterns to pointing into the RAMA and RAMB memory blocks. <br /> </span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;">We can use the ACU and ACU RAM to create several blocks of RAM memory that are used by consecutive loops. A possible configuration using three blocks with 3 and 4 elements respectively. is seen in the figure below.</span><br />
<ul>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">ACU RAM[0] saves the start positions for the current block, this can be read into ACU REG with acu(read,read) addr(0) instead of using acu(clear,clear) to address the base of the block</span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">ACU RAM[1] saves the size of the blocks, read into FREG and used to increase memory pointers at the end of a loop</span><span style="font-family: "arial" , "helvetica" , sans-serif;"> </span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">ACU RAM[1] saves the last position in the last block, this is used but the ACU modulo arithmetic to loop back to the beginning of the first block.</span><span style="font-family: "arial" , "helvetica" , sans-serif;"> </span></li>
</ul>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span id="docs-internal-guid-ad448870-79c2-d325-5792-e6906d13f8d1" style="background-color: transparent; color: black; font-family: "arial"; font-size: 14.666666666666666px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><span id="docs-internal-guid-ad448870-79c5-9b04-fffe-e1f93d4fc0bc" style="background-color: transparent; color: black; font-family: "arial"; font-size: 14.666666666666666px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><span id="docs-internal-guid-ad448870-79c5-9b04-fffe-e1f93d4fc0bc" style="background-color: transparent; color: black; font-family: "arial"; font-size: 14.666666666666666px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><img height="634" src="https://docs.google.com/drawings/d/snML0ciBt6MLcKyBMCp7G7g/image?w=698&h=634&rev=465&ac=1" style="-webkit-transform: rotate(0.00rad); border: none; transform: rotate(0.00rad);" width="698" /></span></span></span> </span><br />
<br />
<br />
<div dir="ltr" id="docs-internal-guid-ad448870-79c6-9287-6376-88be38dd0bc4" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "arial"; font-size: 14.666666666666666px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">At the end of a loop, before waiting for new input, the current base position is loaded and incremented with the values in FREG, this new memory base is then saved into ACU RAM[0] and used in the next loop.</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "arial"; font-size: 14.666666666666666px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">When new input data has arrived the addresses are read from ACU RAM[0] at the start of the next loop, this gives correct RAM addressing even if the DFB has been paused and restarted to change memory parameters between the loops. The code also tests if the updated base value is 0, indicating the end of a major loop.</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<br /></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "arial"; font-size: 14.666666666666666px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">The following assembler code shows the control flow, the value of the current RAMB base address is written to holding register A but no other useful work is done. The process input section only reads, and discards the input from staging register A. The acu magic is marked in <span style="background-color: #ffe599;">orange</span>.</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<br /></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<br /></div>
<div dir="ltr" id="docs-internal-guid-ad448870-79c7-2f4d-e13e-6f5e60a32f19" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">// ACU and block addressing</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">// Every loop uses a separate memory block in RAMA and RAMB</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">// The base address of this block is updated and saved at the end of the loop, before waiting for input data</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">// This base address is read at the start of the loop, in case there was a Pause/Resume event while waiting for input</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">// At any point in the loop the base address can be reloaded </span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">// with "acu(read, read) addr(0)"</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">area acu</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">org 0</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #ffe599;"><span style="color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">dw 0x0000</span></span><span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> </span><span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">// Memory location to save block base address</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #ffe599;"><span style="color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">dw 0x0403</span></span><span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> </span><span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">// Size of block, equals the increase of block base address for each loop</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #ffe599;"><span style="color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">dw 0x130E</span></span><span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"> </span><span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">// REGM values, maximal RAMA and RAMB addresses before wraparound</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<br /></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">area data_a</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">org 0</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<br /></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">area data_b</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">org 0</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">dw 0x0000</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">dw 0x0001</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">dw 0x0002</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">dw 0x0003</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">dw 0x0004</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">dw 0x0005</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">dw 0x0006</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">dw 0x0007</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">dw 0x0008</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">dw 0x0009</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">dw 0x000A</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">dw 0x000B</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">dw 0x000C</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">dw 0x000D</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">dw 0x000E</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">dw 0x000F</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<br /></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">setup:</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">acu(clear, clear) dmux(sa,sa) alu(set0) mac(hold)</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><span style="color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><span style="background-color: #ffe599;">acu(loadf, loadf)</span> addr(1) dmux(sa,sa) alu(set0) mac(hold)</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><span style="color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><span style="background-color: #ffe599;">acu(loadm, loadm)</span> addr(2) dmux(sa,sa) alu(set0) mac(clra) jmp(eob,wait_input)</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><br /></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><span style="color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">loop_start:</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><span style="color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><span style="background-color: #ffe599;">acu(read, read) addr(0)</span> dmux(sa,sa) alu(hold) mac(hold) jmp(eob,process_input)</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><br /></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><span style="color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">process_input:</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><span style="color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">// Only outputs current RAMB base for testing </span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><span style="color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">acu(hold, hold) dmux(sa, sa) alu(clearsem, 001) mac(hold)</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><span style="color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">acu(hold, hold) addr(1) dmux(sa ,ba) alu(setb) mac(hold)</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><span style="color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">// Set ALU to RAMB[ACUB] </span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><span style="color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">acu(hold, hold) dmux(sa, sra) alu(setb) mac(hold)</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><span style="color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">acu(hold, hold) dmux(sa, sa) alu(hold) mac(hold)</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><span style="color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">acu(hold, hold) addr(1) dmux(sa, sa) alu(hold) mac(hold) write(bus) jmp(eob,loop_end)</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><br /></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><span style="color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">loop_end:</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><span style="color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">// Move acu registers to point to next memory block, and save in ACU RAM[0]</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><span style="color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><span style="background-color: #ffe599;">acu(read, read) addr(0)</span> dmux(sa,sa) alu(hold) mac(hold) write(da)</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><span style="color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><span style="background-color: #ffe599;">acu(addf, addf)</span> dmux(sa,sa) alu(hold) mac(hold) jmp(acubeq, major_loop_end)</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><br /></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><span style="color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">minor_loop_end:</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><span style="color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><span style="background-color: #ffe599;">acu(write, write) addr(0)</span> dmux(sm,sm) alu(hold) mac(hold) jmp(eob,wait_input)</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><br /></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><span style="color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">major_loop_end:</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><span style="color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">// Set alu 1 to show that we have detected end of the major loop, </span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white;"><span style="color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">// used in component simulator for testing</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">acu(hold, hold) dmux(sa, sa) alu(set1) mac(hold) </span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><span style="background-color: #ffe599;">acu(write, write) addr(0)</span> dmux(sa,sa) alu(hold) mac(hold) jmp(eob,wait_input)</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<br /></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">wait_input:</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "courier new"; font-size: 12px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">acu(hold, hold) dmux(sa,sa) alu(setsem, 001) mac(hold) jmpl(in1,loop_start)</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<br /></div>
Magnus Lundinhttp://www.blogger.com/profile/17303004553752920522noreply@blogger.com0tag:blogger.com,1999:blog-8756201887955423383.post-23164285222536912562016-11-07T22:00:00.001+01:002016-11-07T22:06:04.576+01:00PSoC 5LP DFB assembler - ACU as a loop counter<div dir="ltr" id="docs-internal-guid-ad448870-408a-bf2b-a338-db2e878843be" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "arial"; font-size: 14.666666666666666px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">This time we will use the address calculation unit ACU as a loop counter. We create a PSoC creator project to test our ideas. The DFB assembler code is checked out in the component simulator until everything seems to work as planned and then we place the code onto a real chip under control of the debugger.</span></div>
<h3 dir="ltr" style="line-height: 1.38; margin-bottom: 4pt; margin-top: 16pt;">
<span style="background-color: transparent; color: #434343; font-family: "arial"; font-size: 18.666666666666664px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Test project</span></h3>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "arial"; font-size: 14.666666666666666px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">The test project is setup to transfer ADC readings to the DFB using DMA. A new output value from the DFB is signaled by raising an interrupt. The interrupt flag can be read from the main loop or handled by an interrupt handler. In the test code the interrupt status is checked in the main look and DFB output data is saved in a SRAM array.</span></div>
<h3 dir="ltr" style="line-height: 1.38; margin-bottom: 4pt; margin-top: 16pt;">
<span style="background-color: transparent; color: #434343; font-family: "arial"; font-size: 18.666666666666664px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Example - Mean value of N samples</span></h3>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "arial"; font-size: 14.666666666666666px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">This example calculates the mean value of successive blocks of 10 samples.</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "arial"; font-size: 14.666666666666666px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">Samples are read from staging register A, multiplied with 0.1 (1/N) and accumulated in the MAC.</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "arial"; font-size: 14.666666666666666px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">The address calculation register ACUB is used as loop counter. Modulo arithmetic for ACUB is enabled and the final loop counter value N (10) is loaded to the MREG register from ACU RAM[0] during setup . When the loop counter reaches 10 the accumulated value is written to output register A and the accumulator is cleared before waiting for the next input value.</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<br /></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: "arial"; font-size: 14.666666666666666px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;"><img height="286" src="https://docs.google.com/drawings/d/sBcKFqrIHPaBLZ_Y_ves51A/image?w=442&h=286&rev=120&ac=1" style="-webkit-transform: rotate(0.00rad); border: none; transform: rotate(0.00rad);" width="442" /></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<br /></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">// Calculates average of 10 inputs</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">area acu</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">org 0</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">dw 0x000A</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<br /></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">area data_a</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">org 0</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">dw 0x0CCCCC // RAMA[0] = 0.1</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<br /></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">setup:</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">acu(clear, clear) dmux(sa,sa) alu(set0) mac(hold)</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">acu(hold, loadm) addr(0) dmux(sa,sa) alu(hold) mac(clra)</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">acu(setmod, setmod) dmux(sa,sa) alu(hold) mac(hold) jmp(eob,wait_input)</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">//</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">process_input:</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">// Read staging register A to MAC port B and multiply-accumulate with RAMA[0]</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">acu(hold, incr) addr(1) dmux(sra,ba) alu(clearsem, 001) mac(macc)</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">// Move MAC o/p to ALU</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">// When ACUB is 10 then block is complete and output is written to holding register</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">acu(hold,hold) dmux(sm,sm) alu(seta) mac(hold) jmp(acubeq,write_output)</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">wait_input:</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">// Use semaphore0 to signal that DFB is waiting for input</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">acu(hold,hold) dmux(sa,sa) alu(setsem, 001) mac(hold) jmpl(in1,process_input)</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">//</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">write_output:</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">//Wait for ALU output</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">acu(hold, hold) dmux(sm,sm) alu(hold) mac(hold)</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">// Write the MAC content to holding register A and clear the MAC</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">acu(clear, clear) addr(1) dmux(sa,sa) alu(set0) mac(hold) write(bus)</span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #fff2cc; color: black; font-family: "courier new"; font-size: 13.333333333333332px; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline;">acu(clear, clear) dmux(sa,sa) alu(hold) mac(clra) jmp(eob,wait_input) </span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<br /></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<br /></div>
<span style="font-family: "arial" , "helvetica" , sans-serif;">There are a few notes: </span><br />
<ol>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">The acubeq condition is true BOTH when the ACUBREG is equal to MREG and when its 0, so we catch the end of the loop when ACUBREG equals MREG and reset it in code</span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">Placing the wait_input state after the process input eliminates one jump </span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">The jump when waiting for input is done with a loop jump jmpl(in1,process_input) that transfers control to the beginning of the block if the condition is not true, the block is this single instruction. </span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">The jump when checking the loop count jmp(acubeq,write_output) is a simple jmp that falls through to the next block ( wait_input) if the condition is not set.</span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">Each sample is processed in less than 4 cycles, including the write of the output. If the DFB runs at 48MHz this equals 12MSamp/s.</span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">Mux settings are only important in two instructions in this example: </span></li>
<ol><ol>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">When reading from RAMA to channel A and the input register A to channel B, passing these values to the MAC input. dmux(sr,ba) , mux3 settings are not used.</span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">When outputting accumulated value from MAC to ALU input A. dmux(sm,sm) , only mux3a setting is used. </span></li>
</ol>
</ol>
</ol>
<br />
<span style="font-family: "arial" , "helvetica" , sans-serif;">The example project can be found at:</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><a href="https://drive.google.com/open?id=0BwkzMBFZwrYtVHo5MjREVV8yUnc">ADC_DFBTest1.cyprj.Archive01.zip</a></span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<br />
<br />Magnus Lundinhttp://www.blogger.com/profile/17303004553752920522noreply@blogger.com3tag:blogger.com,1999:blog-8756201887955423383.post-39323616170399255982016-02-16T20:34:00.003+01:002016-11-04T12:51:53.786+01:00PSoC 5LP DFB assembler<h3 class="tr_bq">
The PSoC 5LP DFB and assembler</h3>
The digital filter block DFB on the PSoC 5LP is a very powerful element on the PSoC chip. It is available through the DFB component or the Filter component in PSoC creator. The filter block can be configured with cascaded FIR or BiQuad filters. This is a very powerful configuration but the filter parameters cannot be changed at run-time using the component API. The DFB component, on the other hand, is programmed using the supplied assembler and all parameters stored in DFB RAM can be dynamically changed at run-time. The assembler syntax is documented in the component and in the chip data sheets and the component contains a simulator to test the user supplied code. The problem using these tools is that the data-flow architecture and vliw instruction syntax have somewhat steep learning curve and there is not many commented examples available to guide the new user through the learning process.<br />
<br />
It is not really very complicated, but it is a pipelined architecture and its important to know at every cycle/instruction what data element is available in what section of the pipeline.<br />
<br />
The main elements are<br />
<ul>
<li>a dual input stage where only one can be connected to the data path at a time, and an input register can only be read once before written again from the main bus, I might be wrong here but this is my experience from my early learning process.</li>
<li>multiplexers controlling what data is routed to the input of the RAM, MAC and the ALU</li>
<li>a pair of RAM blocks, they can be read and written independently and connected to </li>
<li>a 24x24 multiply accumulator block MAC using q23 data format followed by </li>
<li>a 24 bit arithmetic logic unit ALU and a shifter</li>
<li>an output stage </li>
</ul>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcfxyc63kKAqmPfq1ax16_p0LpYMvByUXh8zPMTZHNRgZkb_iNut5ZpCcxwAik6MJf0rffyWp2e3ojmzck4nejjnPbjAhP-4OkC3Ofc-H5YRmpYVGauQRT9Z__jORAoh-NJkeNrs2hVsY/s1600/PSoC5LP_DFB.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="322" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcfxyc63kKAqmPfq1ax16_p0LpYMvByUXh8zPMTZHNRgZkb_iNut5ZpCcxwAik6MJf0rffyWp2e3ojmzck4nejjnPbjAhP-4OkC3Ofc-H5YRmpYVGauQRT9Z__jORAoh-NJkeNrs2hVsY/s640/PSoC5LP_DFB.png" width="640" /></a>There is a control store and state handling but that can mostly be left to the assembler in basic applications.<br />
<br />
<h3>
Number format </h3>
The numerical format is signed 24 bit, and multiply and accumulate operations returns the signed bits 23:46, that is the 24 top minus one bits. A natural interpretation of this data is as signed decimal numbers in q23 format, that is a sign bit followed by a decimal point and 23 decimal bits. For the simulator these values are written as hexadecimal values.<br />
<br />
<h3>
First lessons learned </h3>
Some of the things that is mentioned in the documentation but, at least to me, are not obvious:<br />
<ul>
<li>Input and Output channel A is numbered 1, and B is numbered 0.</li>
<li>Input is the same as Staging register, Output is Holding register.</li>
<li>The DFB component code uses 3x8 bit byte access to the Staging and Holding registers in the LoadInputValue and GetOutputValue functions, but it works well using 32 bit access.</li>
<li>In test examples for the simulator, use values where the product is not zero in the upper 24 bits, otherwise the MAC product stays zero and it seems nothing is happening. </li>
<li>The two input buffers cannot be read at the same time, and they can each be read only once before reloaded from the exterior bus. This means that if an input value must be used several times it has to be stored/held somewhere. This can be in one of the RAM blocks or in the ALU, of course its not possible to hold more than one value in the ALU and only for a few cycles, until some other data must flow through the ALU.</li>
<li> All output from the MAC must go through the ALU</li>
<li>Writing a value to a RAM location puts this same value on the output of the RAM during the same cycle.</li>
<li>Addressing a specific RAM location in one of the RAM buffers is a bit involved<br /><ul>
<li>acu(clear, ...) for location 0</li>
<li>acu(incr, ...) for next location</li>
<li>acu(decr, ...) for previous location</li>
<li>acu(read, ...) addr(xx) to read ACU RAM row xx as RAM A register address</li>
<li>acu(write, ...) addr(xx) to write current RAM A register address to ACU RAM row xx </li>
</ul>
</li>
<li> The saturation logic is for the ALU, the MAC will overflow in the accumulation even with saturation detection enabled.<br /><ul>
</ul>
</li>
</ul>
<br />
<h3>
Example: Squaring the input</h3>
The steps in this code are:<br />
<ul>
<li>Wait for input </li>
<li>Send input buffer A to ALU</li>
<li>Route ALU to both MAC ports and clear, this places the product in the MAC with no accumulation.</li>
<li>Route the result through ALU to the Output register.</li>
</ul>
<br />
The asm code for the DFB block<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="background-color: #fff2cc;"><span style="font-family: "courier new" , "courier" , monospace;">initial:<br />acu(clear, clear) dmux(sa,sa) alu(set0) mac(hold)<br />acu(setmod, setmod) dmux(sa,sa) alu(hold) mac(clra) jmp(eob, waitForNew)<br /><br />// Wait for data to be written to Staging Register Input 1<br />waitForNew:<br />acu(clear,clear) dmux(sa,sa) alu(hold) mac(hold) jmpl(in1,dataRead)<br /><br />dataRead:<br />// <span style="font-family: "courier new" , "courier" , monospace;">Read</span> staging register A into ALU<br />acu(hold, hold) addr(1) dmux(sa,ba) alu(setb) mac(hold)<br /><br />// Multiply ALU out with ALU out and place in c<span style="font-family: "courier new" , "courier" , monospace;">leared </span>MAC ACC<br />acu(hold, hold) dmux(sa,sa) alu(setb) mac(clra) <br /><br />//Move MAC o/p to ALU<br />acu(hold, hold) dmux(sm,sm) alu(seta) mac(hold) <br /><br />//Wait for ALU output<br />acu(hold, hold) dmux(sm,sm) alu(hold) mac(hold)<br /><br />// Write the MAC content to holding register A<br />acu(hold, hold) addr(1) dmux(sa,sa) alu(hold) mac(hold) write(bus) jmp(eob,waitForNew) </span></span></span></blockquote>
<br />
Note: It is possible to send the staging register directly to both ports of the MAC, saving one instruction, but the assembler generates a warning so I guess more testing is needed.<br />
Use the assembler and simulator in the DFB block to test your code carefully before trying in on the live chip. The code reads from staging register A so some data should be placed in the simulator bus data area 'Bus1' (far out to the right). <br />
<br />
<br />
To use this, the following code is put in the program:<br />
<blockquote>
<span style="background-color: #fff2cc;"><span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;">float finput = 0.3, foutput; <br />uint32 input, output;<br /><br />DFB_1_Start();<br />DFB_1_SetInterruptMode(DFB_1_HOLDA);</span></span></span><span style="background-color: #fff2cc;"><span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;">input = finput*(1<<23); /* float to q23 */ </span></span></span><br />
<span style="background-color: #fff2cc;"><span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"></span></span></span></blockquote>
Loop code: <br />
<blockquote>
<span style="background-color: #fff2cc;"><span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;">input = finput*(1<<23); </span></span></span><span style="background-color: #fff2cc;"><span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="background-color: #fff2cc;"><span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;">/* float to q23 */</span></span></span><span style="background-color: #fff2cc;"><span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"><br /></span></span></span>DFB_1_LoadInputValue(1, input); <br /><br />while (!(DFB_1_GetInterruptSource() & DFB_HOLDA) ) ;<br /><br />output = DFB_1_GetOutputValue(1);<br />foutput = ((float)output)/(1<<23); /* q23 to float */</span></span></span><span style="background-color: #fff2cc;"><span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"><br /></span></span></span></blockquote>
To use 32 bit access we can use the following code to write and read the staging and holding registers:<br />
<blockquote class="tr_bq">
<span style="background-color: #fff2cc;"><span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;">*( (reg32 *) DFB_1_DFB__STAGEA) = input;<br />output = *( (reg32 *) DFB_1_DFB__HOLDA);</span></span></span></blockquote>
<br />
<h3>
Example: First order LP filter</h3>
A basic first order filter calculates the recurrence relation: <br />
\[ y_{n} = a_1 y_{n-1} + b_0 x_{n} \]<br />
The filter coefficients are stored in the first two locations of RAM-A and the previous output \( y_{n-1} \) is remembered in the ALU hold register between loops.<br />
<br />
When new input is available \( y_{n-1} \) is routed from ALU output (shift) to MAC input B and multiplied with \( a_1 \) (RAM-A[0] ) without accumulation, mac(clra), next the new input is routed to MAC input B and multiplied with \( b_0 \) (RAM-A[1]) and added to the previous product. The result is then transferred to the ALU and stored in the holding register.<br />
<br />
For the example we use \( a_1 = 0.9 \) and \( b_0 = 0.1 \) for a DC unity gain filter.<br />
<br />
0x733333 // a1 = 0.9 <br />
0x0CCCCC // b0 = 0.1 <br />
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"><br /></span></span>
The asm code for the DFB block:<br />
<blockquote>
<span style="background-color: #fff2cc;"><span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;">area data_a <br />org 0<br />dw 0x733333 // a1 = 0.9<br />dw 0x0CCCCC // b0 = 0.1<br /><br />initial:// Clear ALU and MAC<br />acu(clear, clear) dmux(sa,sa) alu(set0) mac(hold)<br />acu(setmod, setmod) dmux(sa,sa) alu(hold) mac(clra) jmp(eob, waitForNew)<br /><br />// Wait for data to be written to Staging Register Input 1<br />waitForNew:<br />acu(clear,clear) dmux(sa,sa) alu(hold) mac(hold) jmpl(in1,dataRead)<br /><br />dataRead:<br />// Multiply ALU out with RAMA[0] and place in cleared MAC ACC<br />acu(hold, hold) dmux(sra,sa) alu(setb) mac(clra) <br /><br />// Read staging register A to MAC port B and multiply with RAMA[1]<br />acu(incr, hold) addr(1) dmux(sra,ba) alu(hold) mac(macc)<br /><br />//Move MAC o/p to ALU<br />acu(hold, hold) dmux(sm,sm) alu(seta) mac(hold) <br /><br />//Wait for ALU output<br />acu(hold, hold) dmux(sm,sm) alu(hold) mac(hold)<br /><br />// Write the MAC content to holding register A<br />acu(hold, hold) addr(1) dmux(sa,sa) alu(hold) mac(hold) write(bus) jmp(eob,waitForNew) </span></span></span></blockquote>
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"><br /> </span></span><br />
To monitor performance a semaphore can be output during the
calculation and cleared in the wait loop. This is then connected to an
output pin and monitored with a logic analyzer or a oscilloscope.<br />
<h3>
</h3>
<br />Magnus Lundinhttp://www.blogger.com/profile/17303004553752920522noreply@blogger.com1tag:blogger.com,1999:blog-8756201887955423383.post-56882934673609244052016-02-06T13:41:00.002+01:002016-02-06T16:52:53.397+01:00The Cypress PSoC 5LP I recently started to work on a project that needs several analog input and output channels connected to some sensors and a PID control loop and it will probably work better with 5V than the currently popular 3.3 for Cortex M systems. So I decided to dig out a CY8CKIT-059 PSoC 5LP Prototyping Kit that has been gathering dust waiting for the right project to come along. <br />
<br />
This is actually an amazing chip, even if the processor is a standard Cortex-M3 that runs up to 80MHz (there are signs that Cypress is working on a PSoC7 with a M7 core and probably a price to match). The
64K RAM and 256K FLASH sizes are modest but what makes this chip special are
the configurable analog and digital blocks on the chip. There are three ADC's, one with high impedance buffers, two
DAC's and four opamps, all connected to an analog switching network. The digital side has a number of universal digital blocks to implement
your own digital logic or preconfigured communication interfaces and a digital filter block, DFB. This is a 24 bit datastream co-processor with a multiply-accumulate unit and a ALU. The analog and digital I/O can be run from 1.71 to 5.5 volts.<br />
<br />
The vendor supplied tool chain <i><b>PSoC Creator</b></i>
only runs under Windows but it is not a bad experience even though I am
always skeptic of systems that generates code that is hard to know
where one can change and how. I find it often less trouble to implement
stuff directly from the data sheet than to learn the ins and outs of the
library calls. In order to use the extra analog and digital blocks in
the chip I think it is really necessary to use the vendor supplied
toolchain, and without these extras the chip is not very special.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div style="margin-left: 1em; margin-right: 1em;">
<img alt="Bildresultat för cy8ckit-059" class="rg_i" data-sz="f" height="151" name="JIoQAMbh608YJM:" src="data:image/jpeg;base64,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" style="height: 93px; margin-left: -19px; margin-right: -20px; margin-top: 0px; width: 393px;" width="640" /></div>
<br />
<div class="r">
<br />
Add
the fact that the CY8CKIT-059 PSoC 5LP Prototyping Kit can be bought
for $10 this is definitely a system worth trying out, even if USB
connectors made from four strips on top of the circuit board is not the
most professional and stable connection method. That can be fixed with
an old USB cable and a soldering iron, and the price will still be
attractive. The on board programmer and debugger is also a programmable PSoC 5LP and could be used for a project requiring very few I/O pins.<br />
<br />
Getting started is quite easy, install some USB drivers, the PSoC Creator and PSoC Programmer software with example projects. Open an example project and hit the debug button. I started with the "CE95277 ADC and UART" project and soon had the board sending ADC samples over USB serial to my PC. Getting used to all the tools and panels takes a few days but the help functions are easy to access and components have datasheets and code examples the opens with a right click. </div>
Magnus Lundinhttp://www.blogger.com/profile/17303004553752920522noreply@blogger.com0tag:blogger.com,1999:blog-8756201887955423383.post-4471640568515423512015-08-28T22:24:00.002+02:002015-08-29T00:15:29.984+02:00Getting started with the STM32F7 Discovery boardThe other week I got a brand new STM32F7 Discovery board, the fabled Cortex M7 had arrived and performance bliss was at hand ...<br />
<br />
... except there were a few minor stumbling stones on the road to paradise ...<br />
<br />
this is not an ad for ST, I did pay the full Mouser price. <br />
<br />
<ul>
<li>ST programming tools for the ST-Link interface are not available for Mac OSX, and the board does not expose the JTAG/SWD of the Cortex M7, it is only available through the onboard ST-Link adapter chip. The GGC ARM Embedded toolchain <a href="https://launchpad.net/gcc-arm-embedded/+download">https://launchpad.net/gcc-arm-embedded/+download</a> was happy to generate code after importing some system defines and startup code from STM32Cube_FW_F7_V1.1.0 library and a bit of tweaking to Makefiles and linker scripts. It was possible to flash the binaries to the board using the USB file system
interface, but then there is no debug connection, and it refused load code
that was linked to use fast ITCM flash access. </li>
</ul>
<ul>
<li> With some some work it was possible to add the chip and flash configuration details to the free stlink utility <a href="https://github.com/texane/stlink">https://github.com/texane/stlink</a> and also tweak the stlink RAM based flash writing code to handle the 64 bit flash access so flash is correctly written, all running on Mac OSX.</li>
</ul>
<ul>
<li>The example code in the STM32Cube_FW_F7_V1.1.0 library does not by default use the external 25MHz crystal clock, only the onchip internal 16MHz oscillator. The PLL is also not configured by default, meaning the chip runs at 16MHz, and not the 196 or 216 Mhz that should be possible.</li>
</ul>
<ul>
<li>For optimal performance the linker settings should be configured to make the code use the ART accelerated ITCM flash access at 0x0020000 instead of the normal, slow, flash access at 0x0800000. When the linker was configured this way the ST onboard USB flash loader refused to load code into flash, but stlink utility worked.</li>
</ul>
<ul>
<li>The external SDRAM for the Discovery board has a different configuration than the one in the "system_stm32f7xx.c" supplied from ST. It seems ST has used the settings for another STM32F7 board and not been careful to make the changes for the F7 Discovery board.</li>
</ul>
Virtual USB com port was quite easy, it turns out that the USB subsystem is almsot identical to the the one on STMF4 chips.<br />
<br />
After these tweaks I was able to run some simple tests where the chip executed between 200 and 300M instructions/sec. I think this can be a great chip for audio synthesis.<br />
<br />
Next will be the big LCD display, but that must wait for when I have lots of free time again. <br />
<br />Magnus Lundinhttp://www.blogger.com/profile/17303004553752920522noreply@blogger.com3tag:blogger.com,1999:blog-8756201887955423383.post-85882434161941138652015-08-10T12:47:00.001+02:002015-08-13T22:46:18.002+02:00More USB and MIDITime goes fast, new and more powerful microprocessors are introduced, and the favourites of a year ago are fading and starts to collect dust in a draver filled with useful but not quite exciting boards. These days the Cortex M3 of the Maple board feels a bit old, the Teensy 3.1 is a great board and the Arduino type libraries and support is superb, but it has a bit limited memory and no hardware floating point.The boards I use mostly for audio generation at the moment are the Netduino plus 2, without the Netduino bootloader and .Net libraries, the STM32F4 Discovery and the XMC4500 Relax Kit Lite. All of these have Cortex-M4F processors, more than 128KB RAM and 1024KB of flash, they are all cheap and good value for money.<br />
<br />
I need stable USB MIDI and after wrangling with the device libraries and development platforms, endless hierachies of folders and files that are usually targeted at Windows and often lacking USB MIDI, I decided to write yet another lightweight USB implementation. I know this might sound stupid and a waste of effort but having some time free due to vacation times and a bit of rainy summer I went ahead.<br />
<br />
The code is written from scratch and uses only some MCU specific header files borrowed unchanged from the manufaturer supplied code libraries. When time allows and I have done some more testing a few minimal example programs will be added.<br />
<br />
I have uploaded the code to my Cortal Dendrites repository on Github:<br />
<br />
<a href="https://github.com/mlu/cortal_dendrites/tree/master/cortex_m/usblib">https://github.com/mlu/cortal_dendrites/tree/master/cortex_m/usblib</a><br />
<br />
Happy Coding :)<br />
<br />Magnus Lundinhttp://www.blogger.com/profile/17303004553752920522noreply@blogger.com0tag:blogger.com,1999:blog-8756201887955423383.post-42179782381707722512015-05-22T21:54:00.000+02:002015-05-24T21:02:37.500+02:00Computing fractional multipliers and divisors using continued fractions.<span style="font-size: small;"><span style="font-family: Times,"Times New Roman",serif;">This blog post </span></span>will discuss how to find the best rational approximation with bounded numerator or denominator to a a preferred frequency ratio. This will be a bit mathematical but actually nothing more than standard addition, subtraction, multiplication and division will be used. Some example code is given at the end.<br />
<br />
<h3>
Fractional baudrate generation </h3>
Some microprocessors uses fractional multipliers and divisors to generate accurate baud rates from system clocks that are not an integer multiple of the bitslice clock frequency. The bitslice frequency is the baudrate times an oversampling count.<br />
<br />
<div style="text-align: left;">
\[ f_{bitslice} = oversample \cdot baudrate = ratio \cdot f_{sysclock} \tag{1} \]</div>
<br />
An example is the USIC in the Infineon XMC1100 and XMC4500 family microprocessors. Here the clock for the bitslices is derived from the system clock, slightly simplified, as <br />
<br />
<div style="text-align: left;">
\[ f_{bitslice} = (DCQT+1) baudrate = \frac 1 {(PDIV+1)} \cdot \frac {STEP} {1024} \cdot f_{sysclock} \]</div>
<br />
DCQT gives the oversampling count, typically set to 15. PDIV and STEP are register values controlling the frequency division. On the XMC1100 PDIV and STEP are 10 bit wide so they have values from 0 to 1023. Rearranging the above we see that we must find a good approximation<br />
<br />
<div style="text-align: center;">
\[ \frac {STEP} {(PDIV+1)} \approx \frac {(DCQT+1) baudrate \cdot 1024} { f_{sysclock} } \tag{2} \]</div>
<br />
with values of PDIV and STEP between 0 and 1023. <br />
<h4>
Example: 38400 baud from a 32MHz clock and 16 times oversampling</h4>
We enter the values in (2) to find<br />
<br />
<div style="text-align: center;">
\( \frac {STEP} {(PDIV+1)} = \frac {16 \cdot 38400 \cdot 1024} { 32000000 } = \frac {629145600} { 32000000 } = 19.6608 \) </div>
<div style="text-align: center;">
<br /></div>
Working by hand we would now factor out common factors from numerator and denominator, but for computer implementations that is unnecessary extra work. As we shall see the algorithm works as well without that step. <br />
Now we calculate the signed integer division with remainder using the rounded value 20 as quotient. <br />
<br />
<div style="text-align: center;">
\( \frac {16 \cdot 38400 \cdot 1024} { 32000000 } = 20 - \frac {10854400} { 32000000 } = 20 - \frac {1} { \frac { 32000000 } {10854400} } \tag{3} \) </div>
<br />
Rewrite the denominator in the last fraction by carrying out the division with remainder<br />
<br />
<div style="text-align: center;">
\( \frac { 32000000 } {10854400} = 3 - \frac {563200}{ 10854400 } \approx 2.948 \approx 3 \) </div>
<br />
We enter this value 3 in the previous formula (3) to get the approximation<br />
<br />
<div style="text-align: center;">
<div style="text-align: left;">
\[ \frac {16 \cdot 38400 \cdot 1024} { 32000000 } \approx 20 - \frac {1} { 3 } = \frac {59} {3} = 19.6667 \] </div>
<div style="text-align: left;">
<br /></div>
</div>
This is good, after one iteration the error is less than 0.008 or about 300ppm.<br />
We can improve this by using a better using a more precise value <br />
<br />
<div style="text-align: center;">
\(\frac { 32000000 } {10854400} = 3 - \frac {563200}{ 10854400} = 3 - \frac 1 { \frac { 10854400 }{563200}} = 3 - \frac 1 {19 + \frac {153600 }{563200}} \approx 3 - \frac 1 { 19 } = \frac {56}{19}\)</div>
Inserted into (3) this gives<br />
<br />
<div style="text-align: center;">
\( \frac {16 \cdot 38400 \cdot 1024} { 32000000 } \approx 20 - \frac {1} { \frac {56}{19} } = 20 - \frac {19} {56} = \frac {1101} {56} = 19.6607 \) </div>
<br />
This approximation is better, error is about 3ppm, but the STEP value 1101 is to large for the 10 bit range, so we keep the previous approximation of 59/3. <br />
<br />
<h3>
Best rational approximation with continued fractions</h3>
In order to find a general method to calculate good rational approximations as in the previous example we use the theory of <i>partial quotients, or convergents, of continued fraction expansions</i> and <i>best rational approximation theory</i>. [TO DO add links ] This is a well developed general theory for finding the best rational apprimations to a number with a given size of the denominator. There are recursive algoritms for calculating succusively better approximations.<br />
<br />
So we are given a rational number p/q and we want to find succesive approximations \( a_n/b_n \) to p/q with smaller values for \( a_n \) and \(b_n \) than p and q. For the baud rate generations we want the best approximation where \( a_n \) and \(b_n \) fits in the respective fractional multiplier and divisor registers. <br />
<br />
<h4>
The formula</h4>
\[ \frac p q = c_0 + \frac {1}{c_1 + \frac {1}{c_2 + \ddots \frac {1}{c_n + \frac {1} {r_{n+1}}}}} \approx c_0 + \frac {1}{c_1 + \frac {1}{c_2 + \ddots \frac
{1}{c_n }}} = \frac {a_{n+1}}{b_{n+1}} \]<br />
<br />
For the first few values of n we get:<br />
<br />
\[ a_{-1} =0, b_{-1}=1 \] <br />
\[ a_0 =1, b_0=0 \]<br />
\[ \frac {a_{1}}{b_{1}} = c_0 = \frac {0 + 1 \cdot c_0}{1 + 0 \cdot c_0} = \frac {a_{-1} + a_0 \cdot c_0}{b_{-1} + b_0 \cdot c_0} \]<br />
\[ a_1 =c_0, b_1=1 \] <br />
\[ \frac {a_{2}}{b_{2}} = c_0 + \frac {1}{c_1} = \frac {c_0 \cdot c_1 + 1}{c_1} = \frac {a_{0} + a_1 \cdot c_1}{b_{0} + b_1 \cdot c_1} \]<br />
\[ \frac {a_{3}}{b_{3}} = \frac {a_{0} + a_1 ( c_1+ \frac 1 {c_2})}{b_{0} + b_1 ( c_1+ \frac 1 {c_2})} = \frac {(a_{0} + a_1 c_1 ) c_2+ a_1}{(b_{0} + b_1 c_1 ) {c_2}+ b_1} = \frac {a_1 + a_{2}{c_2}}{b_1+b_{2}{c_2}} \]<br />
We now can see the recursion formula develop<br />
\[ \frac {a_{4}}{b_{4}} = \frac {a_{1} + a_2 ( c_2+ \frac 1
{c_3})}{b_{1} + b_2 ( c_2+ \frac 1 {c_3})} = \frac {(a_{1} + a_2 c_2 )
c_3+ a_2}{(b_{1} + b_2 c_2 ) {c_3}+ b_2} = \frac {a_2 +
a_{3}{c_3}}{b_2+b_{3}{c_3}} \] <br />
<br />
\[ \frac {a_{n+1}}{b_{n+1}} = \frac {a_{n-2} + a_{n-1} ( c_{n-1}+ \frac 1
{c_n})}{b_{n-2} + b_{n-1} ( c_{n-1}+ \frac 1 {c_{n}})} = \frac {(a_{n-2} + a_{n-1} c_{n-1} )
c_n+ a_{n-1}}{(b_{n-2} + b_{n-1} c_{n-1} ) {c_n}+ b_{n-1}} = \frac {a_{n-1} +
a_{n}{c_n}}{b_{n-1}+b_{n}{c_n}} \] <br />
<br />
<h4>
</h4>
<br />
<h4>
The algorithm</h4>
We start with a rational number r = p/q. We will generate a sequence of five values \(a_n, b_n, c_n, p_n\) and \(q_n\). The quotients \(a_n/b_n\) will be our succesive approximations to r. The values \(r_n\) are defined as \(p_n/q_n\) but they need not be explicitly calculated, the formula for \(r_n\) is used as the template for how \(p_n\) and \(q_n\) are updated.<br />
<br />
<u><b>Startup: </b></u><br />
\( r_0 = r \)<br />
\( p_0 = p, q_0 = q \)<br />
\( a_{-1} =0, b_{-1}=1 \) <br />
\( a_0 =1, b_0=0 \)<br />
<br />
<u><b>Loop </b></u>until q_n+1 is 0 or an or bn are to large<br />
\( c_{n} = round(r_{n}) = round ( p_{n}/q_{n} ) \)<br />
\( r_{n+1} = 1/(r_n-c_n) \) This is done calculated terms of \(p_n\) and \(q_n\) <br />
\( p_{n+1} = q_n \)<br />
\( q_{n+1}=p_{n}-c_n \cdot q_n \)<br />
\( a_{n+1}=a_{n-1}+a_{n} \cdot c_{n} \)<br />
\( b_{n+1}=b_{n-1}+b_{n} \cdot c_{n} \)<br />
<br />
The rounding operations can be done downwards, keeping all values positive, or towards the nearest integer improving precision but also introducing negative numers and extra complexity. Note that the \(c_n\) value is calculated before updating \(p_n\) and \(q_n\) and is not remembered and used in the next iteration but recalculated.<br />
<h4>
A skeleton C implementation</h4>
Following code lacks error handling and only checks limit for numerator, but it illustrates the algorithm. It does lack a few comments, but follows the algortithm structure closely.<br />
<br />
<br />
<span style="background-color: #eeeeee; font-size: small;"><span style="font-family: "Courier New", Courier, monospace;">void </span><span id="docs-internal-guid-e3067d64-7d1b-ce03-739a-f11c4cdbf25d" style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">cfractr(int32_t p, int32_t q,int32_t alim, uint32_t * ares, uint32_t * bres) {</span></span><br />
<div dir="ltr" id="docs-internal-guid-e3067d64-7d1c-833f-436a-db1226649d46" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">int ap = 0;</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">int a1 = 1;</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">int bp = 1;</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">int b1 = 0;</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">int cn = a1, anext, bnext, pnext;</span></span></div>
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> while (1) {</span></span><br />
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> /* Signed rounded rational division */ </span></span></div>
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> if ((q>0)&&(p>0)</span></span><span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">|</span></span><span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">|(q<0)&&(p<0)) <!--0--><!--0--></span></span><br />
<div dir="ltr" id="docs-internal-guid-e3067d64-7d1f-6c5b-6e7b-27407a5d0805" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">cn = (p+q/2)/q;</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">else</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">cn = (p-q/2)/q;</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> /* Next value for partial quotients and remainder */ </span></span></div>
<div dir="ltr" id="docs-internal-guid-e3067d64-7d1f-d392-9823-500f55a93f95" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">anext = ap + cn*a1;</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">bnext = bp + cn*b1;</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">pnext = p-cn*q;</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> /* Exact value, remainder is 0, break */ </span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">if (pnext == 0) {</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">a1 = anext;</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">b1 = bnext;</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">break;</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">}</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> /* Numerator too large, break */ </span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"><span style="background-color: #eeeeee;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"><span style="background-color: #eeeeee;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"><span style="background-color: #eeeeee;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span></span></span></span></span></span></span></span><span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"><span style="background-color: #eeeeee;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"><span style="background-color: #eeeeee;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"><span style="background-color: #eeeeee;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"><span style="background-color: #eeeeee;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"><span style="background-color: #eeeeee;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> if</span></span></span></span></span></span></span></span> ((anext<-alim)</span></span></span></span><span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"><span style="background-color: #eeeeee;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">|</span></span></span></span><span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"><span style="background-color: #eeeeee;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">|(anext>alim)) {<!---alim--><!---alim--></span></span></span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"><span style="background-color: #eeeeee;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"><span style="background-color: #eeeeee;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> break;</span></span></span></span></span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"><span style="background-color: #eeeeee;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"><span style="background-color: #eeeeee;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"><span style="background-color: #eeeeee;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">}</span></span></span></span></span></span></span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> /* Shift one step before next iteration */ </span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"><span style="background-color: #eeeeee;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span></span> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">ap = a1;</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">bp = b1;</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">a1 = anext;</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">b1 = bnext;</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">p = q;</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">q = pnext;</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">}</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">if (a1<0){a1=-a1;b1=-b1;}<!--0--><!--0--></span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">*ares = a1;</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">*bres = b1;</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: #eeeeee; font-size: small;"><span style="color: black; font-family: "Courier New"; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">}</span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<br /></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<br /></div>
<br />
<span style="background-color: transparent; color: black; font-family: 'Courier New'; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span>Magnus Lundinhttp://www.blogger.com/profile/17303004553752920522noreply@blogger.com0tag:blogger.com,1999:blog-8756201887955423383.post-60019844237234354952013-07-08T20:48:00.001+02:002015-07-20T10:41:32.197+02:00Breath control revisitedI have been using my breath control and <a href="http://openpipe.cc/products/openpipe-breakout/" target="_blank">openpipe breakout</a> for two months now and it makes for a really enjoyable instrument. There are some things to develop, first the hardware pipe and pressure sensor compartment should be redesigned, the current is a quick hack. So here comes some notes on designing a new mouthpiece. In some weeks time I hope to be able to add some sound examples and also describe some of the programming.<br />
<br />
<h4>
Designing a mouthpiece</h4>
The mouthpiece should allow some air to pass through while playing to make breathing more natural, but also stop the airflow enough for a clearly measurable pressure to build up. To avoid moisture on the sensor board i place the sensor in a compartment after the exhaust hole so that the air stream does not pass directly over the sensor board. Closing the exhaust hole and just using the pressure makes the end of notes sound bad since the pressure doesn't drop cleanly when you stop blowing. The best option is probably to make the size of the exhaust hole adjustable and to let the player decide.<br />
<br />
The air pressure in a recorder mouthpiece varies between 200 and 1000Pa depending on the note played with high notes having more pressure. The difference in pressure between pp and ff (loud and quiet) is about 200Pa, these numbers can be found in <a href="http://www.mtg.upf.edu/node/2171" target="_blank">Modeling of Gesture-Sound Relationships in Recorder Playing: A Study of Blowing Pressure</a>, a master thesis by Leny Vinceslas.<br />
An exhaust hole with 3-4mm diameter gives this kind of pressure on the sensor and feels quite nice to play. I will test more with different sized exhaust holes, how hard to blow and how the pressure varies on the sensor. <br />
<br />
Here is my design sketch for the next version of breath sensor mouthpiece. I have found very cheap nylon tubing used for electrical installation work that fits snugly around the Open Pipe. I am fairly confident this can built at home with simple tools, the only remaining part is the silicone rubber film. It can be bought 0.3 mm thick 50x50 cm from Germany for 90 euros, a bit much money but its probably enough for more than 600 such mouthpieces ( I might find some use for a lot of silicone rubber film :) ).<br />
<a href="http://1.bp.blogspot.com/23THCoEahqGAoM4s9gzuLIxjxdjyf8UEqp6rqIUBL7bIATnQtV5o8BdtNATY5RIwLdjq2g=s400" imageanchor="1" ><img border="0" src="http://1.bp.blogspot.com/23THCoEahqGAoM4s9gzuLIxjxdjyf8UEqp6rqIUBL7bIATnQtV5o8BdtNATY5RIwLdjq2g=s400" /></a>
<br />
<h4>
The sensors</h4>
BMP050<br />
Reading both temperature and pressure and calculating the calibrated values takes around 11ms, this time is mostly spent waiting for the chip to complete a conversion. With careful programming other calculations and sampling of the touch sensors can be done during this wait time. A breakout board can be found for around $15<br />
<br />
MPL3115A2<br />
This sensor seems to have as good or better performance than the BMP085 with faster sampling rate. The calibration and temperature compensation is done in the sensor ASIC and the convoluted calculations needed for the BMP085 are not needed. I have ordered a breakout board for testing.<br />
<br />
A further enhancement would be to use a very open mouthpiece and sense both pressure in the middle of the airstream and total flow, this would more correspond to playing a flute. Not sure what sensors to use for this and how to mount them.<br />
<h4>
Relation between pressure, tone height and volume</h4>
Using the data in L Vinceslas work I set up a table of the normal
pressure used to to play the different notes at medium volume. This value is used as baseline for the note, corresponding to midi volume 64. This means that like in a real flute or recorder, in order to keep a constant volume, the pressure must increase as we play higher notes.<br />
<br />
<span style="background-color: #cfe2f3;"><span style="font-family: "Courier New",Courier,monospace;"> int volume;<br /> int midpressure = note_pressure[note-60];</span></span><br />
<span style="background-color: #cfe2f3;"><span style="font-family: "Courier New",Courier,monospace;"><br /></span></span>
<span style="background-color: #cfe2f3;"><span style="font-family: "Courier New",Courier,monospace;"> volume = 64 + ((pressure - midpressure)*psensitivity)/128;<br /> if (volume < 0) volume = 0;<br /> if (volume > 127) volume = 127;</span></span><br />
This code fragment shows the midi volume calculation, the psensitiviy gives the sensitivity to pressure variation around the standard note_pressure from the table. A value of around 15-20 seems to work quite well. In my test sketch I have assigned this value to a CC controller so it can be changed dynamically while playing.<br />
<br />
This has been tested and its easy to dynamically control the expression of the sound.<br />
<h4>
Using the pressure to control the octave of the note played</h4>
If the pressure is more than 2/3 of the pressure difference to the note one octave higher than the one fingered then scale is shifted one octave up and later if it is below 2/3 of the difference down to the original note the scale is shifted back. This code is still in planning.<br />
<br />
<h4>
Detecting the start of a note</h4>
The program recognises the start of a note when the pressure has been more than 50 Pa above ambient for three sample periods (30ms). This is the number of samples needed for the pressure to reach its peak value so that the midi note volume can be calculated. If aftertouch, channel pressure or the expression continuous controller is active then this may be decreased at the risk of losing the initial attack. Magnus Lundinhttp://www.blogger.com/profile/17303004553752920522noreply@blogger.com1tag:blogger.com,1999:blog-8756201887955423383.post-26495547843040030032013-07-04T02:10:00.004+02:002013-07-04T02:34:38.930+02:00Adventures with the Terasic DE0 NanoI have for a long time been fascinated by the idea of programmable logic as a complement to standard MCU's. Ideas like running 32 pwm channels and as many quadrature detectors on one chip for servo control is definitely beyond todays MCU's, powerful as they are.<br />
<br />
I have previously played a bit with the Terasic Trac C1 and the Dallas Logic Quickgate EP2C8 Cyclone II boards, trying to learn VHDL and how to build things like an audio synthesizer with them. So when I saw the Terasic DE0 Nano I simply couldn't resist the urge to buy one. At €74 from Mouser it is not dirt cheap, but for an FPGA board of this kind it is very good value. <br />
<br />
Designing FPGA logic is quite different from ordinary C/C++ microprocessor programming. The best book I have found to help me is "Rtl Hardware Design using VHDL" by Pong P. Chau.<br />
<br />
So after reviving some old VHDL projects I started to install the Quartus software on my Fedora 18 system. Quartus 13 refused to run without frequent crashes even after I changed and added several system libraries to conform to the ones coded into the Quartus 13 executables. After this I tried installing Quartus Free Web Edition 11, and it seems to run perfectly, this might be because of the changes done to make Q 13 run, or not, but at the moment it works. Older Quartus versions can be found at <a href="ftp://ftp.altera.com/outgoing/release/" target="_blank">ftp://ftp.altera.com/outgoing/release/</a>.<br />
<br />
Most of the get started manuals for complex systems like this tells you to install some precoded development package and just click menu boxes in a specified sequence without giving the logic for that. For me this is not really learning a new tool. So I try to build small things from scratch to see what happens before using the heavyweight preprogrammed IP in the component libraries.<br />
<br />
<img class="uw xO" height="360" src="https://lh5.googleusercontent.com/-4veeRUefqJs/UdS7eFy5WqI/AAAAAAAAAIo/jrrqDP3AEmk/w1412-h796-no/2013-07-03+-+1" width="640" /><br />
<br />
Right now I have a Serial Port echo running on the DE0 Nano that displays incoming serial bytes on the 8 LED's and then echoes them back, the small chip is a Teensy 3 that acts as a Serial-USB bridge. Its not very advanced yet but writing the logic from scratch is fun and rewarding. Next step is SPI and some PWM.<br />
<br />
<br />Magnus Lundinhttp://www.blogger.com/profile/17303004553752920522noreply@blogger.com2tag:blogger.com,1999:blog-8756201887955423383.post-91634579746171736812013-05-09T18:00:00.000+02:002013-05-10T02:54:09.600+02:00OpenPipe and breath control<br />
I have been playing around with the OpenPipe Breakout, the electronic pipe/flute control, for a few weeks now, trying to revive some old and mostly forgottens skills on how to play a flute or Irish tinwhistle.<br />
<br />
The pipe is connected through a I2C interface to a Maple clone, the Olimexino STM32 and then with MIDI to Garageband on my iMac. Its a fun instrument but I find it a bit hard to balance, holding it and playing some fast fingering at the same time, using a thumb for note on/off is also a bit unusal.<br />
<br />
So I decided to try and make a breath control so that the pipe can be played almost like a real flute.<br />
<div style="text-align: left;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://drive.google.com/uc?export=view&id=0BwkzMBFZwrYtMkx4b0M3cjU3NmM" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="360" src="http://drive.google.com/uc?export=view&id=0BwkzMBFZwrYtMkx4b0M3cjU3NmM" width="640" /></a></div>
<br />
<br />
The breath control sensor is a BMP085 breakout board, this atmospheric pressure sensor <br />
connects to the Maple board over I2C. The mouthpiece is made from two pieces of nylon tubing. A cork from a bottle of good Italian wine holds things in place. The sensor is placed inside the tube and the end is sealed with the cork, a small ventilation hole lets some air pass thrugh the mouthpiece.<br />
<br />
<br />
<a href="http://drive.google.com/uc?export=view&id=0BwkzMBFZwrYtT1NRMzU4RkFaZkU" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="396" src="http://drive.google.com/uc?export=view&id=0BwkzMBFZwrYtT1NRMzU4RkFaZkU" width="640" /></a><br />
<br />
<br />
<div style="text-align: left;">
</div>
<br />
The sketch reads the BMP085 and the touch sensor in the OpenPipe Breakout and starts a note if the pressure is more than 50Pa above ambient. Some early tests shows that the basic setup works but theres a lot more to do before the sound can be controlled by breath like in a real flute. <br />
<h4>
Selecting a pressure sensor</h4>
BMP085 is an absolute pressure sensor accessed using the I2C protocol. No extra components are needed. The drawbacks are that the breath only represents a small fraction of the sensors range and the baseline pressure, ambient pressure, must me calibrated for.. Price is ___<br />
<br />
The other major type of pressure sensor is a MEMS bridge giving a small voltage representing the difference between measured pressure and ambient. The problem here is that the small sensor output must be amplified before the signal is input to a AD converter. No calibration for changing ambient temperature is needed.<br />
<br />Magnus Lundinhttp://www.blogger.com/profile/17303004553752920522noreply@blogger.com1tag:blogger.com,1999:blog-8756201887955423383.post-82964735677149843072013-04-06T15:10:00.000+02:002013-05-05T00:41:04.405+02:00MIDI USB Class for the Maple board<br />
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"></span><br />
<div dir="ltr" style="margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">I got myself an </span><a href="http://openpipe.cc/" style="text-decoration: none;"><span style="background-color: transparent; color: #1155cc; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: underline; vertical-align: baseline;">OpenPipe breakout</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> board and want to use a </span><a href="http://leaflabs.com/devices/" style="text-decoration: none;"><span style="background-color: transparent; color: #1155cc; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: underline; vertical-align: baseline;">Maple board</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">
to connect it to a soft synth on my computer or a hardware synth. For
this I want the Maple to implement a MIDI USB class device.</span></div>
<br />
<div dir="ltr" style="margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">The
Maple has as standard a USB serial device that gets setup and loaded as
part of building a sketch and its then available as SerialUSB object. The MIDI USB will replace the Serial USB, and register the device as a MIDI class compliant device. The Maple bootloader is not affected, but the remote reset into bootloader is not implemented, so a manual reset is needed to get into the bootloader, I can live with that.</span></div>
<br />
<div dir="ltr" style="margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">The MIDI USB needs a few things to setup</span></div>
<br />
<ul style="margin-bottom: 0pt; margin-top: 0pt;">
<li dir="ltr" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">USB Setup and handling of Control Requests</span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">A MIDI USB device descriptor to present itself to a host computer as a MIDI USB device</span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">Bulk IN and OUT endpoints for MIDI USB packets, 32 bit/4 byte blocks of data</span></div>
</li>
<li dir="ltr" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; list-style-type: disc; text-decoration: none; vertical-align: baseline;"><div dir="ltr" style="margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">Code that interprets the MIDI USB packets as standard MIDI events.</span></div>
</li>
</ul>
<br />
<div dir="ltr" style="margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">Building
the MIDI USB class as a variant of the existing USB serial code, the
first and third parts are almost identical for MIDI and Serial, actually
easier for MIDI since no modem control line handling is necessary and
no management endpoint is needed.</span><br />
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">The device descriptor is bit harder, but its a static datastructure and just following the MIDI USB documentation carefully will get you through this.</span><br />
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">The USB MIDI package handling is standard MIDI code, and does not depend on the details of the USB transport layer. </span></div>
<br />
<div dir="ltr" style="margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">The code has been tested and registers as a MIDI device both under OSX and Android, and seems to be working.</span></div>
<br />
<div dir="ltr" style="margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">A git repository can be found at </span><a href="https://github.com/mlu/maple-ide" style="text-decoration: none;"><span style="background-color: transparent; color: #1155cc; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: underline; vertical-align: baseline;">https://github.com/mlu/maple-ide</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"></span></div>
<br />
<div dir="ltr" style="margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">The MIDI USB is built from the following files:</span></div>
<ul>
</ul>
<span style="font-family: "Courier New",Courier,monospace;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"><span style="font-family: "Courier New",Courier,monospace;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"><span style="font-family: Arial,Helvetica,sans-serif;">High level device object, Wirish style, replaces usb_serial.cpp</span></span></span> </span></span><br />
<ul>
<li><span style="font-family: "Courier New",Courier,monospace;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">usb_midi.cpp </span></span></li>
<li><span style="font-family: "Courier New",Courier,monospace;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">include/wirish/usb_midi.h</span></span></li>
</ul>
<span style="font-family: "Courier New",Courier,monospace;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"><span style="font-family: Arial,Helvetica,sans-serif;">Low level USB driver, replaces usb_cdcacm.c</span></span></span><br />
<ul>
<li><span style="font-family: "Courier New",Courier,monospace;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">stm32f1/usb_midi_device.c<br /> </span></span></li>
<li><span style="font-family: "Courier New",Courier,monospace;"><span style="background-color: transparent; color: black; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">include/libmaple/usb_midi_device.h</span></span></li>
</ul>
<span style="font-family: Arial,Helvetica,sans-serif; font-size: 15px;">The process of setting up a sketch to use MIDI instead of Serial is still clumsy and needs some manual editing of the boards.h file.<br /><br />The development is done on a modified Maple-IDE that uses a current arm toolchain and a libmaple layout that is closer to the present libmaple layout so the files are placed in different locations than the standard Maple-IDE file layout.<br /><br />UPDATE 2013/0412<br /><br />The descriptor definitions have been factored out of usb_midi_device and placed into usb_midi_descr.c/h . A working copy of the libmaple git repository with the midi usb files placed in their proper place in the hierarchy can be found at <span style="color: blue;"> <a href="https://github.com/mlu/libmaple">https://github.com/mlu/libmaple</a> .</span></span><br />
<br />
<div dir="ltr" style="margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span></div>
Magnus Lundinhttp://www.blogger.com/profile/17303004553752920522noreply@blogger.com0tag:blogger.com,1999:blog-8756201887955423383.post-15229220293812314792009-09-12T01:12:00.003+02:002009-09-12T16:28:27.564+02:00Using a STM32 based board for Arduino Development<h2>Exploring ways to enhance Arduino while still keeping the ease and experience.</h2>This is work in progress, more details, updates and pictures coming soon. But the basic stuff works as described today.<br />
<br />
Using Arduino boards and the Arduino GUI is a simple and fast way to develop embedded applications. There are predefined functions for input and output, serial communications and timing, many example sketches and the user does not have to worry about low level initialisation, interrupt vectors and timer configurations. On the other hand, ATMega 168 chips have limited resources, it is an 8 bit chip and not very fast.<br />
Modern Cortex-M3 chips like the STM32 are fast, have much more RAM and flash and they have powerful and well documented debugging subsystems using JTAG tools, but starting to program these chips can be a huge step. <br />
<br />
So here is my project to use a slightly modified, but from the users point standard Arduino IDE, standard Arduino sketches and run them on a powerful 32 bit Cortex-M3 (STM32) chip. The process of writing sketches, uploading them and then running them is exactly the same as for ordinary Arduino development. It is just that the processor board we use is not an Arduino. And you can use it all for your old Arduino boards also.<br />
<br />
More complicated sketches that uses lowlevel access to the ATMega chip must be rewritten for this new platform. <br />
<br />
The components we need:<br />
<ul><li>Hardware.</li>
<li>Modified Arduino IDE.</li>
<li>Library code for this chip and board configuration.</li>
<li>Toolchain to compile and build code for a Cortex-M3 processor</li>
<li>An uplader that is used to program the chip.</li>
</ul>The software setup has been developed and tested under Linux. <br />
<h4>Hardware</h4>The board I use is an ET-STAMP-STM32, a chip carrier module that brings out all chip i/o lines but not much more. I bought it for $24.90 from Futurlec (<a href="http://www.futurlec.com/ET-STM32_Stamp.shtml">ET STM32 Stamp</a>). It is mounted on a breadboard together with a 3.3V power supply, a serial USB adapter, a LED and some extra stuff for experimentation lika a potentiometer connected to an analog input and a push button.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQEbr2v6v220HYH80y7pEdIXOAhyYM1lDF01rDH1ZxM03gM78gGjUkk72x_sPdc3CeG_auP6IymThGMfA7PJ-Koskb4TVp8C89lITGkkd5rpcyCbX9lj8_tEgrM1M4qHty6IGyhoEFbhU/s1600-h/arduino_stm32.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQEbr2v6v220HYH80y7pEdIXOAhyYM1lDF01rDH1ZxM03gM78gGjUkk72x_sPdc3CeG_auP6IymThGMfA7PJ-Koskb4TVp8C89lITGkkd5rpcyCbX9lj8_tEgrM1M4qHty6IGyhoEFbhU/s400/arduino_stm32.jpg" /></a></div><br />
The FTDI USB is only used to supply 5V to the small 3.3V regulator board. It can also be connected to UART2 or UART3.<br />
The board is at the moment running a sketch that read the analog voltage from the potentiometer and adjusts the LED blink frequency:<br />
<blockquote><pre><span style="background-color: #fff2cc; font-size: x-small;">volatile </span><span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;">unsigned</span><span style="background-color: #fff2cc; font-size: x-small;"> </span><span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;">int</span><span style="background-color: #fff2cc; font-size: x-small;"> count=-1;
</span><span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;">int</span><span style="background-color: #fff2cc; font-size: x-small;"> ledPin = 44; </span><span style="background-color: #fff2cc; color: #7e7e7e; font-size: x-small;">// STM32_P103 Board - PC12</span>
<span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;">int</span><span style="background-color: #fff2cc; font-size: x-small;"> dly;
</span><span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;">int</span><span style="background-color: #fff2cc; font-size: x-small;"> analogChn = 10; </span><span style="background-color: #fff2cc; color: #7e7e7e; font-size: x-small;">// Analog channel 10 is PC0 = pin 32</span>
<span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;">void</span><span style="background-color: #fff2cc; font-size: x-small;"> </span><span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;"><b>setup</b></span><span style="background-color: #fff2cc; font-size: x-small;">()
{
</span><span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;">pinMode</span><span style="background-color: #fff2cc; font-size: x-small;">(ledPin, </span><span style="background-color: #fff2cc; color: #006699; font-size: x-small;">OUTPUT</span><span style="background-color: #fff2cc; font-size: x-small;">); </span><span style="background-color: #fff2cc; color: #7e7e7e; font-size: x-small;">// sets the digital pin as output }</span>
<span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;">Serial</span><span style="background-color: #fff2cc; font-size: x-small;">.</span><span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;">begin</span><span style="background-color: #fff2cc; font-size: x-small;">(115200); </span><span style="background-color: #fff2cc; color: #7e7e7e; font-size: x-small;">// opens serial port, 31250bps (MIDI speed)</span>
<span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;">Serial</span><span style="background-color: #fff2cc; font-size: x-small;">.</span><span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;">write</span><span style="background-color: #fff2cc; font-size: x-small;">(</span><span style="background-color: #fff2cc; color: #006699; font-size: x-small;">"\n\n *** Hello from Arduino 32 ***\n"</span><span style="background-color: #fff2cc; font-size: x-small;">);
}
</span><span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;">void</span><span style="background-color: #fff2cc; font-size: x-small;"> </span><span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;"><b>loop</b></span><span style="background-color: #fff2cc; font-size: x-small;">()
{
</span><span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;">int</span><span style="background-color: #fff2cc; font-size: x-small;"> k;
count++;
dly = </span><span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;">analogRead</span><span style="background-color: #fff2cc; font-size: x-small;">(10)/2+20;
</span><span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;">digitalWrite</span><span style="background-color: #fff2cc; font-size: x-small;">(ledPin, </span><span style="background-color: #fff2cc; color: #006699; font-size: x-small;">HIGH</span><span style="background-color: #fff2cc; font-size: x-small;">); </span><span style="background-color: #fff2cc; color: #7e7e7e; font-size: x-small;">// sets the LED off</span>
<span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;">delay</span><span style="background-color: #fff2cc; font-size: x-small;">(dly); </span><span style="background-color: #fff2cc; color: #7e7e7e; font-size: x-small;">// waits for a second</span>
<span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;">digitalWrite</span><span style="background-color: #fff2cc; font-size: x-small;">(ledPin, </span><span style="background-color: #fff2cc; color: #006699; font-size: x-small;">LOW</span><span style="background-color: #fff2cc; font-size: x-small;">); </span><span style="background-color: #fff2cc; color: #7e7e7e; font-size: x-small;">// sets the LED on</span>
dly = <span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;">analogRead</span><span style="background-color: #fff2cc; font-size: x-small;">(10)/2+20;
</span><span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;">delay</span><span style="background-color: #fff2cc; font-size: x-small;">(dly); </span><span style="background-color: #fff2cc; color: #7e7e7e; font-size: x-small;">// waits for a second </span>
<span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;">if</span><span style="background-color: #fff2cc; font-size: x-small;"> (count%100 ==0)
{
</span><span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;">Serial</span><span style="background-color: #fff2cc; font-size: x-small;">.</span><span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;">print</span><span style="background-color: #fff2cc; font-size: x-small;">(count);
</span><span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;">Serial</span><span style="background-color: #fff2cc; font-size: x-small;">.</span><span style="background-color: #fff2cc; color: #cc6600; font-size: x-small;">write</span><span style="background-color: #fff2cc; font-size: x-small;">(</span><span style="background-color: #fff2cc; color: #006699; font-size: x-small;">"\n"</span><span style="font-size: x-small;"><span style="background-color: #fff2cc;">);</span>
<span style="background-color: #fff2cc;"> }
}</span>
</span></pre></blockquote>So you can see that the sketch is a totally standard Arduino sketch. <br />
<h4>Modified Arduino IDE.</h4>The Arduino IDE is modified in order to be able to build code with the ARM toolchain. The modified files and some new files that are added can be found at <a href="http://github.com/mlu/arduino-stm32/tree/master">http://github.com/mlu/arduino-stm32/tree/master</a> . These files must be placed in the source tree for Arduino 0017, and then the IDE must be rebuilt.<br />
<h4>Library code for this chip and board configuration.</h4>The special code for this chip and board are found under hardware/stm32 and to use this you just have to select the board "<i>STM32 Arduino32</i>" in the Tools menu in the IDE.<br />
<br />
<h4>Toolchain to compile and build code for a Cortex-M3 processor</h4>I use the Codesourcery G++ Lite Edition for ARM, EABI version, that can be downloaded from the Codesourcery website (<a href="http://www.codesourcery.com/sgpp/lite/arm/portal/subscription?@template=lite">Codesourcery G++ Lite</a> ).<br />
Install this and make sure that the top bin directory containing "arm-none-eabi-gcc" and the rest of the cross compilation binaries are in the path.<br />
<h4>Uploader</h4>I have written a small uploader, using similar command line arguments as avrdude, that uploads the compiled and linked sketches to the processor.<br />
The code and also a compiled binary that runs under Fedora 10 are included in the files at github.com/mlu/arduino-stm32.<br />
<br />
<h3>Almost ready to rock</h3>The first thing to notice is that the pin numberings are different<br />
<blockquote style="font-family: "Courier New",Courier,monospace;"><b>Arduino sketch Board</b><br />
digital pin number 0..15 pin PA0 .. PA15<br />
analog pin number 0..7 pin PA0 .. PA7<br />
analog pin number 8,9 pin PB0,PB1<br />
analog pin number 10..15 pin PC0 .. PC5 </blockquote>Pins 9 and 10 (PA9 and PA10) are used by USART1 and are connected to the RS232 level shifter for the serial port and should not be used.<br />
<br />
We must also manually switch the board between bootloader mode and normal run mode with the blue switch, and also do all resets manually with the reset switch.<br />
<br />
<h3>Testing Blink</h3>Blink uses the LED on pin number 13, This corresponds to pin PA13 so we add a LED and a 220 ohm serial resistor to PA13. Connect a serial adapter to the board and select the corresponding serial port in the Arduino IDE.<br />
Load the Example/Digital/Blink sketch and select board type "STM32 Arduino 32". Set the board in bootloader mode by depressing the blue button, the green bootloader LED lights up, and reset the board. Now it should be possible to simply upload the sketch :), go back to normal run mode with the blue button and reboot with the reset button.<br />
<br />
Now this is new and quite untested code so many things could go wrong when trying to do this on a computer with a different setup.<br />
<br />
More to follow, especially with reader feedbackMagnus Lundinhttp://www.blogger.com/profile/17303004553752920522noreply@blogger.com8tag:blogger.com,1999:blog-8756201887955423383.post-39368733006677011912009-09-05T16:09:00.034+02:002009-09-06T23:18:14.057+02:00Debugging on the Cortex-A8, System Components<h2>Cortex-A8 for dummies, part 1</h2>I have been working on the Cortex-A8 subsystem for OpenOCD for some time this summer. This is great fun, when there is enough time, but also takes a lot of work. It is a complicated system and the documentation is large, spread over several big TRM's and sometimes hard to grasp. So here comes the "Cortex-A8 Debugging for Dummies" version 0.0. This first post looks at the main components involved and the access methods. <br />
<br />
You can also take a look at OpenOCD for the BeagleBoard at<br />
<a href="http://elinux.org/BeagleBoardOpenOCD">http://elinux.org/BeagleBoardOpenOCD</a><br />
<br />
The new members of the ARM family of processor cores, the Cortex-M3 and the Cortex-A8, share some features but in many fundamental ways they are not similar. They both support the Thumb2 instruction set and they both use the ARM Debug Interface v5 for debugging and direct access to the core debug units and the AHP and APB buses. Cortex-M3 processors also use the NVIC interrupt controller for handling peripheral interrupts. This makes debugging easier and interrupt handling more consistent when using processors from different suppliers. Cortex-A8 processor have implementation defined handling of external interrupts.<br />
<br />
Architecturally there are big differences. The Cortex-M3 uses the ARMv7M profile with a very simplified set of processor modes and a reduced set of shadow registers. Cortex-M3 can only run Thumb2 code. This is in contrast to the Cortex-A8 that can run ARM, Thumb and ThumbEE instructions, and where the architecture is a variant of the standard ARM architecture seen in ARM7, ARM9 and ARM11 cores.<br />
<br />
<h3>System Components<br />
</h3>Here is a simplified picture of a Cortex-A8 system, based on the Texas Instrument OMAP3530 Applications Processor, used in the BeagleBoard. There are four main components involved in our picture of the system:<br />
<ul><li>Debug Access Port, connects an external debugger through JTAG or SW, serial wire, to our system. The DAP can have one or several Access Ports, AP, that connects to different parts of the system. <br />
</li>
<li>MPU, Microprocessor Unit Subsystem. Here we find the processor core, core registers, system coprocessor CP15, Memory Management Unit, L1 and L2 Cache.</li>
<li>A Core Debug Unit that can pass data and instructions directly to the processor core, and also halt and resume the processor. This is connected to the AP through a local memory bus, an Advanced Peripheral Bus, APB.<br />
</li>
<li>External high speed bus, this is the L3 bus and it is an implementation of the Advanced High Speed Bus, AHB, specified by ARM. Peripheral components and memory are connected to this bus.</li>
</ul><h4>Main Components for Core Debug System with one APB and one AHB MEMAP<br />
</h4><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/AVvXsEg07h9pPHFtajcK5imwd9FBBeU3emoFrXIZGFo_4wr4JfOven4lKQ63VHUiDRaLhU3gGHq-j0Z0BFJ5Ke2dmz63fpQjZ7-MoIifb6XRpfQqkQRbY0RoyevY2bwUNBf4FYMzM6484XTo47Q/s1600-h/cortex_a8_debug_components.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg07h9pPHFtajcK5imwd9FBBeU3emoFrXIZGFo_4wr4JfOven4lKQ63VHUiDRaLhU3gGHq-j0Z0BFJ5Ke2dmz63fpQjZ7-MoIifb6XRpfQqkQRbY0RoyevY2bwUNBf4FYMzM6484XTo47Q/s400/cortex_a8_debug_components.png" /></a></div><br />
In this example we have two access ports, both of them access system resources by a local memory address space, so called memory mapped access ports or MEMAP. The access ports are marked with the type of bus it is connected to. The APB-AP is connected to the debug resources without going through the system AHB bus. Each MEMAP have a access port number to identify it in the DAP. For the OMAP3530 processor the AHB-AP is number 0 and the APB-AP is number 1. <br />
<br />
A debug program like OpenOCD connects through JTAG to the DAP, and all communications are passed through an access port into the system. When using OpenOCD we can select which access port to use with the command:<br />
<blockquote><span style="background-color: #ffe599; font-family: "Courier New",Courier,monospace;">>dap apsel n</span></blockquote>Here n is 0 or 1 for a system with two AP's. After selecting a MEMAP we can access the memory space of the AP with the memory display word, mdw, and memory write word, mww, commands: <br />
<blockquote style="background-color: #ffe599; font-family: "Courier New",Courier,monospace;">>dap apsel 1<br />
>mdw 0x80000000<br />
>dap apsel 0<br />
>mdw 0x80000000<br />
>mww 0x80000000 0x12ab34cd<br />
>mdw 0x80000000</blockquote>If there is no memory at the specified address or if the access is prohibited by the security manager a "Sticky Error" is generated by the AP and reported by OpenOCD. We can get more information about the type of resources a MEMAP is connected to by using the command<br />
<blockquote><span style="background-color: #ffe599; font-family: "Courier New",Courier,monospace;">>dap info n</span></blockquote>This information is encoded by the AP in a so called ROM Table. The details of how to identify system resources from a ROM Table will be explained in a later post.<br />
<br />
The APB AP, with MEMAP access port number 1, is reported as "<span style="font-family: "Courier New",Courier,monospace;">MEMTYPE system memory not present. Dedicated debug bus.</span>"This indicates that only CoreSight components and other debug resources identified in the ROMTABLE for this AP are accessible. Memory and memory mapped peripheral control registers are not available.<br />
<br />
The ADP v5 Debug Port is described in <i><a class="external text" href="http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ihi0031a/index.html" rel="nofollow" title="http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ihi0031a/index.html">ARM IHI 0031A</a> (ARM Debug Interface v5).</i><br />
<br />
AHB and APB buses are described in <i><a class="external text" href="http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ihi0011a/index.html" rel="nofollow" title="http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ihi0031a/index.html">ARM IHI 0011A</a> (AMBA Specification Rev. 2.0).</i><br />
<br />
The Debug Unit, the debug registers, MPU and the cache systems are described in <i><a class="external text" href="http://infocenter.arm.com/help/topic/com.arm.doc.ddi0344h/DDI0344H_cortex_a8_r3p0_trm.pdf" rel="nofollow" title="http://infocenter.arm.com/help/topic/com.arm.doc.ddi0344h/DDI0344H_cortex_a8_r3p0_trm.pdf">ARM DDI 0344H</a> (Cortex-A8 TRM).</i><br />
<br />
The system overview and relation between the components can also bee sen in <a class="external text" href="http://www.ti.com/litv/pdf/spruf98b" rel="nofollow" title="http://www.ti.com/litv/pdf/spruf98b">OMAP35x Technical Reference Manual</a> (spruf98b.pdf) Figure 1-1. Interconnect Overview.<br />
<br />
<h3>Core and Memory Access<br />
</h3>The core is accessed through the APB MEMAP using the communications registers in the debug unit DTRRX, DTRTX and ITR.<br />
<br />
Access to the full memory address range of the system can be done through the AHB AP to the L3 bus and is controlled by the security and access restrictions that are active in the system. This access always uses physical memory addresses (PA). There is risk for cache coherency problems when accessing memory this way, for <i>volatile</i> resources like I/O registers the problem should be less. This access can be done while the MPU Core is running.<br />
<br />
When MMU is active all memory addresses in the core like PC, LR and data pointers are virtual addresses and must be translated to physical addresses before accessing them through the AHB AP.<br />
<br />
Another way to access memory and memory mapped resources from the debug port is through the MPU using LDR and STR instructions written to the ITR and data in the DCC registers, DTRRX and DTRTX. [Cortex_A8 TRM, sec 12.11.6]. This access will go through the Cache and Memory Management Units of the Cortex_A8 and thus use virtual addressing when this is activated.<br />
<h4>Strategies<br />
</h4>For configuring systems at start up, such as setting memory controller parameters, clocks and PLL registers, memory access through the AHB access port is good. This should also work well for writing to flash memories.<br />
<br />
For debugging code running on the MPU, the APB and access through the MPU core probably should be used, since this method avoids problems with virtual to physical address translations and also helps avoid cache coherency problems.<br />
<br />
A debug system should implement both access methods and some method to choose which one to use.<br />
<br />
<br />
<h2>Acknowledgements</h2>Many thanks to Dirk Behme for proof reading and helpful comments.Magnus Lundinhttp://www.blogger.com/profile/17303004553752920522noreply@blogger.com2tag:blogger.com,1999:blog-8756201887955423383.post-44475473326391958852009-07-31T01:02:00.003+02:002013-08-02T12:48:56.431+02:00MIDI7S - a flexible USB - MIDI interface<h2>
MIDI7S - a flexible USB - MIDI interface </h2>
<br />
This page is work in progress and will be updated with more precise documentation when that is available.<br />
<br />
Update june 2013<br />
<br />
All the images had vanished from the blog, thanks blogger, but now I have restored them. My work with midi has mostly moved on to use Maple boards and STM4FDiscovery board. The Teensy 3 board have midi implemented as standard and uses Arduino IDE for coding and programming making things much simpler.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<h3>
System Components</h3>
<div id="ahfs" style="text-align: left;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnOQNqDawi05_a5oKpdKD9jbMGqIz8ualKHrDw0XTUpmwW3Cjx4oPL_1JyCf_IZnL-rulIOzHRvMtK4KZ2Wi0wxGYT9dQSRyNoSsbl8YHrEESXGaCxqOhcKyrojP-s085XU01Sxpzat-U/s1600/midi7s_system.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="552" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnOQNqDawi05_a5oKpdKD9jbMGqIz8ualKHrDw0XTUpmwW3Cjx4oPL_1JyCf_IZnL-rulIOzHRvMtK4KZ2Wi0wxGYT9dQSRyNoSsbl8YHrEESXGaCxqOhcKyrojP-s085XU01Sxpzat-U/s640/midi7s_system.jpg" width="640" /></a></div>
<br />
<h4>
Processor board</h4>
<br />
The AT91SAM7S64 processor has 3 uarts that can be used as MIDI ports and a USB interface. The Olimex SAM7-P64 board also has header for most uP pins, power supply and mmc card connector. This makes it a cheap and powerful platform for a USB MIDI system.<br />
<h2>
</h2>
<div style="text-align: left;">
<br /></div>
<br />
This processor is a bit old, but it is still a nice processor and I had this board and did not use for anything else. Today I would probably use something like a Olimex STM32-P103 board or design my own board for a STM32F103 processor.<br />
<br />
<h4>
MIDI interface board</h4>
MIDI out is driven directly from the microprocessor uart tx pin. Only one 220Ohm resistor is used , there should be two according to reference implementations. When driving MIDI from a 3.3 V source 2x70 Ohm is probably the best, for a typical VF in the optocoupler of 1.5V and series resistance of 220 Ohms in the receiver this gives I=(3.3-1.5)/360 = 5mA. The short curcuit current, 47 mA is a little bit high but not exceptional. The MIDI receivers uses 6N137 optoisolators<br />
<br />
MIDI 1 IN / OUT<br />
<br />
MIDI 2 IN / OUT<br />
<br />
Schematic (one channel):<br />
<div id="i70f" style="text-align: left;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgi_bx1fddH7Zwjc_KA4Pri1V_X_rHycQtHE7OZnG70w_Th6M841VAOMn1ABH3jDvwkNeliAMLSNqX2CCCQ4fy-MQ1iDu1e7YioVjL4b0D6Foj0uEF3dYqZ2vffFc8CHyWzeADRx4SBnYQ/s1600/midischem_33.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="514" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgi_bx1fddH7Zwjc_KA4Pri1V_X_rHycQtHE7OZnG70w_Th6M841VAOMn1ABH3jDvwkNeliAMLSNqX2CCCQ4fy-MQ1iDu1e7YioVjL4b0D6Foj0uEF3dYqZ2vffFc8CHyWzeADRx4SBnYQ/s640/midischem_33.png" width="640" /></a></div>
<br />
<br />
Board layout (one channel)<br />
<div id="uod0" style="text-align: left;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgO5SECLRONKN5g33vALHXuiCyOH0D2EqnyoqKYbqdcacP8tFqiQWDyj2bckPeojtHgfDwnISw8MsSnHIvqWHcZjNnlJtEpEGczZbAyahto-wAETvsikAfpghGjB9pB90eI4jHjVxkDnc4/s1600/midiboard.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"></a><img border="0" height="546" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgO5SECLRONKN5g33vALHXuiCyOH0D2EqnyoqKYbqdcacP8tFqiQWDyj2bckPeojtHgfDwnISw8MsSnHIvqWHcZjNnlJtEpEGczZbAyahto-wAETvsikAfpghGjB9pB90eI4jHjVxkDnc4/s640/midiboard.png" width="640" /></div>
<br />
The actual construction was built on a strip-board<br />
<br />
<h4>
DOG-ME Display board</h4>
This a 2x20 character LCD display using serial communications<br />
<br />
<br />
<h3>
Communication Interfaces</h3>
<h4>
USBMIDI</h4>
The USBMIDI configuration uses two logical USB MIDI Cables connected to the physical MIDI ports<br />
/* MIDI IN JACK 1 receives data from the USB interface Ep 1 */<br />
/* MIDI IN JACK 2 receives data from the serial uartmidi[0] */<br />
/* MIDI OUT JACK 3 transmits data to the USB interface Ep 82 */<br />
/* MIDI OUT JACK 4 transmits data to the serial uartmidi[0] */<br />
/* MIDI OUT JACK 8 transmits data to the serial uartmidi[1] */<br />
<br />
The sending of USB MIDI data through MIDI OUT JACK 3 using USB IN endpoint Ep82 needs work for buffering and handling of many small write requests<br />
<br />
<h4>
Serial MIDI</h4>
The serial MIDI interfaces are connected to USART0 and DEBUGUSART. USART1 is connected to a RS232 level shifter an can be used for "standard" serial communications.<br />
<br />
<br />
<h4>
Dog-ME Display interface (SPI 3.3V) </h4>
PA13 MOSI<br />
PA14 SPCK<br />
PA30 IRQ1/NPCS2 DOG_LCD_SELECT_PIN<br />
PA31 NPCS1/PCK2 DOG_LCD_RS_PIN<br />
<br />
<h3>
Code</h3>
The code is written in C++ using a minimal profile for small embedded systems, no dynamic object creation, no exceptions.<br />
<br />
<br />
<h4>
USB MIDI device descriptor</h4>
http://www.usb.org/developers/devclass_docs/midi10.pdf<br />
<br />
<a href="http://docs.google.com/Doc?docid=0AQkzMBFZwrYtZGN4a2Qzd2hfMzZkNnBybnJjNQ&hl=en" id="yilo" title="USB MIDI device descriptors as C code">USB MIDI device descriptors as C code</a>, <a href="http://docs.google.com/Doc?docid=0AQkzMBFZwrYtZGN4a2Qzd2hfNDBwa3dtcnZndg&hl=en" id="wsfx" title="corresponding header file">corresponding header file</a><br />
<h4>
Transmission buffers</h4>
All uart communications uses buffered DMA transactions<br />
<br />
spi to the display should also use DMA but with a DLYBCT of 50 giving a character spacing of approximatly 33us, the serial:: transmission logic can be reused (subclassed) here.<br />
<br />
The AT91SAM7 variable chipselects and chipselect decode mode together with 32 bit DMA SPI transmissions allows us to control both data bits and the RS line with automatic transfers to the Dog-Me display. <br />
<br />
<h3>
Testing</h3>
The system has been used as an USB to MIDI inteface betwen a Linux computer and a U220 synth module. The usb midi ports are autodetected and added as Alsa MIDI ports. Some USB communication gliches has been observed, but not frequent and not yet reproducible. Loopback tests with a standard MIDI cable connected from MIDI out to MIDI in works well.<br />
<br />
Round trip times on PC running Linux, Fedora 10, PC(Alsa MIDI)->USB MIDI IN->MIDI OUT->MIDI IN->USB MIDI OUT->PC are 1.5 - 3 ms (/home/lundin/delad/arbete/mikrop/usbmidi/miditest.c) with processing times up to 130uS using single message pings (090531 r357)<br />
Direct echo within the module , no serial MIDI, gives times of .8 to 2 ms<br />
<br />
<br />
<br />
<h3>
Future </h3>
<br />
With the basic USB and MIDI communications working, it is possible to expand the capabilities of the system.<br />
The analog and digital inputs can be used to generate MIDI events from different sensors and there is spare processor capacity for MIDI processing.<br />
<br />
TWI EEPROM For settings<br />
<br />
Control panel<br />
<br />
I/O Extender<br />
<br />
MIDI file player<br />
<br />
Sensor to midi event generationMagnus Lundinhttp://www.blogger.com/profile/17303004553752920522noreply@blogger.com4Southern Europe58.263287052486007 13.710937536.952121052486007 -27.5976565 79.574453052486 55.0195315tag:blogger.com,1999:blog-8756201887955423383.post-59256505496411861392008-08-08T03:14:00.008+02:002009-07-30T17:48:43.231+02:00Using Python and XML for parsing USB descriptor structures to CThis project consists of a Python script that parses an XML description of USB descriptors and generates C code structures that can be included in a C firmware program for a USB device. This tool is primarily intended for developers of USB devices on embedded platforms. The XML representation of the descriptors gives a good view of the structure and the Python parser generates correct bDescriptorType values, bLength values and calculates total lengths. For elements with a variable number of child elements, such as bNumEndpoints in the Interface descriptor, the correct value is inferred from the XML structure. Most elements have a default value that is inserted in the generated C data structure. Symbolic values can be used for field values through XML entities defined in a DTD. <h3 id="bj85">Related work</h3>This project is part of a set of tools written in Python to simplify work with embedded development and USB. Most of the development work is done under Linux. Other components in this effort are: <ul id="jyek"><li id="jyek0">usbmodule: A Python module that wraps libusb and gives raw access to USB devices, with experimental thread code to download and buffer incoming data before the application requests it, this works (for me) but it is unstructured, uncleaned and probable a bit buggy. This is similar to PyUSB http://pyusb.berlios.de/ , I have not had time to really check out this project, perhaps we should merge .... </li></ul> <ul id="jyek1"><li id="jyek2">A python GUI application for firmware downloads to embedded systems, first written to program Parallax Javelin systems from Linux, then extended to talk to serial monitors on LPC2xxx and AT91SAM7 arm processors. Today it is mostly used for SPI flashing of Atmel AVR8 processors using an FT232 interface in bitbang mode (this is where the USB from Python is used) </li></ul><h3 id="sl9e0">Example</h3>An example XML representation of a device dsecriptor <div id="xvbk"><blockquote style="background-color: rgb(255, 242, 204);" id="ojf:"><USB_Device_Descriptor name="devDescriptor" bcdUSB="0110" bDeviceClass="0" bDeviceSubclass="0" bDeviceProtocol="0" idVendor="EB03" idProduct="2463" bcdDevice="0000" iManufacturer="1" iProduct="2" iSerialNumber="3" bNumConfigs="1"/> </blockquote>and the output in C code format that is generated </div><blockquote style="background-color: rgb(255, 242, 204);" id="k4_5"><span style="font-family:courier new;">const char devDescriptor [] = { </span><br /><span style="font-family:courier new;">// Device Descriptor </span><br /><span style="font-family:courier new;">/* 0 */ 0x12, //bLength </span><br /><span style="font-family:courier new;">/* 1 */ 0x1, //bDescriptorType<br />/* 2 */ 0x10, </span><span style="font-family:courier new;"> //bcdUSB<br />/* 2 */ 0x1,<br />/* 4 */ 0x0, </span><span style="font-family:courier new;"> //bDeviceClass<br />/* 5 */ 0x0, </span><span style="font-family:courier new;">//bDeviceSubclass<br />/* 6 */ 0x0, //bDeviceProtocol<br />/* 7 */ 0x8, </span><span style="font-family:courier new;">//bMaxPacketSize0<br />/* 8 */ 0x3, </span><span style="font-family:courier new;">//idVendor<br />/* 8 */ 0xeb,<br />/* 10 */ 0x63, </span><span style="font-family:courier new;">//idProduct<br />/* 10 */ 0x24,<br />/* 12 */ 0x0, </span><span style="font-family:courier new;">//bcdDevice<br />/* 12 */ 0x0,<br />/* 14 */ 0x1, </span><span style="font-family:courier new;">//iManufacturer<br />/* 15 */ 0x2, //iProduct<br />/* 16 */ 0x3, </span><span style="font-family:courier new;">//iSerialNumber<br />/* 17 */ 0x1 </span><span style="font-family:courier new;">//bNumConfigs</span><br /><span style="font-family:courier new;">};</span> </blockquote> <h3 id="jy26">Status</h3>Currently the tool can generate what looks as correct C code structures, with examples from USB specification. The output has not been tested and used as descriptor structures in actual USB firmware. The Python code can be run as a simple command line tool. There is a lack of documentation for the XML tags and attributes used. Future work devoted to this will depend on the testing and also interest from third parties- <h3 id="jy262">Future work</h3>Use the output from this tool as descriptors for a MIDI interface implemented on an AT91SAM7S development board. Use the output from this tool as descriptors for a HID device implemented on an AT91SAM7S development board connected to . This document/page will also be updated and made more complete depending on external feedback. <h3 id="jy265">Contact</h3>Magnus Lundin If you are interested in this project contact me at: lundin at mlu dot mine dot nuMagnus Lundinhttp://www.blogger.com/profile/17303004553752920522noreply@blogger.com0tag:blogger.com,1999:blog-8756201887955423383.post-48782065410777304632008-08-08T02:49:00.002+02:002008-08-08T12:46:55.346+02:00Welcome<span style="font-size:130%;">Hi there, and welcome to all who are interested in Art and Microcomputers<br /></span><br />And in the power to create your own designs.<br /><br />A new blog !!!<br />I am not sure the world needs so many more blogs. But I will use this space to discuss some of my ideas on tools used in connection with art and microprocessors.<br /><br />Hopefully I will also get some feedback from you out there, passionate users of microprocessors and connected hardware in artistic projects.<br /><br />Some background:<br />I have a background as a programmer, mathematician and also as a dancer. I have done projects in this field since around 1991 when I worked on computer choreography tools with the Kacor group (Stockholm) . Since then I have done computer control for dance performance music, when that was still mostly done by swapping casette tapes and for the last ten years I have mostly worked with choreographer Åsa Unander-Scharin at Scen och Sinnesproduktion and produced some mechatronic installations with her, notably Orpheus and Petrushka .<br /><br />This work has evolved from purely software to a very mixed mixed bag of software, hardware and firmware. During this process I have used and also constructed a wide array of tools. Some of this might be interesting to YOU ?<br /><br />So, a new blog ... we will see<br /><br />Yes I do have a "regular" job at the side to pay rent and other expenses.Magnus Lundinhttp://www.blogger.com/profile/17303004553752920522noreply@blogger.com1