From efb63070a22ca8d3f4df7d5eee5660f23e4cf447 Mon Sep 17 00:00:00 2001 From: Ricky Barrette Date: Tue, 11 Dec 2012 11:06:07 -0500 Subject: [PATCH] Updated ioio library to the lastest code Orignal code pulled from git://github.com/ytai/ioio.git Please note that built in Android Open Accessory support is included in Android 3.1 (API Level 12). If you want to use Android 2.3.4 (API Level 10) amd higher, you will need to use the Add-On Support Library. --- IOIOLib/.classpath | 4 +- .../bluetooth/BluetoothIOIOConnection.class | Bin 3237 -> 3237 bytes .../ioio/lib/impl/AnalogInputImpl.class | Bin 3747 -> 3755 bytes .../bin/classes/ioio/lib/impl/Constants.class | Bin 938 -> 934 bytes .../ioio/lib/impl/DigitalInputImpl.class | Bin 2215 -> 2215 bytes .../ioio/lib/impl/DigitalOutputImpl.class | Bin 1135 -> 1135 bytes .../lib/impl/FlowControlledOutputStream.class | Bin 3102 -> 3102 bytes ...owControlledPacketSender$FlushThread.class | Bin 1750 -> 1754 bytes .../lib/impl/FlowControlledPacketSender.class | Bin 3023 -> 3023 bytes .../bin/classes/ioio/lib/impl/IOIOImpl.class | Bin 20857 -> 20862 bytes .../impl/IOIOProtocol$IncomingHandler.class | Bin 1199 -> 1327 bytes .../impl/IOIOProtocol$IncomingThread.class | Bin 7287 -> 7500 bytes .../ioio/lib/impl/IOIOProtocol$PwmScale.class | Bin 1490 -> 1490 bytes .../classes/ioio/lib/impl/IOIOProtocol.class | Bin 13575 -> 13627 bytes .../ioio/lib/impl/IcspMasterImpl.class | Bin 3422 -> 3422 bytes .../impl/IncomingState$ConnectionState.class | Bin 1355 -> 1355 bytes .../impl/IncomingState$DataModuleState.class | Bin 2064 -> 2064 bytes .../impl/IncomingState$InputPinState.class | Bin 1834 -> 1834 bytes .../classes/ioio/lib/impl/IncomingState.class | Bin 10140 -> 10520 bytes .../ioio/lib/impl/PinFunctionMap.class | Bin 1828 -> 1828 bytes .../bin/classes/ioio/lib/impl/PwmImpl.class | Bin 2199 -> 2203 bytes .../ioio/lib/impl/SocketIOIOConnection.class | Bin 2864 -> 2864 bytes .../classes/ioio/lib/impl/SpiMasterImpl.class | Bin 5791 -> 5791 bytes .../classes/ioio/lib/impl/TwiMasterImpl.class | Bin 4684 -> 4688 bytes .../bin/classes/ioio/lib/impl/UartImpl.class | Bin 2673 -> 2673 bytes .../AbstractIOIOActivity$IOIOThread.class | Bin 3776 -> 3776 bytes .../ioio/lib/util/AbstractIOIOActivity.class | Bin 4868 -> 4868 bytes IOIOLib/project.properties | 2 +- IOIOLib/src/ioio/lib/api/DigitalInput.java | 280 +-- IOIOLib/src/ioio/lib/api/DigitalOutput.java | 240 +-- IOIOLib/src/ioio/lib/api/IOIO.java | 1392 ++++++------- IOIOLib/src/ioio/lib/api/Uart.java | 214 +- IOIOLib/src/ioio/lib/impl/Constants.java | 90 +- IOIOLib/src/ioio/lib/impl/IOIOImpl.java | 1400 +++++++------- IOIOLib/src/ioio/lib/impl/IOIOProtocol.java | 1719 +++++++++-------- IOIOLib/src/ioio/lib/impl/IncomingState.java | 8 +- IOIOLib/src/ioio/lib/impl/TwiMasterImpl.java | 2 +- .../lib/spi/NoRuntimeSupportException.java | 2 +- .../ioio/lib/util/AbstractIOIOActivity.java | 738 +++---- .../ioio/lib/util/IOIOConnectionRegistry.java | 264 ++- IOIOLib/src/ioio/lib/util/IOIOLooper.java | 110 +- 41 files changed, 3235 insertions(+), 3230 deletions(-) diff --git a/IOIOLib/.classpath b/IOIOLib/.classpath index a4763d1..3f9691c 100755 --- a/IOIOLib/.classpath +++ b/IOIOLib/.classpath @@ -1,8 +1,8 @@ - - + + diff --git a/IOIOLib/bin/classes/ioio/lib/bluetooth/BluetoothIOIOConnection.class b/IOIOLib/bin/classes/ioio/lib/bluetooth/BluetoothIOIOConnection.class index d78a3d2e8879debf3e77ff8fbe1a85a60cf5ed9a..558fdf7319bc1da106c3d806afada04acd82f14c 100644 GIT binary patch delta 27 jcmZ1~xm0q)XHG`B$zM2)87FPl;PPN(RNh?3ZNdluhl2=I delta 27 jcmZ1~xm0q)XHG`N$zM2)8K-X6;PPN(RNGw0ZNdluhxG_u diff --git a/IOIOLib/bin/classes/ioio/lib/impl/AnalogInputImpl.class b/IOIOLib/bin/classes/ioio/lib/impl/AnalogInputImpl.class index 3f63933173ee1cfd02a2a6e821ef849d1b301661..fa4306a46ef6af9b20b8f01fdefd383e074731b5 100644 GIT binary patch delta 78 zcmZ21yIOX`3@%3D$uqfZ7^hFZ#^ofe$H2|Nz>vwn!jQ$l!H~_s%aAi!o%<8xj>%Fy diQ*9176x{PR-kMvwn!jQ$l!H_*!oBI>vmdSEFiNX+> V76x{PR-jBfgD^wK=4m{lOaN}n548XQ diff --git a/IOIOLib/bin/classes/ioio/lib/impl/Constants.class b/IOIOLib/bin/classes/ioio/lib/impl/Constants.class index 1115ed1b437fbbaa525eeb4bc5d2852f9f130a92..f3b3595479102c8e5daeba4355c95cba4e40beed 100644 GIT binary patch delta 37 tcmZ3*zKngt5hli2laDgh3kxx@FfcHvG4L^{Gbl4?Gej`xOpa#u2LQIt2j2hy delta 41 xcmZ3+zKVUr5hliYlaDghi;FR^GB7ZxG4L^{Gbl4?Gej`xFyu1GPY!4H2LRSZ2y_4d diff --git a/IOIOLib/bin/classes/ioio/lib/impl/DigitalInputImpl.class b/IOIOLib/bin/classes/ioio/lib/impl/DigitalInputImpl.class index ca776c9e83a5675fbd818a266eda167056167f7c..6cfc6364e20c6c249fed157e916ce1a51b853402 100644 GIT binary patch delta 14 VcmZ23xLj~UA3LM)=6-ewMgS!&1S|jm delta 14 VcmZ23xLj~UA3LMi=6-ewMgS!~1TO#p diff --git a/IOIOLib/bin/classes/ioio/lib/impl/DigitalOutputImpl.class b/IOIOLib/bin/classes/ioio/lib/impl/DigitalOutputImpl.class index 5d8c712c5c5d98d504f0daff24a12f4b569e04e2..8377952adeaf9a9eced5d2acaf149085100f1906 100644 GIT binary patch delta 13 UcmaFQ@t$LYIt!!1WDOQ~03u=o@c;k- delta 13 UcmaFQ@t$LYIt!!nWDOQ~03vY%^Z)<= diff --git a/IOIOLib/bin/classes/ioio/lib/impl/FlowControlledOutputStream.class b/IOIOLib/bin/classes/ioio/lib/impl/FlowControlledOutputStream.class index c732183f1c289743b5a57b4802342d08c7b72f67..e2f38f741107d07d39d19899ce6787ed1601fdac 100644 GIT binary patch delta 20 ccmbOyF;8N{2M$K5$saimGst@>UFd3=9mZ3@i*84BQNvKwdV3D3DfR$YQW($ef(WRtf+l C?+R7` delta 45 zcmcb`dyRKPH!GvUt(q;_23=9mZ3@i*84BQNv415gP45C0veqMaT0}e*1$qza9GfHn>$f?H!09aoKWB>pF delta 20 ccmX>veqMaT0}e*n$qza9GsI@jhNg`+hO`Zh4e1y8bHLgUhaKEG*ou^+I5;^-z9koz)!I$; zU2>C~!%hxPa*>Ntav~+4c6zVZ`%~|y$iE`5_I+H^2fi&btv{PH9kjF+s~FVkEAho1 z{WkbWHt5^oLvmbM$#VwOQ&O>2ZH~OqRtuvKqPL`uM7c=K)nCE^CxC={PlfkGH_Vh# zmo3AYy@nxr6#b~yFotdM#)S8w9$+J!^q`JS@X-rDeF(AzQTh>ME8=WNT)bh)NIUW< z2nwUk5Ljc&@XE%Wa1UI5_mbO0b=EC2h;T)n*uAQfPM9V;;bj*B466@&K(&qKXzIe) zvB8}FoscJ{b$+r+d1Bm(7`)eOQ>PBP)W^)8nKt4w(tu|S=-t^Na$T3^R>=+hJ>Tu* Tjt(wLGzRm(xvam4#q`V2c*fCH@Ct7aTrk)`>>i2~~+N(XBq>hji=h$%?_{+ZlN^txJgpIj57!L4%Ka zW%k%cQ#Dh29n*#-s&>4>(!1$Va#detisYL9oe$c%qXStvIn$}!g-xWNg%kb*4l+$X diff --git a/IOIOLib/bin/classes/ioio/lib/impl/IOIOProtocol$IncomingHandler.class b/IOIOLib/bin/classes/ioio/lib/impl/IOIOProtocol$IncomingHandler.class index 05b920c2e43791df2a8b276c68d7e4ab9da3b9e5..d05e0274bf727a281882150f082caa4faaa9e289 100644 GIT binary patch delta 353 zcmZ3_xt@#b)W2Q(7#J9g7)&>EO=qlE*6_(nEKAfcEy>K$_sJ|Su}0@>hA}d524|+{ zC6<&Hr7|-3qU*4M=*UUTOV{_zD@jdHEwZ*lHwL>R&CM$qPcpI?Gcrg`6p)(S&zxJ& z$RGxE9utE&3nPOBgCqk3kd}hd(hM?SzAS?Pn3jWz%R^}e21T&A5>#FpDy{;hRiXOT zpz`Vr9ANbtP+F5g(grM`#h?wQb)Xt_p$6!IXrSZt!K49$A&}-`U<5)V1`{?;08^Mg A2><{9 delta 224 zcmZ3_wVspf)W2Q(7#J9g7>qY^O=o0d*NFCv_S`Jbbc&J1kdZ-ZqJY$7c9z_F1{OvJ zF$Qr45G?_vB^ji^d}#&&Ff9WWmxa=D4Dw)c1*p6tR9p#4D?|0GK;=~#IKb-FptL$v nod$!Z30Oi4szDnnp#!2Bm>6`yq#lDlkmh1w1VRG_BQ{O|kR=i3 diff --git a/IOIOLib/bin/classes/ioio/lib/impl/IOIOProtocol$IncomingThread.class b/IOIOLib/bin/classes/ioio/lib/impl/IOIOProtocol$IncomingThread.class index 3233d4fdaf08a91777c49a39b5f93a7691697176..9151c99cd1565eb0e058d811151352f64ce58745 100644 GIT binary patch literal 7500 zcmb7J3w%`Nl|SG4?wy%TE)WtD7!pF{nFJv`1d#-gmoVLEkU$WhTqZZk;AAGwLmsw> z6uauKb+wNb)FP|fRO_R*@`zHUt=g`(t97gGs;#ZH4hOc2~I{OEVZV9)nOeWHaNFp{N9FHWr zqw&twT}j7o_miQhWTSn#-4L_moedsTQL!LfIyzEL`VvJd49MknEZV+!OWH{R;)}*N zWI8b63l@Wc9k*kN&Xv)4n;pxz1SQQb(@Z)VYiN$9(v6CWTBDtDJDo{7iY6Y1Zt}ie z9m4Un)9EA|7hp}6^I1u|+W~tKJtXdID*U#RPIuyRr#*`vR=~N{5xElvLrx|tXt%cy zaPg(PqNxef6;(B#+?U|(Yl_CB=>>|$)_xXYU7I3fNuu2;B1NMu8bRej(o|(p1&vXp zYwOwsGu9%Ld@?)5BEL5qZ&84X{4`NfS>C0Kl1Y1u_%%oqs7hAUS`?&Wnblh~)SI1Z z(J(6Z(=uO zFHSNeF~?2{(L#&Pq(yK(BDN?N1JBxm5HCr@VooF-O~f1P&KL3}7A>V^iUQHJleE)` zq@s%2x`GwqEWELpmQ&bID`0P4gB;eP&(S|1jB#gkTG5Cc2RCI~Hf)5*Mn9dM^K@Y* zixMpst)z3IL?jVU+sI@^55!ipTAE08n-scDa9#wg5n-{*qHF0o$&Onrx|MFrM}LN*&;1|KKY1n%)Tb48ygi0PrEOQs%y?XlTC3NGTW5-?Hc~ar-cjRcoRn zy~=^t1ov%=?xA}XReHEpPER74UK;I;rtMfbj$N0|AV6kq_jQ8 zVAkoJlSoH9wgjn}zH8C<=s{#R&i0Jcf-PBrm=xqs?kE@y<(3u+S5}Q{=lN^>1v_91Jy`+`N`nUUP0KUnm~fDs1|6Y&HeBg$#@kwt%#4U>(HAaizpV$qR; zy(FjsLyuY1FM@N1#v^uaol=%!!R6!$F1Jt_mNLad!?Vf=(o;F0{5XGCIT0s{ZnP$a zt?M2O&NP&ARb;84TeRB);7>u>*&Z6lkQ!>KVWKK}93+olp$8l376#0m#Kl~YKLra`+rdrDxD z8f~dcRVA%e4>BAF-_#QvFohLjkZz5_qS{hpRSl{^I+2q%xLL}I3#f4jTkc*`<0O-b zq_TnZq#yCgPAd)inRM&78&mZ}w}j>snCKs9boq;QHGcCr&^ zhYT~Z-{YBXxj_KX?iPSxmz`|iWG9_4ykKoeB+{{j4gbq$up^r6&f$DrI6R%CpNibD zW|9%-tf=(N?wOvmZ<>TtPJSHk$t5v6m2x0!Snf8q!aIK8kQ~IjiBSzIt;W@^h*<6h zn6cap+!6NzcSPS0D$AV@0Uq7|pl{p(27RO3ANVc>J$nB9cS(udPQXiKRM1FZMqzdv zv|x;_^;7mysQv&|*6V##Ew7sTk~0ql_R+ZdhiSsP12kzLP0mm2^3y4pP6a{3KAN7N z&U^rDnNGudk{HCZsEALap*)+)cn($aT$;pZ&d+T2Kt?&>TA5U5~TK zQ&mj@H*wjO^$*hYJ~{(OIVO1O`e*^uTFhqVz%%hNWdICn+-945X$oLxDLPEeXAAYI zeRK}fE*b&wDwmyr)_@lPYZdM8e^%Hx*9*6OR3|=~B4!z`S@RGP;)O8lOd83HsD>BQ zG+s)Lyo{FdS+t7L)$ts}4ZtCfju0*?%O`^f9Uk8802@F%ZlLc#nn|GNi!q^t z)QMr7me(WusavA`Al2MPLmnn)U1{n7Wgc}Cp_hg>mu@cIdXPT9cFLmdgSb^rpn>ezpbhA9!T=EtH4U)^;FC@ z4dVzR)Q+UmItGgT(~YZlYBi>E zZ~uFe9G>V>q2i5X@})EcV>x#h1id0FR)TuHD^_M-cFTcm-0gsAH?a8O=LnfNWR!H> zcw^TV4+pxK$lL+x|59HP+)p>*XgL&^XNo%On(hW}GE|X&WAI#!=UrsODIOf$NVVdb zif5$<6MA{nhj`kc`e8gf@LUXwF2wi_#<_T|$AcfG^il9zglBzzy|EMD_u=^+U}d68 zN%(ezOeQV2Q+W-hlb_~eq=I`#1FXRse z`sf=5_4XG7h%#`eyNQwAyZfkDQSY($L{d|BMWwm5(%5DodyHN(bRXTVLGsLJlH4aG z_x2vUyZ2bH5H0{O6bA^>bBcOtq0F?;)81N0!UUhSC|?4?se z!Cdv3SCmyLRJ5NSf+pYBBv`lRya*f$87kIit}>2W)qBi`g>b@QMGK%DJ|<@sh42~W zL4VI~DiU2ioXpJ4v8)bym54otZb6k{47DG zZyS7DRpQ&cy^o#{nk!ryJqMCYLS}hTKCw%Lab?NEZN~b&{cq$Jm-x1Nu#nkDPa>K} z=ew)1o40SpA59r0Ew{+`ME&cgz{ASyJc2EkC5p}?xSCr)O+M{SFXHH zXxXn|*^#{`)$K)Sa%4xLZod&o&q){jPSEETE_hWS3-el3p`h)dsuS8&wYUH6{MssU z-k;#SBa~mBN9V)yI*j<_C66ZS#zA}Hf1tuAhd#}tsw5!MeMiu@g-k6JH?9tuhBwKI zGDVH|MZ^}Dg}2{Iv)DfR5S#Loiw8bGmd_TC(u;OQPUn(g2=`Hu)=&t-?_mH{c}tKv zbBuChH~IW?jQVmTWai65B^U^#Pic7NOHJV zfG9nnMpPbD<@;4=zZwIoc|lo<&3jOdUmFTOI#0HlTVm8CMRFnzH&bRRcOvplbSJ9i zWn^%Yg1m`_^H#c*KTr4Z7w9l=qsRD4dIIBfqkMdwD&p%^DSug2^9|}0zDZ5uuc+z#Rn>%X5r0iB<(pNQcd1t1tuDdX&bO#e z-lI119jcqZsgm5QuHbK}tN1Q;6UJNk+iDNrqx$$>^%TbE_ke}@&{&&B**9?JW8 z6z}IsKEMn*v0%PNBJ;!V@&c7IKz+eR(_nXvjB^j_~XHQj9(PhEDNc^k#lb zZ|Ar54g8M2iQm0y?zcE|~j1jun2x-fx)x{?ssm7Cfs`0FzX1t;s zj6dk<#$WYJ<0C!WII8EETAywP^jx!8&oj$(qd8eOne}?1IZK~uF3?NO6?&Q3tj{vr z^m6kejO+33=oMy<4x1_6Y-aS?=2hD3HjhvUr}B<$<1x~_P}ND}fovSD>M>(oO7pX` zbpx=MX|@M5s&g=71C@I)m84tM6lqm>6kX)aOih#Bmd3!oxJ;djmd3=-EN7tCC<5j4 zG)qmx%ug@TRMmi4Ky5>hA`MTG>Z4N3F2?Mw+>9&nqxf{e@?=~Igf7T?snVP2@`2fF zXrNrI>7Z+t?lNd*aGj8uPg*JUA}#30mB{DEp2a`EnnC!r;5ru|5En4MXu-&SxJsyU zK=$L>*$;|BpcbI=|9@zi`_bD4UCy|gihNO}tRL4g{5c2ma!~kZIa;@oWBOr1p;Rbb zc^s{%Y1Q;o)nLN${e%l-ffb%GtDhzgCafL`wcNiaDPiTQC3=ArDN@K`JZN3=3Xk*g z~V5=0aeQ3sJZ` d;LoEo@yTkIk{hR7fA>(An(hA8txL@z`d`%34!-~Z literal 7287 zcmb7J3w%`Nl|SG4?mRNNkQWmfl0XEMB#68uViLk52n-tu<&C(?Wpa~@PG-`{L>^Uq z(rVY1)xH$!3dNGGwXRlqL?}|*YL~WKYqwe-wcVE5^- z?s=c{o$q|-n;bj!_z@zSrfPk}ifW^YXkv0Kx?ys(yC*g|+!k(InoOh;kwk2KI37uK zN8_CrV8yLiqH{sg>b93g<3hmez+)!u?!>irdj?k2>L}_6jipK-DNO&o1*b(s#(#P znvWu^U8TrqNwnJqr05)zN~knInnEU((I`c_rgoKJDoyf`S7xJ4^0~8Wll)X5u(2iu zsL)5_6_w=tU1ark!RG*tqw_`F1Zb)WyYgyHGHICbPBf{QhAAp)jmGUIecc=E8NDk~Y4?+nlo_rdiMK7DAtCFUK`c>8=ima-IiYSzJqLYhu9d~}hbVL5|g ztV#9awkHy^tz>{^QiG2!$$FK)FeWuplOi8dq|a{aP*e`r&ai%>sM)01GzY=NIw}g* z#XwA#)tX)_LU!*UYwBsNs%L_s_*WvEaCEwhWUG_6Y z;cVMw*z%MWx#lvf$4MC<6+&-EG!~oJhh+*}x+!A!q@syK#(m;iN9 zmybFXjXL`lGbu_}BYIXOV)r^5a{5PaG}mF#6z}OvEl;7`bTwR>cQ|{W6iD>&|Cl6Z_ohGfJt%@e(Cv!$Y z-pXcGqA)7#=wL1exo9IT{NkY0S*PHH11Jl(nq)~Lstwq_Su`@tTN7S4uXdG?+-}lM zbTh)!8{GmpF-63rO9X_8BJ~W)8|mk=2`94 zc5ey=CfeIoopBt=QQd8IMkB)e1(QBWpOTdLl1X>dJ-H>Hs%Y`wS@N@|&tQ>SWX0QK zDD;K2lkWA=mlf6h<6I{F8{LOw=yHTynsubbT|oGO;2~?|ztp^)wA-YwNLY(pj^&At z)G`}U5#0SIeU0mCr$c}pfbS}Wi8l)j&I*H=_z^|$BQd_c~8_8?RP|H z4ERrzj)}GB3=$1BR+RkEq#ucroS>}wADi?{o@G!msQp=!ewxP=o)*b6{mi82@|b`b zWcs;DFGx5t?f`|<=!-eI@sdd|=UM9D^1~{YzGBiZ=~w6#TyI*s?8r4z+LIkt#D=II z)LiUSqb8F-zc%SNVoGMM!jaw{*ZpOgwGyGfHR)CQ6bg_l)FsMV^}i;)CfS@>8$o9M ze8Z$S^AcT9gO0vs(jP=|*3o#x8sz(vNpA}-t50x)jPIKCXNgcr#u!1mCj06CaOf?w zBX$(cUv)3`l~a%H3#Eqs#iYMVwN&kXI*Bt#ww;TX`hUu#w3v#f1Igo43JKwyO3sPx zme6^9(OA2k^ec^qZct5M?hHVO+l?a7P(5W+KoOzqnyI{|@+m*cUMjK3Mogvr%b75w zQOT5OFsXp43YCdUYV{z)apFumLv_z@a)#K}C?bZNsz?=MpQjR8eM1|Nj5@z6#j<5P z^lCeqOrYKRgc@Pe4JxRp=?t1rKUeY~=;9L_rB7_E4I^*VIi?yZK^>7v#=(l%n&?IQ zVOYsd)NdK4VZX=wy4?oGXm<)gpvy|OZ?uwj7*Q}cBoe7u!b1GzGtd!Dc4u(~XnhtW zlHC?$db@Cn$pPebnnLs!137d8LLRn)uhjG{@TVhskuZ{9rl)bDh za?b@sDGPBgDpZZas&VtdwMTk#%vd^dXGA~ljOfOl5j{4jhdc8k(4o`LeHRx?w-21~ zmeB}cf|zY51C&Iw>L%`^^11^wvQF=#3VBu470)^B-$!HW^x?ohI=Ai+jayq>e1Oi| zM>Y8$b&o&*(*<~6D5mgaD&Q$JoTpM5PooOHh{o~^8i!{B*VAOan5N*lh-cCy@R%?K z27q_6BL|0wYn<8)sbcQ^b&pZa0B(PTNnLhw?%D>=k$OWn_fsh3sk(5MP*onJiw9^H z)9PEbstOvr)4!W|2D-X4(78(HD!QznCSEW=mnu3+Gna_UNdxpxO!v?TfS0&d0Q50v z0bseJ9qDH!28I)ZW-3Aq8WDpgD&<*pJ~zYHSuko2E#bLz1xA}&D9Q8bI=+-{=LNK# z7t#*E_V8jSCe5zjnV28~v>K6BbUv1M4RB0L24@Mnh}P2OfL%wUX&qgGg!yM!BXM%WyX-6$2(!Zc8F#eZ0iK3n0pn9AnkCHA8 zO)}ot`q-#m6bSNI(Egda;=q2|UZUu*zriEstZjM#IN5#juL{pLJZ~c#kN^T#SVgrM z&v-lwU6{Zf-0Of{2Ge)riQt(Hk7i+f7Gnrc9M64tUV*%^c;@E#4IAIv@jQv=T`{FN zyo*LVleS$H%tA~Ta$hFf?viXP_QQOy^Y%G!e_gRZB0Pd(ay>R};l zt~wlODA4tRekuwT1OozVyEUMKfvVlsC>?Pq29iJ*J(8U9-!SLUp!M8&#~D$nRs{_-{%L_DgFj4ewcmy2nYC^T*QxZkRRhp z-p6D408itCJQJ|F{5ZGrAzp%UIUnX#`~oW6e$3zEXZU;k6Mmk5%CGXz_%;4Hzr`=`JNzR5gQ;;&<5%?xeoe3C*R{oO=wAN4zM21^xAEKh z)BKLUi{I7v^LzSHeqZnB6Z#OJ)JORP{WPD_KjO509^$kPmf7V|8SMAej?KcW^ zfl-37TnCJh9%hWz!;N}fWL%<4jb>eDwCEAWN*y%T=#hq{L&nv5l(AV?7}x31#!Y&R zaht9-zNE(*d-Ql?ubyChUDp_o>RRI|J<)hhPcmN6Q;b*iRO7gwX1u1S8*l0v#=E-S z7z6w1Cv{Z0&xK23Yv$f3E|2E!sDGP4T^jq zdg`6%vj0D{%xT;o@aGk%!(CPMBRK1!yHLcKA4UMV0R7oHRno)f>xS87G;9dD)AmD> zITDLElz3bk-Ly-caT0nZ24g194Vt^iUxsX@>I#dnO-vDa|yWao+ diff --git a/IOIOLib/bin/classes/ioio/lib/impl/IOIOProtocol$PwmScale.class b/IOIOLib/bin/classes/ioio/lib/impl/IOIOProtocol$PwmScale.class index 5a0471bc869379e3e1f69b3f38102153e060f9f1..68729c1ed5f4c321b3ebee345a14ca3e838b49c1 100644 GIT binary patch delta 41 xcmcb_eTjQR7Yl0xg9AhTQ1polS3>N?Z delta 41 xcmcb_eTjQR7Yl10g9AhD@o5?Lf+z2E|&O~M<2=q>h zHhIvLqCzNS9$_Ap!g!UM&LnndsX2=FhuJYx-(NNg?eyEJW(8+^?uIA2phLIn4ldR1 z;lI7mqZelMsfdtD<0o*(ent;q3=UE`#OzP0_Oth4wJ&6W_9%&CB#uLi&y}BXq4oqL zC+TE>9tKspvBq%*9ykkcoFj9V-M(g}^9aHPgyAB>xlY6-B;c~rhQ6x1!u%mtyh`Fb zgyMU(HMCQIozb6I^=Izt26Jw5*0iYHxqmiDq2{?R~@nY2Ml5~SPxd5;tg=)DT4RI&83Fz2F+=lQFcqJ-jC^H znLdu`df3DOhxn@&i&;*oJ(k0c5b8$ip)4DQC@~>U%$Ot=OcyJj;hH8kES7N9ZoOlS zBpn4$iH25U5F``mJ{oqJ$jn&PG5(q@5pI%1;t6=mBO^>vZa%dI)E3fp3dYJJ<+PXS(izQQbTP+}Nxv?R z;ftiD7%f?hW|PZdw`}^#B9TWT9}!Z3L|KL@Qi$1H7f2COrC1$|7<81wM=B5~<#bR< z2UVO;HIigG$!a7^4dzQN7D-)im%~H!^=$t#8?A(&G_cVtOk1S}B3J4gsk}yIHSNBR zXjy|;c|*CPZX27ZG*ejzqqHDWS~=PlnrXufd0XX1_v+svv7W>R=%gJ6*+~1FRAfwv zelwLVRJO9}HiSqANBF+l6?5OY1HRJ9$WBIfAzXH|Ul$E`({LA3t5f#Z=*X=$ctGltcSS=MxX!kMN&{A2e!zxVlk-ut}wJ@!{DtLSw1 zviX)*7Z=u!t*M?>Ue-`wD)5NUn39oU&l7l;)HD=Tmd>oLFD>qJdPVt4nvM(ku(2ND z03L=vW+E5`FryGrC_*fX;Xnz7qZFx_h0!QOI$prjC`TqLkb@U78I@F3kx|XB8q}c{ z^Z5S~>d}PRSdKYpLjx3Zv4%)H=A(m(xvc2M-#kEs*O>V_JL{w72IqZKiz3&WZV~x`NIyHhjS&3EJ^D%gqgpI?i2Oq2 zE~CG))?HZf8*I3T1pKc1qMCy77b$4m z@Hg+pI)_=E&hU}$7$hFl4W`Z$LE?oF@gCT!;QI=0XET-5;w0Q599$22b*eST9mAQmJ^1V&0E9+N0M%QaW5m?SaU6Vq?8 zksS|DvBO6k2$KYMV24c-sdVavVb@}l;3h6IlHn^UFi9$g%1D^y5%xQZwbS5~(Rw+y z)%XN+jbY_$#b z&euD(W2sZ&F4GvDPVNj=oKA1k$S5GA5b;uk6e&iUl;A0@<7F0dq)czepR`wEh*Tj| zD(Rw{E^0WVTBJ%HnYGA}dW@6V$d)->SM45Rn#c01G4{@@U^|sOQb{gJ>EZKoPc^}hc zCkmw#WwHxZ(uDNkC{;3qn)`BFP_9unJo+1A% z`RB<0g8cIj;;X~;Xv~*nensX*wt4A)EWiJ<=4ztFs@q*5F_+1`LhiTZUVR{UqQ312 z)O)T(<8^ZT$h|=aH|gMeb`$I+lLoGh$mD^f^OHk-c+-V9UHX~ywzenN#b)#RF6XP# q%vYfWLk$xUW5`9kVIrJ{Jh%+`7-g8G$thDLQ`=HpJhVqr7XAbEHATh% diff --git a/IOIOLib/bin/classes/ioio/lib/impl/IcspMasterImpl.class b/IOIOLib/bin/classes/ioio/lib/impl/IcspMasterImpl.class index 5434699e3a03edf7d6a44c55732db2cad548bec2..bf946419113860014aded02dad4eaf360d7fd51d 100644 GIT binary patch delta 32 ncmca7bx&%;YEDMJ$!j=!fTSf?FC+it<6M^+O*hZxKFkOJz>*6@ delta 32 ncmca7bx&%;YEDMM$!j=!fTSf?FQd@p<6M^+EjG{QKFkOJ!A1*E diff --git a/IOIOLib/bin/classes/ioio/lib/impl/IncomingState$ConnectionState.class b/IOIOLib/bin/classes/ioio/lib/impl/IncomingState$ConnectionState.class index 9cfeb3f7d8a35f7b5cede5c166d9562b6d6feb83..84230af14b2bc886bf2ad20ee458a80f18e56a27 100644 GIT binary patch delta 23 fcmX@jb((8KA`7bygCm3Xo_DPoBXV!RyAr&fw0#!{EUn r#^5#iFKarlFM||=AA=%;KZ6=W;N(KKOwJGnQHD?kb%wCXkJ;P-aKRGM delta 87 zcmZ3*w~BAW7ZygF$zNH5IBgg>8EhFu80;nousX9kGH^3EO`gFT!RyMv&fvzt!{E*! r#^5>mFKarl4}%ngFM}e3AA=f0z~n-du-EH7(L(GyLM07K_3%3x^CUpjcqUn2zxWx94idQ=%#|C%({)t@mMhd#iAgJ z!HB!TOqme~*$@SRAukn-Molnki1>_AF&IVvVUb`kD4vdBU?HYy&-u>peBXEPcki!# z4ZV%=r~f%|5O~cYd1 zYq@cuU;>44Ixpo1$sJ4>?UTsUFk&r|@Ca;p6fUfT7mp!}-)uyXN1TB5n1;tujVCY{ z8?X?YaW9@hJ28wcSc7Nr6j9?j^kOUeiHFdGqf|a1p20SJi5GC5c#)1A-hgt%@^=UU zJve5-)&~P#h6#PJ;uVa=4rE}LUT)i(-j8?;AQ^jLA&$XoaAGe!*vD1vM==g)w|z;{ zVdlTd{KL#Ys<+tv>IC!N>hU`CC3}TB$>3BpXmC`h_ZYk%4fZnlkikdMKsn3QX_)b` zu66p=r<6bI@w)Xf=d8HTIiRx`g)ek$YIEE-eDp0x^_}h-=g{j?`+ev5{3j&f97c1C zx%e3qiPP~5X5v@W-~wh78}a*~|BiI2x=7m)9Gt{>{DC4|!c<~8E@M9a^F}9SV>n7$q4= zG71*4AXQTISFUtD##OBx%ya5RuF_llF8b5xA5XuVeh>XYmCZgmx-4yp%14|O=$&cx zYBE`|9wM7gHbYm9uU8dhmHK(IS!6Z(99cb?Ur%z^srfKTqmH;MR5Mu%nN5G~-krY~ ziE=-jvILnDM4>E2wX|XZd9yr#MG``*Jcu^(mC~+XP2Z>ek2Adym>K_k2K;T-W(%wilKY} zIk|^XnCCh!1u=M6ijTXvTbWe;=c=UUqiRCTRd&dPNR<|k zO`p$nsF%3^?LA(f%+y=GHeKO$svSJDojfy#>jLXWd-4B=ELu4cKk}j)SfZN#eAQ3y zz_54o|9J1xE7NQ`A09>1o+%wRh7KBXu&HID`9DQZI92lqQYLQ2F#02{K#PXX zR_JSsCc|thWjP}pE*i92w&m7`)%uwKNICl+RI}N1+T)pjw6z=eJiqsS-uHg*^ZpoE zHMrb<_WJlFfC^bMVt?9^Y%N&Vw5}=CBCvFB?da0;&Jttk+Pb4nttq>uM*CA5EfGP9 zzAQf7X?3b`MJ$biVg@p`#_G^6*QXL1ZA=YGPaiDUjwI}W8;`?>Col(3BFMjdbfbt^ zj2_I#PBdZ{?#5HN7rU_*d(cjN6nk0yEc%Fw=P-chag6vD_Te=4;|%c}4&W=ifQ!T# zyodsh5p7&IH{{W_a}|A{uJv+SwE&9c$S&BSvRhoUXK=g>&ygClRUMU_sHIl#=m3y3{M|M zPqpc_<|D-8toEcYGaobliGG&eX8WA(e1T+qsgaCU+c%7VOP|i`P{u^)0&`PHzy-MQ zJqkHr8L=9dun<3B34X*<;wt<++B-WS4bzm(z=LV{@dqmKCn|{%T*gZLMN=ipCNs0(P7zupA-8~GZ^_viutU8Wc|3G0-< z*;J6t)$;6SQ$<#-yT~GBb$X6$5!qr51e(oKvS!^DXfi8cm6iH#pw6_AwUW8jn{y<* z9*MF6Ubzo>vJs{702<{%+(X_fo3LIsW0SOD3;8zLqCe&InulPQhq506E=|ze>qceH!vRBv43HJ!H_~^R%Sm+Uav5{e< z7M?h%APm46Mc)_6ad+g+1mPyEq_Hq7Auj-5B(k0S@vKUs|>f25nNR$AV!qMEeg# z?Vk?XU1jVL!}>(NvnloxDc8jOusK52QK|y}qo~jkzgzqA)68+M;&m?1W81?%!s@xv z+}F&#$=t}zT*B?#Jh?+t3qrmzW==<^%;qnGum1Lwb}7@f1uHtndGB{?m7=1Uc^h87s9mOJBYSk8+qsP{@Ou`Vti<-~ewUL`if#mhqCBF4kS G#lSz%U=>mT diff --git a/IOIOLib/bin/classes/ioio/lib/impl/PinFunctionMap.class b/IOIOLib/bin/classes/ioio/lib/impl/PinFunctionMap.class index f8485074aeb1120799b706509498e6af3ef35ce4..3af9e48749fdb2daa757f3b96ba95a1d21aed7ac 100644 GIT binary patch delta 14 VcmZ3&w}fxQQx-5} diff --git a/IOIOLib/bin/classes/ioio/lib/impl/SocketIOIOConnection.class b/IOIOLib/bin/classes/ioio/lib/impl/SocketIOIOConnection.class index 0ff06801939a6d731a39da0ac369a434855eb959..f2b841737e3ed78bf169fe2665cd58d68e49edb0 100644 GIT binary patch delta 53 zcmdlWwn1#eHV(lV48aU@7(y79GK4d1W{70iwfQ)QDx;t>Lji+2Lm`6!LkWX9Lm7kJ J=D(cAi~yZ=4haAN delta 53 zcmdlWwn1#eHV(nr48aU@7(y79GK4d1W{70iyZJbWDx;tpLji+2Lm`6!LkWX9Lm7kP J=D(cAi~yde4ix|Z diff --git a/IOIOLib/bin/classes/ioio/lib/impl/SpiMasterImpl.class b/IOIOLib/bin/classes/ioio/lib/impl/SpiMasterImpl.class index 73d8977dcfbf1c53699907f071717ff76d0d9313..8cfa80f0384be2666c71322d0a444797cc161c47 100644 GIT binary patch delta 20 ccmbQQJ70H$st{x0W;LN%%#7-j4~pIc07jMu=>Px# delta 20 ccmbQQJ70H$st{wzW;LN%%#2!-4~pIc07l6M?*IS* diff --git a/IOIOLib/bin/classes/ioio/lib/impl/TwiMasterImpl.class b/IOIOLib/bin/classes/ioio/lib/impl/TwiMasterImpl.class index 47c7a4ad7e375c88f6523cfe0df950490a1ed513..4a84fb46cc063719b9a93960e5d08fb01d7e285a 100644 GIT binary patch delta 127 zcmX@3azSOoLq5ik$&dK9aWOJ8umT|igU{qe{JP9SGV>;%<5%Q%VQ>eExife%xKIAY zuV`t+(92-U(9ht=(8=J$_;t1Uw3&6cFsx*j*}GdB+KFD z4D3L1|3(HT1|bFq24|pJX9hP0=gI&06)p7`dKoMk`Wb8)IvLyFg diff --git a/IOIOLib/bin/classes/ioio/lib/impl/UartImpl.class b/IOIOLib/bin/classes/ioio/lib/impl/UartImpl.class index b210d3c168e3f7e3f8addd4f8e53d513ef76f8c0..1be0403df8bb14945f24b84a5433578427ff015d 100644 GIT binary patch delta 14 Vcmew;@=;`iBL}0vW+x7PCIBfn1VaD- delta 14 Vcmew;@=;`iBL}1KW+x7PCIBf(1V#V= diff --git a/IOIOLib/bin/classes/ioio/lib/util/AbstractIOIOActivity$IOIOThread.class b/IOIOLib/bin/classes/ioio/lib/util/AbstractIOIOActivity$IOIOThread.class index 8c1116b42bc23c302199738391043d6fefb0cc8e..bfcf152abd07f6ecbb40689e8f0b9f7a36bab49c 100644 GIT binary patch delta 52 zcmV-40L%Zt9l#y1$_oiu0Vx1o0X6_;lhX?)0il!o3o8NOlP3%-0VI=C3?~6rlY0y! K0fw`m3?Txrs}FDh delta 52 zcmV-40L%Zt9l#y1$_oix0Vx1o0X6_>lhX?)0i=`r3o8NRlP3%-0Vk7F3?~6ulY0y! K0g1Dp3?TxtsSkw! diff --git a/IOIOLib/bin/classes/ioio/lib/util/AbstractIOIOActivity.class b/IOIOLib/bin/classes/ioio/lib/util/AbstractIOIOActivity.class index 5c9ac82f08d46b58d2a338a57ddea08d54e1b898..a3fb0be90c83382df525ecf0d1af8bd2a5c572fa 100644 GIT binary patch delta 21 ccmZosYf;;f$ITeKIiLFh6C=mw0KP3O08VHIy#N3J delta 21 ccmZosYf;;f$ITeJIiLFh6C?NL0KP3O08SDHxBvhE diff --git a/IOIOLib/project.properties b/IOIOLib/project.properties index f28bc83..0e58ae1 100644 --- a/IOIOLib/project.properties +++ b/IOIOLib/project.properties @@ -9,4 +9,4 @@ android.library=true # Project target. -target=android-15 +target=android-17 diff --git a/IOIOLib/src/ioio/lib/api/DigitalInput.java b/IOIOLib/src/ioio/lib/api/DigitalInput.java index f773d88..76d58c8 100644 --- a/IOIOLib/src/ioio/lib/api/DigitalInput.java +++ b/IOIOLib/src/ioio/lib/api/DigitalInput.java @@ -1,140 +1,140 @@ -/* - * Copyright 2011 Ytai Ben-Tsvi. All rights reserved. - * - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARSHAN POURSOHI OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied. - */ -package ioio.lib.api; - -import ioio.lib.api.exception.ConnectionLostException; - -/** - * A pin used for digital input. - *

- * A digital input pin can be used to read logic-level signals. DigitalInput - * instances are obtained by calling {@link IOIO#openDigitalInput(DigitalInput.Spec)}. - *

- * The value of the pin is obtained by calling {@link #read()}. It is also - * possible for the client to block until a certain level is sensed, by using - * {@link #waitForValue(boolean)}. - *

- * The instance is alive since its creation. The first {@link #read()} call - * block for a few milliseconds until the initial value is updated. If the - * connection with the IOIO drops at any point, the instance transitions to a - * disconnected state, in which every attempt to use the pin (except - * {@link #close()}) will throw a {@link ConnectionLostException}. Whenever - * {@link #close()} is invoked the instance may no longer be used. Any resources - * associated with it are freed and can be reused. - *

- * Typical usage: - * - *

- * DigitalInput button = ioio.openDigitalInput(10);  // used an external pull-up
- * button.waitForValue(false);  // wait for press
- * ...
- * button.close();  // pin 10 can now be used for something else.
- * 
- */ -public interface DigitalInput extends Closeable { - /** - * A digital input pin specification, used when opening digital inputs. - */ - static public class Spec { - /** Input pin mode. */ - public enum Mode { - /** - * Pin is floating. When the pin is left disconnected the value - * sensed is undefined. Use this mode when an external pull-up or - * pull-down resistor is used or when interfacing push-pull type - * logic circuits. - */ - FLOATING, - /** - * Internal pull-up resistor is used. When the pin is left - * disconnected, a logical "HIGH" (true) will be sensed. This is - * useful for interfacing with open drain circuits or for - * interacting with a switch connected between the pin and ground. - */ - PULL_UP, - /** - * Internal pull-down resistor is used. When the pin is left - * disconnected, a logical "LOW" (false) will be sensed. This is - * useful for interacting with a switch connected between the pin - * and Vdd. - */ - PULL_DOWN - } - - /** The pin number, as labeled on the board. */ - public int pin; - /** The pin mode. */ - public Mode mode; - - /** - * Constructor. - * - * @param pin - * Pin number, as labeled on the board. - * @param mode - * Pin mode. - */ - public Spec(int pin, Mode mode) { - this.pin = pin; - this.mode = mode; - } - - /** Shorthand for Spec(pin, Mode.FLOATING). */ - public Spec(int pin) { - this(pin, Mode.FLOATING); - } - } - - /** - * Read the value sensed on the pin. May block for a few milliseconds if - * called right after creation of the instance. If this is a problem, the - * calling thread may be interrupted. - * - * @return True for logical "HIGH", false for logical "LOW". - * @throws InterruptedException - * The calling thread has been interrupted. - * @throws ConnectionLostException - * The connection with the IOIO has been lost. - */ - public boolean read() throws InterruptedException, ConnectionLostException; - - /** - * Block until a desired logical level is sensed. The calling thread can be - * interrupted for aborting this operation. - * - * @param value - * The desired logical level. true for "HIGH", false for "LOW". - * @throws InterruptedException - * The calling thread has been interrupted. - * @throws ConnectionLostException - * The connection with the IOIO has been lost. - */ - public void waitForValue(boolean value) throws InterruptedException, - ConnectionLostException; -} +/* + * Copyright 2011 Ytai Ben-Tsvi. All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARSHAN POURSOHI OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied. + */ +package ioio.lib.api; + +import ioio.lib.api.exception.ConnectionLostException; + +/** + * A pin used for digital input. + *

+ * A digital input pin can be used to read logic-level signals. DigitalInput + * instances are obtained by calling {@link IOIO#openDigitalInput(DigitalInput.Spec)}. + *

+ * The value of the pin is obtained by calling {@link #read()}. It is also + * possible for the client to block until a certain level is sensed, by using + * {@link #waitForValue(boolean)}. + *

+ * The instance is alive since its creation. The first {@link #read()} call + * block for a few milliseconds until the initial value is updated. If the + * connection with the IOIO drops at any point, the instance transitions to a + * disconnected state, in which every attempt to use the pin (except + * {@link #close()}) will throw a {@link ConnectionLostException}. Whenever + * {@link #close()} is invoked the instance may no longer be used. Any resources + * associated with it are freed and can be reused. + *

+ * Typical usage: + * + *

+ * DigitalInput button = ioio.openDigitalInput(10);  // used an external pull-up
+ * button.waitForValue(false);  // wait for press
+ * ...
+ * button.close();  // pin 10 can now be used for something else.
+ * 
+ */ +public interface DigitalInput extends Closeable { + /** + * A digital input pin specification, used when opening digital inputs. + */ + static public class Spec { + /** Input pin mode. */ + public enum Mode { + /** + * Pin is floating. When the pin is left disconnected the value + * sensed is undefined. Use this mode when an external pull-up or + * pull-down resistor is used or when interfacing push-pull type + * logic circuits. + */ + FLOATING, + /** + * Internal pull-up resistor is used. When the pin is left + * disconnected, a logical "HIGH" (true) will be sensed. This is + * useful for interfacing with open drain circuits or for + * interacting with a switch connected between the pin and ground. + */ + PULL_UP, + /** + * Internal pull-down resistor is used. When the pin is left + * disconnected, a logical "LOW" (false) will be sensed. This is + * useful for interacting with a switch connected between the pin + * and Vdd. + */ + PULL_DOWN + } + + /** The pin number, as labeled on the board. */ + public int pin; + /** The pin mode. */ + public Mode mode; + + /** + * Constructor. + * + * @param pin + * Pin number, as labeled on the board. + * @param mode + * Pin mode. + */ + public Spec(int pin, Mode mode) { + this.pin = pin; + this.mode = mode; + } + + /** Shorthand for Spec(pin, Mode.FLOATING). */ + public Spec(int pin) { + this(pin, Mode.FLOATING); + } + } + + /** + * Read the value sensed on the pin. May block for a few milliseconds if + * called right after creation of the instance. If this is a problem, the + * calling thread may be interrupted. + * + * @return True for logical "HIGH", false for logical "LOW". + * @throws InterruptedException + * The calling thread has been interrupted. + * @throws ConnectionLostException + * The connection with the IOIO has been lost. + */ + public boolean read() throws InterruptedException, ConnectionLostException; + + /** + * Block until a desired logical level is sensed. The calling thread can be + * interrupted for aborting this operation. + * + * @param value + * The desired logical level. true for "HIGH", false for "LOW". + * @throws InterruptedException + * The calling thread has been interrupted. + * @throws ConnectionLostException + * The connection with the IOIO has been lost. + */ + public void waitForValue(boolean value) throws InterruptedException, + ConnectionLostException; +} diff --git a/IOIOLib/src/ioio/lib/api/DigitalOutput.java b/IOIOLib/src/ioio/lib/api/DigitalOutput.java index 6d6a2a5..ccb8824 100644 --- a/IOIOLib/src/ioio/lib/api/DigitalOutput.java +++ b/IOIOLib/src/ioio/lib/api/DigitalOutput.java @@ -1,120 +1,120 @@ -/* - * Copyright 2011 Ytai Ben-Tsvi. All rights reserved. - * - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARSHAN POURSOHI OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied. - */ -package ioio.lib.api; - -import ioio.lib.api.exception.ConnectionLostException; - -/** - * A pin used for digital output. - *

- * A digital input pin can be used to generate logic-level signals. - * DigitalOutput instances are obtained by calling - * {@link IOIO#openDigitalOutput(DigitalOutput.Spec, boolean)}. - *

- * The value of the pin is set by calling {@link #write(boolean)}. - *

- * The instance is alive since its creation. If the connection with the IOIO - * drops at any point, the instance transitions to a disconnected state, in - * which every attempt to use the pin (except {@link #close()}) will throw a - * {@link ConnectionLostException}. Whenever {@link #close()} is invoked the - * instance may no longer be used. Any resources associated with it are freed - * and can be reused. - *

- * Typical usage: - * - *

- * DigitalOutput led = ioio.openDigitalInput(2);  // LED anode on pin 2.
- * led.write(true);  // turn LED on.
- * ...
- * led.close();  // pin 2 can now be used for something else.
- * 
- */ -public interface DigitalOutput extends Closeable { - /** - * A digital output pin specification, used when opening digital outputs. - */ - public static class Spec { - /** Output pin mode. */ - public enum Mode { - /** - * Pin operates in push-pull mode, i.e. a logical "HIGH" is - * represented by a voltage of Vdd on the pin and a logical "LOW" by - * a voltage of 0 (ground). - */ - NORMAL, - /** - * Pin operates in open-drain mode, i.e. a logical "HIGH" is - * represented by a high impedance on the pin (as if it is - * disconnected) and a logical "LOW" by a voltage of 0 (ground). - * This mode is most commonly used for generating 5V logical signal - * on a 3.3V pin: 5V tolerant pins must be used; a pull-up resistor - * is connected between the pin and 5V, and the pin is used in open- - * drain mode. - */ - OPEN_DRAIN, - } - - /** The pin number, as labeled on the board. */ - public int pin; - /** The pin mode. */ - public Mode mode; - - /** - * Constructor. - * - * @param pin - * Pin number, as labeled on the board. - * @param mode - * Pin mode. - */ - public Spec(int pin, Mode mode) { - this.pin = pin; - this.mode = mode; - } - - /** - * Shorthand for Spec(pin, Mode.NORMAL). - * - * @see DigitalOutput.Spec#Spec(int, DigitalOutput.Spec.Mode) - */ - public Spec(int pin) { - this(pin, Mode.NORMAL); - } - } - - /** - * Set the output of the pin. - * - * @param val - * The output. true is logical "HIGH", false is logical "LOW". - * @throws ConnectionLostException - * The connection with the IOIO has been lost. - */ - public void write(boolean val) throws ConnectionLostException; -} +/* + * Copyright 2011 Ytai Ben-Tsvi. All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARSHAN POURSOHI OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied. + */ +package ioio.lib.api; + +import ioio.lib.api.exception.ConnectionLostException; + +/** + * A pin used for digital output. + *

+ * A digital input pin can be used to generate logic-level signals. + * DigitalOutput instances are obtained by calling + * {@link IOIO#openDigitalOutput(DigitalOutput.Spec, boolean)}. + *

+ * The value of the pin is set by calling {@link #write(boolean)}. + *

+ * The instance is alive since its creation. If the connection with the IOIO + * drops at any point, the instance transitions to a disconnected state, in + * which every attempt to use the pin (except {@link #close()}) will throw a + * {@link ConnectionLostException}. Whenever {@link #close()} is invoked the + * instance may no longer be used. Any resources associated with it are freed + * and can be reused. + *

+ * Typical usage: + * + *

+ * DigitalOutput led = ioio.openDigitalInput(2);  // LED anode on pin 2.
+ * led.write(true);  // turn LED on.
+ * ...
+ * led.close();  // pin 2 can now be used for something else.
+ * 
+ */ +public interface DigitalOutput extends Closeable { + /** + * A digital output pin specification, used when opening digital outputs. + */ + public static class Spec { + /** Output pin mode. */ + public enum Mode { + /** + * Pin operates in push-pull mode, i.e. a logical "HIGH" is + * represented by a voltage of Vdd on the pin and a logical "LOW" by + * a voltage of 0 (ground). + */ + NORMAL, + /** + * Pin operates in open-drain mode, i.e. a logical "HIGH" is + * represented by a high impedance on the pin (as if it is + * disconnected) and a logical "LOW" by a voltage of 0 (ground). + * This mode is most commonly used for generating 5V logical signal + * on a 3.3V pin: 5V tolerant pins must be used; a pull-up resistor + * is connected between the pin and 5V, and the pin is used in open- + * drain mode. + */ + OPEN_DRAIN, + } + + /** The pin number, as labeled on the board. */ + public int pin; + /** The pin mode. */ + public Mode mode; + + /** + * Constructor. + * + * @param pin + * Pin number, as labeled on the board. + * @param mode + * Pin mode. + */ + public Spec(int pin, Mode mode) { + this.pin = pin; + this.mode = mode; + } + + /** + * Shorthand for Spec(pin, Mode.NORMAL). + * + * @see DigitalOutput.Spec#Spec(int, DigitalOutput.Spec.Mode) + */ + public Spec(int pin) { + this(pin, Mode.NORMAL); + } + } + + /** + * Set the output of the pin. + * + * @param val + * The output. true is logical "HIGH", false is logical "LOW". + * @throws ConnectionLostException + * The connection with the IOIO has been lost. + */ + public void write(boolean val) throws ConnectionLostException; +} diff --git a/IOIOLib/src/ioio/lib/api/IOIO.java b/IOIOLib/src/ioio/lib/api/IOIO.java index 627e2e7..2f2de6c 100644 --- a/IOIOLib/src/ioio/lib/api/IOIO.java +++ b/IOIOLib/src/ioio/lib/api/IOIO.java @@ -1,696 +1,696 @@ -/* - * Copyright 2011 Ytai Ben-Tsvi. All rights reserved. - * - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARSHAN POURSOHI OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied. - */ -package ioio.lib.api; - -import ioio.lib.api.PulseInput.PulseMode; -import ioio.lib.api.TwiMaster.Rate; -import ioio.lib.api.Uart.Parity; -import ioio.lib.api.Uart.StopBits; -import ioio.lib.api.exception.ConnectionLostException; -import ioio.lib.api.exception.IncompatibilityException; -import ioio.lib.api.exception.OutOfResourceException; - -import java.io.Closeable; - -/** - * This interface provides control over all the IOIO board functions. - *

- * An instance of this interface is typically obtained by using the - * {@link IOIOFactory} class. Initially, a connection should be established, by - * calling {@link #waitForConnect()}. This method will block until the board is - * connected an a connection has been established. - *

- * During the connection process, this library verifies that the IOIO firmware - * is compatible with the required version. If not, {@link #waitForConnect()} - * will throw a {@link IncompatibilityException}, putting the {@link IOIO} - * instance in a "zombie" state: nothing could be done with it except calling - * {@link #disconnect()}, or waiting for the physical connection to drop via - * {@link #waitForDisconnect()}. - *

- * As soon as a connection is established, the IOIO can be used, typically, by - * calling the openXXX() functions to obtain additional interfaces for - * controlling specific function of the board. - *

- * Whenever a connection is lost as a result of physically disconnecting the - * board or as a result of calling {@link #disconnect()}, this instance and all - * the interfaces obtained from it become invalid, and will throw a - * {@link ConnectionLostException} on every operation. Once the connection is - * lost, those instances cannot be recycled, but rather it is required to create - * new ones and wait for a connection again. - *

- * Initially all pins are tri-stated (floating), and all functions are disabled. - * Whenever a connection is lost or dropped, the board will immediately return - * to the this initial state. - *

- * Typical usage: - * - *

- * IOIO ioio = IOIOFactory.create();
- * try {
- *   ioio.waitForConnect();
- *   DigitalOutput out = ioio.openDigitalOutput(10);
- *   out.write(true);
- *   ...
- * } catch (ConnectionLostException e) {
- * } catch (Exception e) {
- *   ioio.disconnect();
- * } finally {
- *   ioio.waitForDisconnect();
- * }
- * 
- * - * @see IOIOFactory#create() - */ -public interface IOIO { - /** An invalid pin number. */ - public static final int INVALID_PIN = -1; - /** The pin number used to designate the on-board 'stat' LED. */ - public static final int LED_PIN = 0; - - /** - * A versioned component in the system. - * - * @see IOIO#getImplVersion(VersionType) - */ - public enum VersionType { - /** Hardware version. */ - HARDWARE_VER, - /** Bootloader version. */ - BOOTLOADER_VER, - /** Application layer firmware version. */ - APP_FIRMWARE_VER, - /** IOIOLib version. */ - IOIOLIB_VER - } - - /** - * A state of a IOIO instance. - */ - public enum State { - /** Connection not yet established. */ - INIT, - /** Connected. */ - CONNECTED, - /** Connection established, incompatible firmware detected. */ - INCOMPATIBLE, - /** Disconnected. Instance is useless. */ - DEAD - } - - /** - * Establishes connection with the IOIO board. - *

- * This method is blocking until connection is established. This method can - * be aborted by calling {@link #disconnect()}. In this case, it will throw - * a {@link ConnectionLostException}. - * - * @throws ConnectionLostException - * An error occurred during connection or disconnect() has been - * called during connection. The instance state is disconnected. - * @throws IncompatibilityException - * An incompatible board firmware of hardware has been detected. - * The instance state is disconnected. - * @see #disconnect() - * @see #waitForDisconnect() - */ - public void waitForConnect() throws ConnectionLostException, - IncompatibilityException; - - /** - * Closes the connection to the board, or aborts a connection process - * started with waitForConnect(). - *

- * Once this method is called, this IOIO instance and all the instances - * obtain from it become invalid and will throw an exception on every - * operation. - *

- * This method is asynchronous, i.e. it returns immediately, but it is not - * guaranteed that all connection-related resources has already been freed - * and can be reused upon return. In cases when this is important, client - * can call {@link #waitForDisconnect()}, which will block until all - * resources have been freed. - */ - public void disconnect(); - - /** - * Blocks until IOIO has been disconnected and all connection-related - * resources have been freed, so that a new connection can be attempted. - * - * @throws InterruptedException - * When interrupt() has been called on this thread. This might - * mean that an immediate attempt to create and connect a new - * IOIO object might fail for resource contention. - * @see #disconnect() - * @see #waitForConnect() - */ - public void waitForDisconnect() throws InterruptedException; - - /** - * Gets the connections state. - * - * @return The connection state. - */ - public State getState(); - - /** - * Resets the entire state (returning to initial state), without dropping - * the connection. - *

- * It is equivalent to calling {@link Closeable#close()} on every interface - * obtained from this instance. A connection must have been established - * prior to calling this method, by invoking {@link #waitForConnect()}. - * - * @throws ConnectionLostException - * Connection was lost before or during the execution of this - * method. - * @see #hardReset() - */ - public void softReset() throws ConnectionLostException; - - /** - * Equivalent to disconnecting and reconnecting the board power supply. - *

- * The connection will be dropped and not reestablished. Full boot sequence - * will take place, so firmware upgrades can be performed. A connection must - * have been established prior to calling this method, by invoking - * {@link #waitForConnect()}. - * - * @throws ConnectionLostException - * Connection was lost before or during the execution of this - * method. - * @see #softReset() - */ - public void hardReset() throws ConnectionLostException; - - /** - * Query the implementation version of the system's components. The - * implementation version uniquely identifies a hardware revision or a - * software build. Returned version IDs are always 8-character long, - * according to the IOIO versioning system: first 4 characters are the - * version authority and last 4 characters are the revision. - * - * @param v - * The component whose version we query. - * @return An 8-character implementation version ID. - * @throws ConnectionLostException - * Connection was lost before or during the execution of this - * method. - */ - public String getImplVersion(VersionType v) throws ConnectionLostException; - - /** - * Open a pin for digital input. - *

- * A digital input pin can be used to read logic-level signals. The pin will - * operate in this mode until close() is invoked on the returned interface. - * It is illegal to open a pin that has already been opened and has not been - * closed. A connection must have been established prior to calling this - * method, by invoking {@link #waitForConnect()}. - * - * @param spec - * Pin specification, consisting of the pin number, as labeled on - * the board, and the mode, which determines whether the pin will - * be floating, pull-up or pull-down. See - * {@link DigitalInput.Spec.Mode} for more information. - * @return Interface of the assigned pin. - * @throws ConnectionLostException - * Connection was lost before or during the execution of this - * method. - * @see DigitalInput - */ - public DigitalInput openDigitalInput(DigitalInput.Spec spec) - throws ConnectionLostException; - - /** - * Shorthand for openDigitalInput(new DigitalInput.Spec(pin)). - * - * @see #openDigitalInput(ioio.lib.api.DigitalInput.Spec) - */ - public DigitalInput openDigitalInput(int pin) - throws ConnectionLostException; - - /** - * Shorthand for openDigitalInput(new DigitalInput.Spec(pin, mode)). - * - * @see #openDigitalInput(ioio.lib.api.DigitalInput.Spec) - */ - public DigitalInput openDigitalInput(int pin, DigitalInput.Spec.Mode mode) - throws ConnectionLostException; - - /** - * Open a pin for digital output. - *

- * A digital output pin can be used to generate logic-level signals. The pin - * will operate in this mode until close() is invoked on the returned - * interface. It is illegal to open a pin that has already been opened and - * has not been closed. A connection must have been established prior to - * calling this method, by invoking {@link #waitForConnect()}. - * - * @param spec - * Pin specification, consisting of the pin number, as labeled on - * the board, and the mode, which determines whether the pin will - * be normal or open-drain. See {@link DigitalOutput.Spec.Mode} - * for more information. - * @param startValue - * The initial logic level this pin will generate as soon at it - * is open. - * @return Interface of the assigned pin. - * @throws ConnectionLostException - * Connection was lost before or during the execution of this - * method. - * @see DigitalOutput - */ - public DigitalOutput openDigitalOutput(DigitalOutput.Spec spec, - boolean startValue) throws ConnectionLostException; - - /** - * Shorthand for openDigitalOutput(new DigitalOutput.Spec(pin, mode), - * startValue). - * - * @see #openDigitalOutput(ioio.lib.api.DigitalOutput.Spec, boolean) - */ - public DigitalOutput openDigitalOutput(int pin, - DigitalOutput.Spec.Mode mode, boolean startValue) - throws ConnectionLostException; - - /** - * Shorthand for openDigitalOutput(new DigitalOutput.Spec(pin), startValue). - * Pin mode will be "normal" (as opposed to "open-drain". - * - * @see #openDigitalOutput(ioio.lib.api.DigitalOutput.Spec, boolean) - */ - public DigitalOutput openDigitalOutput(int pin, boolean startValue) - throws ConnectionLostException; - - /** - * Shorthand for openDigitalOutput(new DigitalOutput.Spec(pin), false). Pin - * mode will be "normal" (as opposed to "open-drain". - * - * @see #openDigitalOutput(ioio.lib.api.DigitalOutput.Spec, boolean) - */ - public DigitalOutput openDigitalOutput(int pin) - throws ConnectionLostException; - - /** - * Open a pin for analog input. - *

- * An analog input pin can be used to measure voltage. Note that not every - * pin can be used as an analog input. See board documentation for the legal - * pins and permitted voltage range. - *

- * The pin will operate in this mode until close() is invoked on the - * returned interface. It is illegal to open a pin that has already been - * opened and has not been closed. A connection must have been established - * prior to calling this method, by invoking {@link #waitForConnect()}. - * - * @param pin - * Pin number, as labeled on the board. - * @return Interface of the assigned pin. - * @throws ConnectionLostException - * Connection was lost before or during the execution of this - * method. - * @see AnalogInput - */ - public AnalogInput openAnalogInput(int pin) throws ConnectionLostException; - - /** - * Open a pin for PWM (Pulse-Width Modulation) output. - *

- * A PWM pin produces a logic-level PWM signal. These signals are typically - * used for simulating analog outputs for controlling the intensity of LEDs, - * the rotation speed of motors, etc. They are also frequently used for - * controlling hobby servo motors. - *

- * Note that not every pin can be used as PWM output. In addition, the total - * number of concurrent PWM modules in use is limited. See board - * documentation for the legal pins and limit on concurrent usage. - *

- * The pin will operate in this mode until close() is invoked on the - * returned interface. It is illegal to open a pin that has already been - * opened and has not been closed. A connection must have been established - * prior to calling this method, by invoking {@link #waitForConnect()}. - * - * @param spec - * Pin specification, consisting of the pin number, as labeled on - * the board, and the mode, which determines whether the pin will - * be normal or open-drain. See {@link DigitalOutput.Spec.Mode} - * for more information. - * @param freqHz - * PWM frequency, in Hertz. - * @return Interface of the assigned pin. - * @throws ConnectionLostException - * Connection was lost before or during the execution of this - * method. - * @throws OutOfResourceException - * This is a runtime exception, so it is not necessary to catch - * it if the client guarantees that the total number of - * concurrent PWM resources is not exceeded. - * @see PwmOutput - */ - public PwmOutput openPwmOutput(DigitalOutput.Spec spec, int freqHz) - throws ConnectionLostException; - - /** - * Shorthand for openPwmOutput(new DigitalOutput.Spec(pin), freqHz). - * - * @see #openPwmOutput(ioio.lib.api.DigitalOutput.Spec, int) - */ - public PwmOutput openPwmOutput(int pin, int freqHz) - throws ConnectionLostException; - - /** - * Open a pin for pulse input. - *

- * The pulse input module is quite flexible. It enables several kinds of - * timing measurements on a digital signal: pulse width measurement - * (positive or negative pulse), and frequency of a periodic signal. - *

- * Note that not every pin can be used as pulse input. In addition, the - * total number of concurrent pulse input modules in use is limited. See - * board documentation for the legal pins and limit on concurrent usage. - *

- * The pin will operate in this mode until close() is invoked on the - * returned interface. It is illegal to open a pin that has already been - * opened and has not been closed. A connection must have been established - * prior to calling this method, by invoking {@link #waitForConnect()}. - * - * @param spec - * Pin specification, consisting of the pin number, as labeled on - * the board, and the mode, which determines whether the pin will - * be floating, pull-up or pull-down. See - * {@link DigitalInput.Spec.Mode} for more information. - * @param rate - * The clock rate to use for timing the signal. A faster clock - * rate will result in better precision but will only be able to - * measure narrow pulses / high frequencies. - * @param mode - * The mode in which to operate. Determines whether the module - * will measure pulse durations or frequency. - * @param doublePrecision - * Whether to open a double-precision pulse input module. Double- - * precision modules enable reading of much longer pulses and - * lower frequencies with high accuracy than single precision - * modules. However, their number is limited, so when possible, - * and if the resources are all needed, use single-precision. For - * more details on the exact spec of single- vs. double- - * precision, see {@link PulseInput}. - * @return An instance of the {@link PulseInput}, which can be used to - * obtain the data. - * @throws ConnectionLostException - * Connection was lost before or during the execution of this - * method. - * @throws OutOfResourceException - * This is a runtime exception, so it is not necessary to catch - * it if the client guarantees that the total number of - * concurrent PWM resources is not exceeded. - * @see PulseInput - */ - public PulseInput openPulseInput(DigitalInput.Spec spec, - PulseInput.ClockRate rate, PulseInput.PulseMode mode, - boolean doublePrecision) throws ConnectionLostException; - - /** - * Shorthand for openPulseInput(new DigitalInput.Spec(pin), rate, mode, - * true), i.e. opens a double-precision, 16MHz pulse input on the given pin - * with the given mode. - * - * @see #openPulseInput(ioio.lib.api.DigitalInput.Spec, - * ioio.lib.api.PulseInput.ClockRate, - * ioio.lib.api.PulseInput.PulseMode, boolean) - */ - public PulseInput openPulseInput(int pin, PulseMode mode) - throws ConnectionLostException; - - /** - * Open a UART module, enabling a bulk transfer of byte buffers. - *

- * UART is a very common hardware communication protocol, enabling full- - * duplex, asynchronous point-to-point data transfer. It typically serves - * for opening consoles or as a basis for higher-level protocols, such as - * MIDI RS-232, and RS-485. - *

- * Note that not every pin can be used for UART RX or TX. In addition, the - * total number of concurrent UART modules in use is limited. See board - * documentation for the legal pins and limit on concurrent usage. - *

- * The UART module will operate, and the pins will work in their respective - * modes until close() is invoked on the returned interface. It is illegal - * to use pins that have already been opened and has not been closed. A - * connection must have been established prior to calling this method, by - * invoking {@link #waitForConnect()}. - * - * @param rx - * Pin specification for the RX pin, consisting of the pin - * number, as labeled on the board, and the mode, which - * determines whether the pin will be floating, pull-up or - * pull-down. See {@link DigitalInput.Spec.Mode} for more - * information. null can be passed to designate that we do not - * want RX input to this module. - * @param tx - * Pin specification for the TX pin, consisting of the pin - * number, as labeled on the board, and the mode, which - * determines whether the pin will be normal or open-drain. See - * {@link DigitalOutput.Spec.Mode} for more information. null can - * be passed to designate that we do not want TX output to this - * module. - * @param baud - * The clock frequency of the UART module in Hz. - * @param parity - * The parity mode, as in {@link Parity}. - * @param stopbits - * Number of stop bits, as in {@link StopBits}. - * @return Interface of the assigned module. - * @throws ConnectionLostException - * Connection was lost before or during the execution of this - * method. - * @throws OutOfResourceException - * This is a runtime exception, so it is not necessary to catch - * it if the client guarantees that the total number of - * concurrent UART resources is not exceeded. - * @see Uart - */ - public Uart openUart(DigitalInput.Spec rx, DigitalOutput.Spec tx, int baud, - Parity parity, StopBits stopbits) throws ConnectionLostException; - - /** - * Shorthand for - * {@link #openUart(DigitalInput.Spec, DigitalOutput.Spec, int, Uart.Parity, Uart.StopBits)} - * , where the input pins use their default specs. {@link #INVALID_PIN} can - * be used on either pin if a TX- or RX-only UART is needed. - * - * @see #openUart(DigitalInput.Spec, DigitalOutput.Spec, int, Uart.Parity, - * Uart.StopBits) - */ - public Uart openUart(int rx, int tx, int baud, Parity parity, - StopBits stopbits) throws ConnectionLostException; - - /** - * Open a SPI master module, enabling communication with multiple - * SPI-enabled slave modules. - *

- * SPI is a common hardware communication protocol, enabling full-duplex, - * synchronous point-to-multi-point data transfer. It requires MOSI, MISO - * and CLK lines shared by all nodes, as well as a SS line per slave, - * connected between this slave and a respective pin on the master. The MISO - * line should operate in pull-up mode, using either the internal pull-up or - * an external resistor. - *

- * Note that not every pin can be used for SPI MISO, MOSI or CLK. In - * addition, the total number of concurrent SPI modules in use is limited. - * See board documentation for the legal pins and limit on concurrent usage. - *

- * The SPI module will operate, and the pins will work in their respective - * modes until close() is invoked on the returned interface. It is illegal - * to use pins that have already been opened and has not been closed. A - * connection must have been established prior to calling this method, by - * invoking {@link #waitForConnect()}. - * - * @param miso - * Pin specification for the MISO (Master In Slave Out) pin, - * consisting of the pin number, as labeled on the board, and the - * mode, which determines whether the pin will be floating, - * pull-up or pull-down. See {@link DigitalInput.Spec.Mode} for - * more information. - * @param mosi - * Pin specification for the MOSI (Master Out Slave In) pin, - * consisting of the pin number, as labeled on the board, and the - * mode, which determines whether the pin will be normal or - * open-drain. See {@link DigitalOutput.Spec.Mode} for more - * information. - * @param clk - * Pin specification for the CLK pin, consisting of the pin - * number, as labeled on the board, and the mode, which - * determines whether the pin will be normal or open-drain. See - * {@link DigitalOutput.Spec.Mode} for more information. - * @param slaveSelect - * An array of pin specifications for each of the slaves' SS - * (Slave Select) pin. The index of this array designates the - * slave index, used later to refer to this slave. The spec is - * consisting of the pin number, as labeled on the board, and the - * mode, which determines whether the pin will be normal or - * open-drain. See {@link DigitalOutput.Spec.Mode} for more - * information. - * @param config - * The configuration of the SPI module. See - * {@link SpiMaster.Config} for details. - * @return Interface of the assigned module. - * @throws ConnectionLostException - * Connection was lost before or during the execution of this - * method. - * @throws OutOfResourceException - * This is a runtime exception, so it is not necessary to catch - * it if the client guarantees that the total number of - * concurrent SPI resources is not exceeded. - * @see SpiMaster - */ - public SpiMaster openSpiMaster(DigitalInput.Spec miso, - DigitalOutput.Spec mosi, DigitalOutput.Spec clk, - DigitalOutput.Spec[] slaveSelect, SpiMaster.Config config) - throws ConnectionLostException; - - /** - * Shorthand for - * {@link #openSpiMaster(ioio.lib.api.DigitalInput.Spec, ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec[], ioio.lib.api.SpiMaster.Config)} - * , where the pins are all open with the default modes and default - * configuration values are used. - * - * @see #openSpiMaster(ioio.lib.api.DigitalInput.Spec, - * ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec, - * ioio.lib.api.DigitalOutput.Spec[], ioio.lib.api.SpiMaster.Config) - */ - public SpiMaster openSpiMaster(int miso, int mosi, int clk, - int[] slaveSelect, SpiMaster.Rate rate) - throws ConnectionLostException; - - /** - * Shorthand for - * {@link #openSpiMaster(ioio.lib.api.DigitalInput.Spec, ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec[], ioio.lib.api.SpiMaster.Config)} - * , where the MISO pins is opened with pull up, and the other pins are open - * with the default modes and default configuration values are used. In this - * version, a single slave is used. - * - * @see #openSpiMaster(ioio.lib.api.DigitalInput.Spec, - * ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec, - * ioio.lib.api.DigitalOutput.Spec[], ioio.lib.api.SpiMaster.Config) - */ - public SpiMaster openSpiMaster(int miso, int mosi, int clk, - int slaveSelect, SpiMaster.Rate rate) - throws ConnectionLostException; - - /** - * Open a TWI (Two-Wire Interface, such as I2C/SMBus) master module, - * enabling communication with multiple TWI-enabled slave modules. - *

- * TWI is a common hardware communication protocol, enabling half-duplex, - * synchronous point-to-multi-point data transfer. It requires a physical - * connection of two lines (SDA, SCL) shared by all the bus nodes, where the - * SDA is open-drain and externally pulled-up. - *

- * Note that there is a fixed number of TWI modules, and the pins they use - * are static. Client has to make sure these pins are not already opened - * before calling this method. See board documentation for the number of - * modules and the respective pins they use. - *

- * The TWI module will operate, and the pins will work in their respective - * modes until close() is invoked on the returned interface. It is illegal - * to use pins that have already been opened and has not been closed. A - * connection must have been established prior to calling this method, by - * invoking {@link #waitForConnect()}. - * - * @param twiNum - * The TWI module index to use. Will also determine the pins - * used. - * @param rate - * The clock rate. Can be 100KHz / 400KHz / 1MHz. - * @param smbus - * When true, will use SMBus voltage levels. When false, I2C - * voltage levels. - * @return Interface of the assigned module. - * @throws ConnectionLostException - * Connection was lost before or during the execution of this - * method. - * @see TwiMaster - */ - public TwiMaster openTwiMaster(int twiNum, Rate rate, boolean smbus) - throws ConnectionLostException; - - /** - * Open an ICSP channel, enabling Flash programming of an external PIC MCU, - * and in particular, another IOIO board. - *

- * ICSP (In-Circuit Serial Programming) is a protocol intended for - * programming of PIC MCUs. It is a serial protocol over three wires: PGC - * (clock), PGD (data) and MCLR (reset), where PGC and MCLR are controlled - * by the master and PGD is shared by the master and slave, depending on the - * transaction state. - *

- * Note that there is only one ICSP modules, and the pins it uses are - * static. Client has to make sure that the ICSP module is not already in - * use, as well as those dedicated pins. See board documentation for the - * actual pins used for ICSP. - * - * @return Interface of the ICSP module. - * @see IcspMaster - * @throws ConnectionLostException - * Connection was lost before or during the execution of this - * method. - */ - public IcspMaster openIcspMaster() throws ConnectionLostException; - - /** - * Start a batch of operations. This is strictly an optimization and will - * not change functionality: if the client knows that a sequence of several - * IOIO operations are going to be performed immediately following each - * other, a call to {@link #beginBatch()} before the sequence and - * {@link #endBatch()} after the sequence will cause the operations to be - * grouped into one transfer to the IOIO, thus reducing latency. A matching - * {@link #endBatch()} operation must always follow, or otherwise no - * operation will ever be actually executed. {@link #beginBatch()} / - * {@link #endBatch()} blocks may be nested - the transfer will occur when - * the outermost {@link #endBatch()} is invoked. Note that it is not - * guaranteed that no transfers will happen while inside a batch - it should - * be treated as a hint. Code running inside the block must be quick as it - * blocks all transfers to the IOIO, including those performed from - * other threads. - * - * @throws ConnectionLostException - * Connection was lost before or during the execution of this - * method. - */ - public void beginBatch() throws ConnectionLostException; - - /** - * End a batch of operations. For explanation, see {@link #beginBatch()}. - * - * @throws ConnectionLostException - * Connection was lost before or during the execution of this - * method. - */ - public void endBatch() throws ConnectionLostException; -} +/* + * Copyright 2011 Ytai Ben-Tsvi. All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARSHAN POURSOHI OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied. + */ +package ioio.lib.api; + +import ioio.lib.api.PulseInput.PulseMode; +import ioio.lib.api.TwiMaster.Rate; +import ioio.lib.api.Uart.Parity; +import ioio.lib.api.Uart.StopBits; +import ioio.lib.api.exception.ConnectionLostException; +import ioio.lib.api.exception.IncompatibilityException; +import ioio.lib.api.exception.OutOfResourceException; + +import java.io.Closeable; + +/** + * This interface provides control over all the IOIO board functions. + *

+ * An instance of this interface is typically obtained by using the + * {@link IOIOFactory} class. Initially, a connection should be established, by + * calling {@link #waitForConnect()}. This method will block until the board is + * connected an a connection has been established. + *

+ * During the connection process, this library verifies that the IOIO firmware + * is compatible with the required version. If not, {@link #waitForConnect()} + * will throw a {@link IncompatibilityException}, putting the {@link IOIO} + * instance in a "zombie" state: nothing could be done with it except calling + * {@link #disconnect()}, or waiting for the physical connection to drop via + * {@link #waitForDisconnect()}. + *

+ * As soon as a connection is established, the IOIO can be used, typically, by + * calling the openXXX() functions to obtain additional interfaces for + * controlling specific function of the board. + *

+ * Whenever a connection is lost as a result of physically disconnecting the + * board or as a result of calling {@link #disconnect()}, this instance and all + * the interfaces obtained from it become invalid, and will throw a + * {@link ConnectionLostException} on every operation. Once the connection is + * lost, those instances cannot be recycled, but rather it is required to create + * new ones and wait for a connection again. + *

+ * Initially all pins are tri-stated (floating), and all functions are disabled. + * Whenever a connection is lost or dropped, the board will immediately return + * to the this initial state. + *

+ * Typical usage: + * + *

+ * IOIO ioio = IOIOFactory.create();
+ * try {
+ *   ioio.waitForConnect();
+ *   DigitalOutput out = ioio.openDigitalOutput(10);
+ *   out.write(true);
+ *   ...
+ * } catch (ConnectionLostException e) {
+ * } catch (Exception e) {
+ *   ioio.disconnect();
+ * } finally {
+ *   ioio.waitForDisconnect();
+ * }
+ * 
+ * + * @see IOIOFactory#create() + */ +public interface IOIO { + /** An invalid pin number. */ + public static final int INVALID_PIN = -1; + /** The pin number used to designate the on-board 'stat' LED. */ + public static final int LED_PIN = 0; + + /** + * A versioned component in the system. + * + * @see IOIO#getImplVersion(VersionType) + */ + public enum VersionType { + /** Hardware version. */ + HARDWARE_VER, + /** Bootloader version. */ + BOOTLOADER_VER, + /** Application layer firmware version. */ + APP_FIRMWARE_VER, + /** IOIOLib version. */ + IOIOLIB_VER + } + + /** + * A state of a IOIO instance. + */ + public enum State { + /** Connection not yet established. */ + INIT, + /** Connected. */ + CONNECTED, + /** Connection established, incompatible firmware detected. */ + INCOMPATIBLE, + /** Disconnected. Instance is useless. */ + DEAD + } + + /** + * Establishes connection with the IOIO board. + *

+ * This method is blocking until connection is established. This method can + * be aborted by calling {@link #disconnect()}. In this case, it will throw + * a {@link ConnectionLostException}. + * + * @throws ConnectionLostException + * An error occurred during connection or disconnect() has been + * called during connection. The instance state is disconnected. + * @throws IncompatibilityException + * An incompatible board firmware of hardware has been detected. + * The instance state is disconnected. + * @see #disconnect() + * @see #waitForDisconnect() + */ + public void waitForConnect() throws ConnectionLostException, + IncompatibilityException; + + /** + * Closes the connection to the board, or aborts a connection process + * started with waitForConnect(). + *

+ * Once this method is called, this IOIO instance and all the instances + * obtain from it become invalid and will throw an exception on every + * operation. + *

+ * This method is asynchronous, i.e. it returns immediately, but it is not + * guaranteed that all connection-related resources has already been freed + * and can be reused upon return. In cases when this is important, client + * can call {@link #waitForDisconnect()}, which will block until all + * resources have been freed. + */ + public void disconnect(); + + /** + * Blocks until IOIO has been disconnected and all connection-related + * resources have been freed, so that a new connection can be attempted. + * + * @throws InterruptedException + * When interrupt() has been called on this thread. This might + * mean that an immediate attempt to create and connect a new + * IOIO object might fail for resource contention. + * @see #disconnect() + * @see #waitForConnect() + */ + public void waitForDisconnect() throws InterruptedException; + + /** + * Gets the connections state. + * + * @return The connection state. + */ + public State getState(); + + /** + * Resets the entire state (returning to initial state), without dropping + * the connection. + *

+ * It is equivalent to calling {@link Closeable#close()} on every interface + * obtained from this instance. A connection must have been established + * prior to calling this method, by invoking {@link #waitForConnect()}. + * + * @throws ConnectionLostException + * Connection was lost before or during the execution of this + * method. + * @see #hardReset() + */ + public void softReset() throws ConnectionLostException; + + /** + * Equivalent to disconnecting and reconnecting the board power supply. + *

+ * The connection will be dropped and not reestablished. Full boot sequence + * will take place, so firmware upgrades can be performed. A connection must + * have been established prior to calling this method, by invoking + * {@link #waitForConnect()}. + * + * @throws ConnectionLostException + * Connection was lost before or during the execution of this + * method. + * @see #softReset() + */ + public void hardReset() throws ConnectionLostException; + + /** + * Query the implementation version of the system's components. The + * implementation version uniquely identifies a hardware revision or a + * software build. Returned version IDs are always 8-character long, + * according to the IOIO versioning system: first 4 characters are the + * version authority and last 4 characters are the revision. + * + * @param v + * The component whose version we query. + * @return An 8-character implementation version ID. + * @throws ConnectionLostException + * Connection was lost before or during the execution of this + * method. + */ + public String getImplVersion(VersionType v) throws ConnectionLostException; + + /** + * Open a pin for digital input. + *

+ * A digital input pin can be used to read logic-level signals. The pin will + * operate in this mode until close() is invoked on the returned interface. + * It is illegal to open a pin that has already been opened and has not been + * closed. A connection must have been established prior to calling this + * method, by invoking {@link #waitForConnect()}. + * + * @param spec + * Pin specification, consisting of the pin number, as labeled on + * the board, and the mode, which determines whether the pin will + * be floating, pull-up or pull-down. See + * {@link DigitalInput.Spec.Mode} for more information. + * @return Interface of the assigned pin. + * @throws ConnectionLostException + * Connection was lost before or during the execution of this + * method. + * @see DigitalInput + */ + public DigitalInput openDigitalInput(DigitalInput.Spec spec) + throws ConnectionLostException; + + /** + * Shorthand for openDigitalInput(new DigitalInput.Spec(pin)). + * + * @see #openDigitalInput(ioio.lib.api.DigitalInput.Spec) + */ + public DigitalInput openDigitalInput(int pin) + throws ConnectionLostException; + + /** + * Shorthand for openDigitalInput(new DigitalInput.Spec(pin, mode)). + * + * @see #openDigitalInput(ioio.lib.api.DigitalInput.Spec) + */ + public DigitalInput openDigitalInput(int pin, DigitalInput.Spec.Mode mode) + throws ConnectionLostException; + + /** + * Open a pin for digital output. + *

+ * A digital output pin can be used to generate logic-level signals. The pin + * will operate in this mode until close() is invoked on the returned + * interface. It is illegal to open a pin that has already been opened and + * has not been closed. A connection must have been established prior to + * calling this method, by invoking {@link #waitForConnect()}. + * + * @param spec + * Pin specification, consisting of the pin number, as labeled on + * the board, and the mode, which determines whether the pin will + * be normal or open-drain. See {@link DigitalOutput.Spec.Mode} + * for more information. + * @param startValue + * The initial logic level this pin will generate as soon at it + * is open. + * @return Interface of the assigned pin. + * @throws ConnectionLostException + * Connection was lost before or during the execution of this + * method. + * @see DigitalOutput + */ + public DigitalOutput openDigitalOutput(DigitalOutput.Spec spec, + boolean startValue) throws ConnectionLostException; + + /** + * Shorthand for openDigitalOutput(new DigitalOutput.Spec(pin, mode), + * startValue). + * + * @see #openDigitalOutput(ioio.lib.api.DigitalOutput.Spec, boolean) + */ + public DigitalOutput openDigitalOutput(int pin, + DigitalOutput.Spec.Mode mode, boolean startValue) + throws ConnectionLostException; + + /** + * Shorthand for openDigitalOutput(new DigitalOutput.Spec(pin), startValue). + * Pin mode will be "normal" (as opposed to "open-drain". + * + * @see #openDigitalOutput(ioio.lib.api.DigitalOutput.Spec, boolean) + */ + public DigitalOutput openDigitalOutput(int pin, boolean startValue) + throws ConnectionLostException; + + /** + * Shorthand for openDigitalOutput(new DigitalOutput.Spec(pin), false). Pin + * mode will be "normal" (as opposed to "open-drain". + * + * @see #openDigitalOutput(ioio.lib.api.DigitalOutput.Spec, boolean) + */ + public DigitalOutput openDigitalOutput(int pin) + throws ConnectionLostException; + + /** + * Open a pin for analog input. + *

+ * An analog input pin can be used to measure voltage. Note that not every + * pin can be used as an analog input. See board documentation for the legal + * pins and permitted voltage range. + *

+ * The pin will operate in this mode until close() is invoked on the + * returned interface. It is illegal to open a pin that has already been + * opened and has not been closed. A connection must have been established + * prior to calling this method, by invoking {@link #waitForConnect()}. + * + * @param pin + * Pin number, as labeled on the board. + * @return Interface of the assigned pin. + * @throws ConnectionLostException + * Connection was lost before or during the execution of this + * method. + * @see AnalogInput + */ + public AnalogInput openAnalogInput(int pin) throws ConnectionLostException; + + /** + * Open a pin for PWM (Pulse-Width Modulation) output. + *

+ * A PWM pin produces a logic-level PWM signal. These signals are typically + * used for simulating analog outputs for controlling the intensity of LEDs, + * the rotation speed of motors, etc. They are also frequently used for + * controlling hobby servo motors. + *

+ * Note that not every pin can be used as PWM output. In addition, the total + * number of concurrent PWM modules in use is limited. See board + * documentation for the legal pins and limit on concurrent usage. + *

+ * The pin will operate in this mode until close() is invoked on the + * returned interface. It is illegal to open a pin that has already been + * opened and has not been closed. A connection must have been established + * prior to calling this method, by invoking {@link #waitForConnect()}. + * + * @param spec + * Pin specification, consisting of the pin number, as labeled on + * the board, and the mode, which determines whether the pin will + * be normal or open-drain. See {@link DigitalOutput.Spec.Mode} + * for more information. + * @param freqHz + * PWM frequency, in Hertz. + * @return Interface of the assigned pin. + * @throws ConnectionLostException + * Connection was lost before or during the execution of this + * method. + * @throws OutOfResourceException + * This is a runtime exception, so it is not necessary to catch + * it if the client guarantees that the total number of + * concurrent PWM resources is not exceeded. + * @see PwmOutput + */ + public PwmOutput openPwmOutput(DigitalOutput.Spec spec, int freqHz) + throws ConnectionLostException; + + /** + * Shorthand for openPwmOutput(new DigitalOutput.Spec(pin), freqHz). + * + * @see #openPwmOutput(ioio.lib.api.DigitalOutput.Spec, int) + */ + public PwmOutput openPwmOutput(int pin, int freqHz) + throws ConnectionLostException; + + /** + * Open a pin for pulse input. + *

+ * The pulse input module is quite flexible. It enables several kinds of + * timing measurements on a digital signal: pulse width measurement + * (positive or negative pulse), and frequency of a periodic signal. + *

+ * Note that not every pin can be used as pulse input. In addition, the + * total number of concurrent pulse input modules in use is limited. See + * board documentation for the legal pins and limit on concurrent usage. + *

+ * The pin will operate in this mode until close() is invoked on the + * returned interface. It is illegal to open a pin that has already been + * opened and has not been closed. A connection must have been established + * prior to calling this method, by invoking {@link #waitForConnect()}. + * + * @param spec + * Pin specification, consisting of the pin number, as labeled on + * the board, and the mode, which determines whether the pin will + * be floating, pull-up or pull-down. See + * {@link DigitalInput.Spec.Mode} for more information. + * @param rate + * The clock rate to use for timing the signal. A faster clock + * rate will result in better precision but will only be able to + * measure narrow pulses / high frequencies. + * @param mode + * The mode in which to operate. Determines whether the module + * will measure pulse durations or frequency. + * @param doublePrecision + * Whether to open a double-precision pulse input module. Double- + * precision modules enable reading of much longer pulses and + * lower frequencies with high accuracy than single precision + * modules. However, their number is limited, so when possible, + * and if the resources are all needed, use single-precision. For + * more details on the exact spec of single- vs. double- + * precision, see {@link PulseInput}. + * @return An instance of the {@link PulseInput}, which can be used to + * obtain the data. + * @throws ConnectionLostException + * Connection was lost before or during the execution of this + * method. + * @throws OutOfResourceException + * This is a runtime exception, so it is not necessary to catch + * it if the client guarantees that the total number of + * concurrent PWM resources is not exceeded. + * @see PulseInput + */ + public PulseInput openPulseInput(DigitalInput.Spec spec, + PulseInput.ClockRate rate, PulseInput.PulseMode mode, + boolean doublePrecision) throws ConnectionLostException; + + /** + * Shorthand for openPulseInput(new DigitalInput.Spec(pin), rate, mode, + * true), i.e. opens a double-precision, 16MHz pulse input on the given pin + * with the given mode. + * + * @see #openPulseInput(ioio.lib.api.DigitalInput.Spec, + * ioio.lib.api.PulseInput.ClockRate, + * ioio.lib.api.PulseInput.PulseMode, boolean) + */ + public PulseInput openPulseInput(int pin, PulseMode mode) + throws ConnectionLostException; + + /** + * Open a UART module, enabling a bulk transfer of byte buffers. + *

+ * UART is a very common hardware communication protocol, enabling full- + * duplex, asynchronous point-to-point data transfer. It typically serves + * for opening consoles or as a basis for higher-level protocols, such as + * MIDI RS-232, and RS-485. + *

+ * Note that not every pin can be used for UART RX or TX. In addition, the + * total number of concurrent UART modules in use is limited. See board + * documentation for the legal pins and limit on concurrent usage. + *

+ * The UART module will operate, and the pins will work in their respective + * modes until close() is invoked on the returned interface. It is illegal + * to use pins that have already been opened and has not been closed. A + * connection must have been established prior to calling this method, by + * invoking {@link #waitForConnect()}. + * + * @param rx + * Pin specification for the RX pin, consisting of the pin + * number, as labeled on the board, and the mode, which + * determines whether the pin will be floating, pull-up or + * pull-down. See {@link DigitalInput.Spec.Mode} for more + * information. null can be passed to designate that we do not + * want RX input to this module. + * @param tx + * Pin specification for the TX pin, consisting of the pin + * number, as labeled on the board, and the mode, which + * determines whether the pin will be normal or open-drain. See + * {@link DigitalOutput.Spec.Mode} for more information. null can + * be passed to designate that we do not want TX output to this + * module. + * @param baud + * The clock frequency of the UART module in Hz. + * @param parity + * The parity mode, as in {@link Parity}. + * @param stopbits + * Number of stop bits, as in {@link StopBits}. + * @return Interface of the assigned module. + * @throws ConnectionLostException + * Connection was lost before or during the execution of this + * method. + * @throws OutOfResourceException + * This is a runtime exception, so it is not necessary to catch + * it if the client guarantees that the total number of + * concurrent UART resources is not exceeded. + * @see Uart + */ + public Uart openUart(DigitalInput.Spec rx, DigitalOutput.Spec tx, int baud, + Parity parity, StopBits stopbits) throws ConnectionLostException; + + /** + * Shorthand for + * {@link #openUart(DigitalInput.Spec, DigitalOutput.Spec, int, Uart.Parity, Uart.StopBits)} + * , where the input pins use their default specs. {@link #INVALID_PIN} can + * be used on either pin if a TX- or RX-only UART is needed. + * + * @see #openUart(DigitalInput.Spec, DigitalOutput.Spec, int, Uart.Parity, + * Uart.StopBits) + */ + public Uart openUart(int rx, int tx, int baud, Parity parity, + StopBits stopbits) throws ConnectionLostException; + + /** + * Open a SPI master module, enabling communication with multiple + * SPI-enabled slave modules. + *

+ * SPI is a common hardware communication protocol, enabling full-duplex, + * synchronous point-to-multi-point data transfer. It requires MOSI, MISO + * and CLK lines shared by all nodes, as well as a SS line per slave, + * connected between this slave and a respective pin on the master. The MISO + * line should operate in pull-up mode, using either the internal pull-up or + * an external resistor. + *

+ * Note that not every pin can be used for SPI MISO, MOSI or CLK. In + * addition, the total number of concurrent SPI modules in use is limited. + * See board documentation for the legal pins and limit on concurrent usage. + *

+ * The SPI module will operate, and the pins will work in their respective + * modes until close() is invoked on the returned interface. It is illegal + * to use pins that have already been opened and has not been closed. A + * connection must have been established prior to calling this method, by + * invoking {@link #waitForConnect()}. + * + * @param miso + * Pin specification for the MISO (Master In Slave Out) pin, + * consisting of the pin number, as labeled on the board, and the + * mode, which determines whether the pin will be floating, + * pull-up or pull-down. See {@link DigitalInput.Spec.Mode} for + * more information. + * @param mosi + * Pin specification for the MOSI (Master Out Slave In) pin, + * consisting of the pin number, as labeled on the board, and the + * mode, which determines whether the pin will be normal or + * open-drain. See {@link DigitalOutput.Spec.Mode} for more + * information. + * @param clk + * Pin specification for the CLK pin, consisting of the pin + * number, as labeled on the board, and the mode, which + * determines whether the pin will be normal or open-drain. See + * {@link DigitalOutput.Spec.Mode} for more information. + * @param slaveSelect + * An array of pin specifications for each of the slaves' SS + * (Slave Select) pin. The index of this array designates the + * slave index, used later to refer to this slave. The spec is + * consisting of the pin number, as labeled on the board, and the + * mode, which determines whether the pin will be normal or + * open-drain. See {@link DigitalOutput.Spec.Mode} for more + * information. + * @param config + * The configuration of the SPI module. See + * {@link SpiMaster.Config} for details. + * @return Interface of the assigned module. + * @throws ConnectionLostException + * Connection was lost before or during the execution of this + * method. + * @throws OutOfResourceException + * This is a runtime exception, so it is not necessary to catch + * it if the client guarantees that the total number of + * concurrent SPI resources is not exceeded. + * @see SpiMaster + */ + public SpiMaster openSpiMaster(DigitalInput.Spec miso, + DigitalOutput.Spec mosi, DigitalOutput.Spec clk, + DigitalOutput.Spec[] slaveSelect, SpiMaster.Config config) + throws ConnectionLostException; + + /** + * Shorthand for + * {@link #openSpiMaster(ioio.lib.api.DigitalInput.Spec, ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec[], ioio.lib.api.SpiMaster.Config)} + * , where the pins are all open with the default modes and default + * configuration values are used. + * + * @see #openSpiMaster(ioio.lib.api.DigitalInput.Spec, + * ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec, + * ioio.lib.api.DigitalOutput.Spec[], ioio.lib.api.SpiMaster.Config) + */ + public SpiMaster openSpiMaster(int miso, int mosi, int clk, + int[] slaveSelect, SpiMaster.Rate rate) + throws ConnectionLostException; + + /** + * Shorthand for + * {@link #openSpiMaster(ioio.lib.api.DigitalInput.Spec, ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec[], ioio.lib.api.SpiMaster.Config)} + * , where the MISO pins is opened with pull up, and the other pins are open + * with the default modes and default configuration values are used. In this + * version, a single slave is used. + * + * @see #openSpiMaster(ioio.lib.api.DigitalInput.Spec, + * ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec, + * ioio.lib.api.DigitalOutput.Spec[], ioio.lib.api.SpiMaster.Config) + */ + public SpiMaster openSpiMaster(int miso, int mosi, int clk, + int slaveSelect, SpiMaster.Rate rate) + throws ConnectionLostException; + + /** + * Open a TWI (Two-Wire Interface, such as I2C/SMBus) master module, + * enabling communication with multiple TWI-enabled slave modules. + *

+ * TWI is a common hardware communication protocol, enabling half-duplex, + * synchronous point-to-multi-point data transfer. It requires a physical + * connection of two lines (SDA, SCL) shared by all the bus nodes, where the + * SDA is open-drain and externally pulled-up. + *

+ * Note that there is a fixed number of TWI modules, and the pins they use + * are static. Client has to make sure these pins are not already opened + * before calling this method. See board documentation for the number of + * modules and the respective pins they use. + *

+ * The TWI module will operate, and the pins will work in their respective + * modes until close() is invoked on the returned interface. It is illegal + * to use pins that have already been opened and has not been closed. A + * connection must have been established prior to calling this method, by + * invoking {@link #waitForConnect()}. + * + * @param twiNum + * The TWI module index to use. Will also determine the pins + * used. + * @param rate + * The clock rate. Can be 100KHz / 400KHz / 1MHz. + * @param smbus + * When true, will use SMBus voltage levels. When false, I2C + * voltage levels. + * @return Interface of the assigned module. + * @throws ConnectionLostException + * Connection was lost before or during the execution of this + * method. + * @see TwiMaster + */ + public TwiMaster openTwiMaster(int twiNum, Rate rate, boolean smbus) + throws ConnectionLostException; + + /** + * Open an ICSP channel, enabling Flash programming of an external PIC MCU, + * and in particular, another IOIO board. + *

+ * ICSP (In-Circuit Serial Programming) is a protocol intended for + * programming of PIC MCUs. It is a serial protocol over three wires: PGC + * (clock), PGD (data) and MCLR (reset), where PGC and MCLR are controlled + * by the master and PGD is shared by the master and slave, depending on the + * transaction state. + *

+ * Note that there is only one ICSP modules, and the pins it uses are + * static. Client has to make sure that the ICSP module is not already in + * use, as well as those dedicated pins. See board documentation for the + * actual pins used for ICSP. + * + * @return Interface of the ICSP module. + * @see IcspMaster + * @throws ConnectionLostException + * Connection was lost before or during the execution of this + * method. + */ + public IcspMaster openIcspMaster() throws ConnectionLostException; + + /** + * Start a batch of operations. This is strictly an optimization and will + * not change functionality: if the client knows that a sequence of several + * IOIO operations are going to be performed immediately following each + * other, a call to {@link #beginBatch()} before the sequence and + * {@link #endBatch()} after the sequence will cause the operations to be + * grouped into one transfer to the IOIO, thus reducing latency. A matching + * {@link #endBatch()} operation must always follow, or otherwise no + * operation will ever be actually executed. {@link #beginBatch()} / + * {@link #endBatch()} blocks may be nested - the transfer will occur when + * the outermost {@link #endBatch()} is invoked. Note that it is not + * guaranteed that no transfers will happen while inside a batch - it should + * be treated as a hint. Code running inside the block must be quick as it + * blocks all transfers to the IOIO, including those performed from + * other threads. + * + * @throws ConnectionLostException + * Connection was lost before or during the execution of this + * method. + */ + public void beginBatch() throws ConnectionLostException; + + /** + * End a batch of operations. For explanation, see {@link #beginBatch()}. + * + * @throws ConnectionLostException + * Connection was lost before or during the execution of this + * method. + */ + public void endBatch() throws ConnectionLostException; +} diff --git a/IOIOLib/src/ioio/lib/api/Uart.java b/IOIOLib/src/ioio/lib/api/Uart.java index 30faa91..dd59f34 100644 --- a/IOIOLib/src/ioio/lib/api/Uart.java +++ b/IOIOLib/src/ioio/lib/api/Uart.java @@ -1,107 +1,107 @@ -/* - * Copyright 2011 Ytai Ben-Tsvi. All rights reserved. - * - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARSHAN POURSOHI OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied. - */ -package ioio.lib.api; - -import ioio.lib.api.exception.ConnectionLostException; - -import java.io.InputStream; -import java.io.OutputStream; - -/** - * An interface for controlling a UART module. - *

- * UART is a very common hardware communication protocol, enabling full- duplex, - * asynchronous point-to-point data transfer. It typically serves for opening - * consoles or as a basis for higher-level protocols, such as MIDI, RS-232 and - * RS-485. Uart instances are obtained by calling - * {@link IOIO#openUart(DigitalInput.Spec, DigitalOutput.Spec, int, Uart.Parity, Uart.StopBits)}. - *

- * The UART protocol is completely symmetric - there is no "master" and "slave" - * at this layer. Each end may send any number of bytes at arbitrary times, - * making it very useful for terminals and terminal-controllable devices. - *

- * Working with UART is very intuitive - it just provides a standard InputStream - * and/or OutputStream. Optionally, one could create a read-only or write-only - * UART instances, by passing null (or INVALID_PIN) for either TX or RX pins. - *

- * The instance is alive since its creation. If the connection with the IOIO - * drops at any point, the instance transitions to a disconnected state, which - * every attempt to use it (except {@link #close()}) will throw a - * {@link ConnectionLostException}. Whenever {@link #close()} is invoked the - * instance may no longer be used. Any resources associated with it are freed - * and can be reused. - *

- * Typical usage: - * - *

- * Uart uart = ioio.openUart(3, 4, 19200, Parity.NONE, StopBits.ONE);
- * InputStream in = uart.getInputStream();
- * OutputStream out = uart.getOutputStream();
- * out.write(new String("Hello").getBytes());
- * int i = in.read();  // blocking
- * ...
- * uart.close();  // free UART module and pins
- * 
- * - * @see IOIO#openUart(DigitalInput.Spec, DigitalOutput.Spec, int, Uart.Parity, - * Uart.StopBits) - */ -public interface Uart extends Closeable { - /** Parity-bit mode. */ - enum Parity { - /** No parity. */ - NONE, - /** Even parity. */ - EVEN, - /** Odd parity. */ - ODD - } - - /** Number of stop-bits. */ - enum StopBits { - /** One stop bit. */ - ONE, - /** Two stop bits. */ - TWO - } - - /** - * Gets the input stream. - * - * @return An input stream. - */ - public InputStream getInputStream(); - - /** - * Gets the output stream. - * - * @return An output stream. - */ - public OutputStream getOutputStream(); -} +/* + * Copyright 2011 Ytai Ben-Tsvi. All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARSHAN POURSOHI OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied. + */ +package ioio.lib.api; + +import ioio.lib.api.exception.ConnectionLostException; + +import java.io.InputStream; +import java.io.OutputStream; + +/** + * An interface for controlling a UART module. + *

+ * UART is a very common hardware communication protocol, enabling full- duplex, + * asynchronous point-to-point data transfer. It typically serves for opening + * consoles or as a basis for higher-level protocols, such as MIDI, RS-232 and + * RS-485. Uart instances are obtained by calling + * {@link IOIO#openUart(DigitalInput.Spec, DigitalOutput.Spec, int, Uart.Parity, Uart.StopBits)}. + *

+ * The UART protocol is completely symmetric - there is no "master" and "slave" + * at this layer. Each end may send any number of bytes at arbitrary times, + * making it very useful for terminals and terminal-controllable devices. + *

+ * Working with UART is very intuitive - it just provides a standard InputStream + * and/or OutputStream. Optionally, one could create a read-only or write-only + * UART instances, by passing null (or INVALID_PIN) for either TX or RX pins. + *

+ * The instance is alive since its creation. If the connection with the IOIO + * drops at any point, the instance transitions to a disconnected state, which + * every attempt to use it (except {@link #close()}) will throw a + * {@link ConnectionLostException}. Whenever {@link #close()} is invoked the + * instance may no longer be used. Any resources associated with it are freed + * and can be reused. + *

+ * Typical usage: + * + *

+ * Uart uart = ioio.openUart(3, 4, 19200, Parity.NONE, StopBits.ONE);
+ * InputStream in = uart.getInputStream();
+ * OutputStream out = uart.getOutputStream();
+ * out.write(new String("Hello").getBytes());
+ * int i = in.read();  // blocking
+ * ...
+ * uart.close();  // free UART module and pins
+ * 
+ * + * @see IOIO#openUart(DigitalInput.Spec, DigitalOutput.Spec, int, Uart.Parity, + * Uart.StopBits) + */ +public interface Uart extends Closeable { + /** Parity-bit mode. */ + enum Parity { + /** No parity. */ + NONE, + /** Even parity. */ + EVEN, + /** Odd parity. */ + ODD + } + + /** Number of stop-bits. */ + enum StopBits { + /** One stop bit. */ + ONE, + /** Two stop bits. */ + TWO + } + + /** + * Gets the input stream. + * + * @return An input stream. + */ + public InputStream getInputStream(); + + /** + * Gets the output stream. + * + * @return An output stream. + */ + public OutputStream getOutputStream(); +} diff --git a/IOIOLib/src/ioio/lib/impl/Constants.java b/IOIOLib/src/ioio/lib/impl/Constants.java index abfefb4..aa82221 100644 --- a/IOIOLib/src/ioio/lib/impl/Constants.java +++ b/IOIOLib/src/ioio/lib/impl/Constants.java @@ -1,45 +1,45 @@ -/* - * Copyright 2011 Ytai Ben-Tsvi. All rights reserved. - * - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARSHAN POURSOHI OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied. - */ -package ioio.lib.impl; - -class Constants { - static final int NUM_PINS = 49; - static final int NUM_ANALOG_PINS = 16; - static final int NUM_PWM_MODULES = 9; - static final int NUM_UART_MODULES = 4; - static final int NUM_SPI_MODULES = 3; - static final int NUM_TWI_MODULES = 3; - static final int[] INCAP_MODULES_DOUBLE = new int[] { 0, 2, 4}; - static final int[] INCAP_MODULES_SINGLE = new int[] { 6, 7, 8}; - static final int BUFFER_SIZE = 1024; - static final int PACKET_BUFFER_SIZE = 256; - - static final int[][] TWI_PINS = new int[][] {{ 4, 5 }, { 47, 48 }, { 26, 25 }}; - static final int[] ICSP_PINS = new int[] { 36, 37, 38 }; -} +/* + * Copyright 2011 Ytai Ben-Tsvi. All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARSHAN POURSOHI OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied. + */ +package ioio.lib.impl; + +class Constants { + static final int NUM_PINS = 49; + static final int NUM_ANALOG_PINS = 16; + static final int NUM_PWM_MODULES = 9; + static final int NUM_UART_MODULES = 4; + static final int NUM_SPI_MODULES = 3; + static final int NUM_TWI_MODULES = 3; + static final int[] INCAP_MODULES_DOUBLE = new int[] { 0, 2, 4}; + static final int[] INCAP_MODULES_SINGLE = new int[] { 6, 7, 8}; + static final int BUFFER_SIZE = 1024; + static final int PACKET_BUFFER_SIZE = 256; + + static final int[][] TWI_PINS = new int[][] {{ 4, 5 }, { 47, 48 }, { 26, 25 }}; + static final int[] ICSP_PINS = new int[] { 36, 37, 38 }; +} diff --git a/IOIOLib/src/ioio/lib/impl/IOIOImpl.java b/IOIOLib/src/ioio/lib/impl/IOIOImpl.java index 8731ea0..088110e 100644 --- a/IOIOLib/src/ioio/lib/impl/IOIOImpl.java +++ b/IOIOLib/src/ioio/lib/impl/IOIOImpl.java @@ -1,700 +1,700 @@ -/* - * Copyright 2011 Ytai Ben-Tsvi. All rights reserved. - * - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARSHAN POURSOHI OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied. - */ -package ioio.lib.impl; - -import ioio.lib.api.AnalogInput; -import ioio.lib.api.DigitalInput; -import ioio.lib.api.DigitalInput.Spec; -import ioio.lib.api.DigitalInput.Spec.Mode; -import ioio.lib.api.DigitalOutput; -import ioio.lib.api.IOIO; -import ioio.lib.api.IOIOConnection; -import ioio.lib.api.IcspMaster; -import ioio.lib.api.PulseInput; -import ioio.lib.api.PulseInput.ClockRate; -import ioio.lib.api.PulseInput.PulseMode; -import ioio.lib.api.PwmOutput; -import ioio.lib.api.SpiMaster; -import ioio.lib.api.TwiMaster; -import ioio.lib.api.TwiMaster.Rate; -import ioio.lib.api.Uart; -import ioio.lib.api.exception.ConnectionLostException; -import ioio.lib.api.exception.IncompatibilityException; -import ioio.lib.impl.IOIOProtocol.PwmScale; -import ioio.lib.impl.IncomingState.DisconnectListener; - -import java.io.IOException; - -import android.util.Log; - -public class IOIOImpl implements IOIO, DisconnectListener { - private static final String TAG = "IOIOImpl"; - private boolean disconnect_ = false; - - private static final byte[] REQUIRED_INTERFACE_ID = new byte[] { 'I', 'O', - 'I', 'O', '0', '0', '0', '3' }; - - private final IOIOConnection connection_; - private final IncomingState incomingState_ = new IncomingState(); - private final boolean openPins_[] = new boolean[Constants.NUM_PINS]; - private final boolean openTwi_[] = new boolean[Constants.NUM_TWI_MODULES]; - private boolean openIcsp_ = false; - private final ModuleAllocator pwmAllocator_ = new ModuleAllocator( - Constants.NUM_PWM_MODULES, "PWM"); - private final ModuleAllocator uartAllocator_ = new ModuleAllocator( - Constants.NUM_UART_MODULES, "UART"); - private final ModuleAllocator spiAllocator_ = new ModuleAllocator( - Constants.NUM_SPI_MODULES, "SPI"); - private final ModuleAllocator incapAllocatorDouble_ = new ModuleAllocator( - Constants.INCAP_MODULES_DOUBLE, "INCAP_DOUBLE"); - private final ModuleAllocator incapAllocatorSingle_ = new ModuleAllocator( - Constants.INCAP_MODULES_SINGLE, "INCAP_SINGLE"); - IOIOProtocol protocol_; - private State state_ = State.INIT; - - public IOIOImpl(IOIOConnection con) { - connection_ = con; - } - - @Override - public void waitForConnect() throws ConnectionLostException, - IncompatibilityException { - if (state_ == State.CONNECTED) { - return; - } - if (state_ == State.DEAD) { - throw new ConnectionLostException(); - } - addDisconnectListener(this); - Log.d(TAG, "Waiting for IOIO connection"); - try { - try { - Log.v(TAG, "Waiting for underlying connection"); - connection_.waitForConnect(); - synchronized (this) { - if (disconnect_) { - throw new ConnectionLostException(); - } - protocol_ = new IOIOProtocol(connection_.getInputStream(), - connection_.getOutputStream(), incomingState_); - // Once this block exits, a disconnect will also involve - // softClose(). - } - } catch (ConnectionLostException e) { - incomingState_.handleConnectionLost(); - throw e; - } - Log.v(TAG, "Waiting for handshake"); - incomingState_.waitConnectionEstablished(); - Log.v(TAG, "Querying for required interface ID"); - checkInterfaceVersion(); - Log.v(TAG, "Required interface ID is supported"); - state_ = State.CONNECTED; - Log.i(TAG, "IOIO connection established"); - } catch (ConnectionLostException e) { - Log.d(TAG, "Connection lost / aborted"); - state_ = State.DEAD; - throw e; - } catch (InterruptedException e) { - Log.e(TAG, "Unexpected exception", e); - } - } - - @Override - public synchronized void disconnect() { - Log.d(TAG, "Client requested disconnect."); - if (disconnect_) { - return; - } - disconnect_ = true; - try { - if (protocol_ != null) { - protocol_.softClose(); - } - } catch (IOException e) { - Log.e(TAG, "Soft close failed", e); - } - connection_.disconnect(); - } - - @Override - public synchronized void disconnected() { - state_ = State.DEAD; - if (disconnect_) { - return; - } - Log.d(TAG, "Physical disconnect."); - disconnect_ = true; - // The IOIOConnection doesn't necessarily know about the disconnect - connection_.disconnect(); - } - - @Override - public void waitForDisconnect() throws InterruptedException { - incomingState_.waitDisconnect(); - } - - @Override - public State getState() { - return state_; - } - - private void checkInterfaceVersion() throws IncompatibilityException, - ConnectionLostException, InterruptedException { - try { - protocol_.checkInterface(REQUIRED_INTERFACE_ID); - } catch (IOException e) { - throw new ConnectionLostException(e); - } - if (!incomingState_.waitForInterfaceSupport()) { - state_ = State.INCOMPATIBLE; - Log.e(TAG, "Required interface ID is not supported"); - throw new IncompatibilityException( - "IOIO firmware does not support required firmware: " - + new String(REQUIRED_INTERFACE_ID)); - } - } - - synchronized void removeDisconnectListener(DisconnectListener listener) { - incomingState_.removeDisconnectListener(listener); - } - - synchronized void addDisconnectListener(DisconnectListener listener) - throws ConnectionLostException { - incomingState_.addDisconnectListener(listener); - } - - synchronized void closePin(int pin) { - try { - checkState(); - if (!openPins_[pin]) { - throw new IllegalStateException("Pin not open: " + pin); - } - protocol_.setPinDigitalIn(pin, DigitalInput.Spec.Mode.FLOATING); - openPins_[pin] = false; - } catch (IOException e) { - } catch (ConnectionLostException e) { - } - } - - synchronized void closePwm(int pwmNum) { - try { - checkState(); - pwmAllocator_.releaseModule(pwmNum); - protocol_.setPwmPeriod(pwmNum, 0, IOIOProtocol.PwmScale.SCALE_1X); - } catch (IOException e) { - } catch (ConnectionLostException e) { - } - } - - synchronized void closeUart(int uartNum) { - try { - checkState(); - uartAllocator_.releaseModule(uartNum); - protocol_.uartClose(uartNum); - } catch (IOException e) { - } catch (ConnectionLostException e) { - } - } - - synchronized void closeTwi(int twiNum) { - try { - checkState(); - if (!openTwi_[twiNum]) { - throw new IllegalStateException("TWI not open: " + twiNum); - } - openTwi_[twiNum] = false; - openPins_[Constants.TWI_PINS[twiNum][0]] = false; - openPins_[Constants.TWI_PINS[twiNum][1]] = false; - protocol_.i2cClose(twiNum); - } catch (IOException e) { - } catch (ConnectionLostException e) { - } - } - - synchronized void closeIcsp() { - try { - checkState(); - if (!openIcsp_) { - throw new IllegalStateException("ICSP not open"); - } - openIcsp_ = false; - openPins_[Constants.ICSP_PINS[0]] = false; - openPins_[Constants.ICSP_PINS[1]] = false; - protocol_.icspClose(); - } catch (ConnectionLostException e) { - } catch (IOException e) { - } - } - - synchronized void closeSpi(int spiNum) { - try { - checkState(); - spiAllocator_.releaseModule(spiNum); - protocol_.spiClose(spiNum); - } catch (IOException e) { - } catch (ConnectionLostException e) { - } - } - - synchronized void closeIncap(int incapNum, boolean doublePrecision) { - try { - checkState(); - if (doublePrecision) { - incapAllocatorDouble_.releaseModule(incapNum); - } else { - incapAllocatorSingle_.releaseModule(incapNum); - } - protocol_.incapClose(incapNum); - } catch (IOException e) { - } catch (ConnectionLostException e) { - } - } - - @Override - synchronized public void softReset() throws ConnectionLostException { - checkState(); - try { - protocol_.softReset(); - } catch (IOException e) { - throw new ConnectionLostException(e); - } - } - - @Override - synchronized public void hardReset() throws ConnectionLostException { - checkState(); - try { - protocol_.hardReset(); - } catch (IOException e) { - throw new ConnectionLostException(e); - } - } - - @Override - public String getImplVersion(VersionType v) throws ConnectionLostException { - if (state_ == State.INIT) { - throw new IllegalStateException( - "Connection has not yet been established"); - } - switch (v) { - case HARDWARE_VER: - return incomingState_.hardwareId_; - case BOOTLOADER_VER: - return incomingState_.bootloaderId_; - case APP_FIRMWARE_VER: - return incomingState_.firmwareId_; - case IOIOLIB_VER: - return "IOIO0322"; - } - return null; - } - - @Override - public DigitalInput openDigitalInput(int pin) - throws ConnectionLostException { - return openDigitalInput(new DigitalInput.Spec(pin)); - } - - @Override - public DigitalInput openDigitalInput(int pin, Mode mode) - throws ConnectionLostException { - return openDigitalInput(new DigitalInput.Spec(pin, mode)); - } - - @Override - synchronized public DigitalInput openDigitalInput(DigitalInput.Spec spec) - throws ConnectionLostException { - checkState(); - PinFunctionMap.checkValidPin(spec.pin); - checkPinFree(spec.pin); - DigitalInputImpl result = new DigitalInputImpl(this, spec.pin); - addDisconnectListener(result); - openPins_[spec.pin] = true; - incomingState_.addInputPinListener(spec.pin, result); - try { - protocol_.setPinDigitalIn(spec.pin, spec.mode); - protocol_.setChangeNotify(spec.pin, true); - } catch (IOException e) { - result.close(); - throw new ConnectionLostException(e); - } - return result; - } - - @Override - public DigitalOutput openDigitalOutput(int pin, - ioio.lib.api.DigitalOutput.Spec.Mode mode, boolean startValue) - throws ConnectionLostException { - return openDigitalOutput(new DigitalOutput.Spec(pin, mode), startValue); - } - - @Override - synchronized public DigitalOutput openDigitalOutput( - DigitalOutput.Spec spec, boolean startValue) - throws ConnectionLostException { - checkState(); - PinFunctionMap.checkValidPin(spec.pin); - checkPinFree(spec.pin); - DigitalOutputImpl result = new DigitalOutputImpl(this, spec.pin, startValue); - addDisconnectListener(result); - openPins_[spec.pin] = true; - try { - protocol_.setPinDigitalOut(spec.pin, startValue, spec.mode); - } catch (IOException e) { - result.close(); - throw new ConnectionLostException(e); - } - return result; - } - - @Override - public DigitalOutput openDigitalOutput(int pin, boolean startValue) - throws ConnectionLostException { - return openDigitalOutput(new DigitalOutput.Spec(pin), startValue); - } - - @Override - public DigitalOutput openDigitalOutput(int pin) - throws ConnectionLostException { - return openDigitalOutput(new DigitalOutput.Spec(pin), false); - } - - @Override - synchronized public AnalogInput openAnalogInput(int pin) - throws ConnectionLostException { - checkState(); - PinFunctionMap.checkSupportsAnalogInput(pin); - checkPinFree(pin); - AnalogInputImpl result = new AnalogInputImpl(this, pin); - addDisconnectListener(result); - openPins_[pin] = true; - incomingState_.addInputPinListener(pin, result); - try { - protocol_.setPinAnalogIn(pin); - protocol_.setAnalogInSampling(pin, true); - } catch (IOException e) { - result.close(); - throw new ConnectionLostException(e); - } - return result; - } - - @Override - public PwmOutput openPwmOutput(int pin, int freqHz) - throws ConnectionLostException { - return openPwmOutput(new DigitalOutput.Spec(pin), freqHz); - } - - @Override - synchronized public PwmOutput openPwmOutput(DigitalOutput.Spec spec, - int freqHz) throws ConnectionLostException { - checkState(); - PinFunctionMap.checkSupportsPeripheralOutput(spec.pin); - checkPinFree(spec.pin); - int pwmNum = pwmAllocator_.allocateModule(); - - int scale = 0; - float baseUs; - int period; - while (true) { - final int clk = 16000000 / IOIOProtocol.PwmScale.values()[scale].scale; - period = clk / freqHz; - if (period <= 65536) { - baseUs = 1000000.0f / clk; - break; - } - if (++scale >= PwmScale.values().length) { - throw new IllegalArgumentException("Frequency too low: " - + freqHz); - } - } - - PwmImpl pwm = new PwmImpl(this, spec.pin, pwmNum, period, baseUs); - addDisconnectListener(pwm); - openPins_[spec.pin] = true; - try { - protocol_.setPinDigitalOut(spec.pin, false, spec.mode); - protocol_.setPinPwm(spec.pin, pwmNum, true); - protocol_.setPwmPeriod(pwmNum, period - 1, - IOIOProtocol.PwmScale.values()[scale]); - } catch (IOException e) { - pwm.close(); - throw new ConnectionLostException(e); - } - return pwm; - } - - @Override - public Uart openUart(int rx, int tx, int baud, Uart.Parity parity, - Uart.StopBits stopbits) throws ConnectionLostException { - return openUart(rx == INVALID_PIN ? null : new DigitalInput.Spec(rx), - tx == INVALID_PIN ? null : new DigitalOutput.Spec(tx), baud, - parity, stopbits); - } - - @Override - synchronized public Uart openUart(DigitalInput.Spec rx, - DigitalOutput.Spec tx, int baud, Uart.Parity parity, - Uart.StopBits stopbits) throws ConnectionLostException { - checkState(); - if (rx != null) { - PinFunctionMap.checkSupportsPeripheralInput(rx.pin); - checkPinFree(rx.pin); - } - if (tx != null) { - PinFunctionMap.checkSupportsPeripheralOutput(tx.pin); - checkPinFree(tx.pin); - } - int rxPin = rx != null ? rx.pin : INVALID_PIN; - int txPin = tx != null ? tx.pin : INVALID_PIN; - int uartNum = uartAllocator_.allocateModule(); - UartImpl uart = new UartImpl(this, txPin, rxPin, uartNum); - addDisconnectListener(uart); - incomingState_.addUartListener(uartNum, uart); - try { - if (rx != null) { - openPins_[rx.pin] = true; - protocol_.setPinDigitalIn(rx.pin, rx.mode); - protocol_.setPinUart(rx.pin, uartNum, false, true); - } - if (tx != null) { - openPins_[tx.pin] = true; - protocol_.setPinDigitalOut(tx.pin, true, tx.mode); - protocol_.setPinUart(tx.pin, uartNum, true, true); - } - boolean speed4x = true; - int rate = Math.round(4000000.0f / baud) - 1; - if (rate > 65535) { - speed4x = false; - rate = Math.round(1000000.0f / baud) - 1; - } - protocol_.uartConfigure(uartNum, rate, speed4x, stopbits, parity); - } catch (IOException e) { - uart.close(); - throw new ConnectionLostException(e); - } - return uart; - } - - @Override - synchronized public TwiMaster openTwiMaster(int twiNum, Rate rate, - boolean smbus) throws ConnectionLostException { - checkState(); - checkTwiFree(twiNum); - checkPinFree(Constants.TWI_PINS[twiNum][0]); - checkPinFree(Constants.TWI_PINS[twiNum][1]); - openPins_[Constants.TWI_PINS[twiNum][0]] = true; - openPins_[Constants.TWI_PINS[twiNum][1]] = true; - openTwi_[twiNum] = true; - TwiMasterImpl twi = new TwiMasterImpl(this, twiNum); - addDisconnectListener(twi); - incomingState_.addTwiListener(twiNum, twi); - try { - protocol_.i2cConfigureMaster(twiNum, rate, smbus); - } catch (IOException e) { - twi.close(); - throw new ConnectionLostException(e); - } - return twi; - } - - @Override - synchronized public IcspMaster openIcspMaster() - throws ConnectionLostException { - checkState(); - checkIcspFree(); - checkPinFree(Constants.ICSP_PINS[0]); - checkPinFree(Constants.ICSP_PINS[1]); - checkPinFree(Constants.ICSP_PINS[2]); - openPins_[Constants.ICSP_PINS[0]] = true; - openPins_[Constants.ICSP_PINS[1]] = true; - openPins_[Constants.ICSP_PINS[2]] = true; - openIcsp_ = true; - IcspMasterImpl icsp = new IcspMasterImpl(this); - addDisconnectListener(icsp); - incomingState_.addIcspListener(icsp); - try { - protocol_.icspOpen(); - } catch (IOException e) { - icsp.close(); - throw new ConnectionLostException(e); - } - return icsp; - } - - @Override - public SpiMaster openSpiMaster(int miso, int mosi, int clk, - int slaveSelect, SpiMaster.Rate rate) - throws ConnectionLostException { - return openSpiMaster(miso, mosi, clk, new int[] { slaveSelect }, rate); - } - - @Override - public SpiMaster openSpiMaster(int miso, int mosi, int clk, - int[] slaveSelect, SpiMaster.Rate rate) - throws ConnectionLostException { - DigitalOutput.Spec[] slaveSpecs = new DigitalOutput.Spec[slaveSelect.length]; - for (int i = 0; i < slaveSelect.length; ++i) { - slaveSpecs[i] = new DigitalOutput.Spec(slaveSelect[i]); - } - return openSpiMaster(new DigitalInput.Spec(miso, Mode.PULL_UP), - new DigitalOutput.Spec(mosi), new DigitalOutput.Spec(clk), - slaveSpecs, new SpiMaster.Config(rate)); - } - - @Override - synchronized public SpiMaster openSpiMaster(DigitalInput.Spec miso, - DigitalOutput.Spec mosi, DigitalOutput.Spec clk, - DigitalOutput.Spec[] slaveSelect, SpiMaster.Config config) - throws ConnectionLostException { - checkState(); - int ssPins[] = new int[slaveSelect.length]; - checkPinFree(miso.pin); - PinFunctionMap.checkSupportsPeripheralInput(miso.pin); - checkPinFree(mosi.pin); - PinFunctionMap.checkSupportsPeripheralOutput(mosi.pin); - checkPinFree(clk.pin); - PinFunctionMap.checkSupportsPeripheralOutput(clk.pin); - for (int i = 0; i < slaveSelect.length; ++i) { - checkPinFree(slaveSelect[i].pin); - ssPins[i] = slaveSelect[i].pin; - } - - int spiNum = spiAllocator_.allocateModule(); - SpiMasterImpl spi = new SpiMasterImpl(this, spiNum, mosi.pin, miso.pin, - clk.pin, ssPins); - addDisconnectListener(spi); - - openPins_[miso.pin] = true; - openPins_[mosi.pin] = true; - openPins_[clk.pin] = true; - for (int i = 0; i < slaveSelect.length; ++i) { - openPins_[slaveSelect[i].pin] = true; - } - - incomingState_.addSpiListener(spiNum, spi); - try { - protocol_.setPinDigitalIn(miso.pin, miso.mode); - protocol_.setPinSpi(miso.pin, 1, true, spiNum); - protocol_.setPinDigitalOut(mosi.pin, true, mosi.mode); - protocol_.setPinSpi(mosi.pin, 0, true, spiNum); - protocol_.setPinDigitalOut(clk.pin, config.invertClk, clk.mode); - protocol_.setPinSpi(clk.pin, 2, true, spiNum); - for (DigitalOutput.Spec spec : slaveSelect) { - protocol_.setPinDigitalOut(spec.pin, true, spec.mode); - } - protocol_.spiConfigureMaster(spiNum, config); - } catch (IOException e) { - spi.close(); - throw new ConnectionLostException(e); - } - return spi; - } - - @Override - public PulseInput openPulseInput(Spec spec, ClockRate rate, PulseMode mode, - boolean doublePrecision) throws ConnectionLostException { - checkState(); - checkPinFree(spec.pin); - PinFunctionMap.checkSupportsPeripheralInput(spec.pin); - int incapNum = doublePrecision ? incapAllocatorDouble_.allocateModule() - : incapAllocatorSingle_.allocateModule(); - IncapImpl incap = new IncapImpl(this, mode, incapNum, spec.pin, - rate.hertz, mode.scaling, doublePrecision); - addDisconnectListener(incap); - incomingState_.addIncapListener(incapNum, incap); - openPins_[spec.pin] = true; - try { - protocol_.setPinDigitalIn(spec.pin, spec.mode); - protocol_.setPinIncap(spec.pin, incapNum, true); - protocol_.incapConfigure(incapNum, doublePrecision, - mode.ordinal() + 1, rate.ordinal()); - } catch (IOException e) { - incap.close(); - throw new ConnectionLostException(e); - } - return incap; - } - - @Override - public PulseInput openPulseInput(int pin, PulseMode mode) - throws ConnectionLostException { - return openPulseInput(new DigitalInput.Spec(pin), ClockRate.RATE_16MHz, - mode, true); - } - - private void checkPinFree(int pin) { - if (openPins_[pin]) { - throw new IllegalArgumentException("Pin already open: " + pin); - } - } - - private void checkTwiFree(int twi) { - if (openTwi_[twi]) { - throw new IllegalArgumentException("TWI already open: " + twi); - } - } - - private void checkIcspFree() { - if (openIcsp_) { - throw new IllegalArgumentException("ICSP already open"); - } - } - - private void checkState() throws ConnectionLostException { - if (state_ == State.DEAD) { - throw new ConnectionLostException(); - } - if (state_ == State.INCOMPATIBLE) { - throw new IllegalStateException( - "Incompatibility has been reported - IOIO cannot be used"); - } - if (state_ != State.CONNECTED) { - throw new IllegalStateException( - "Connection has not yet been established"); - } - } - - @Override - public synchronized void beginBatch() throws ConnectionLostException { - checkState(); - protocol_.beginBatch(); - } - - @Override - public synchronized void endBatch() throws ConnectionLostException { - checkState(); - try { - protocol_.endBatch(); - } catch (IOException e) { - throw new ConnectionLostException(e); - } - } -} +/* + * Copyright 2011 Ytai Ben-Tsvi. All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARSHAN POURSOHI OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied. + */ +package ioio.lib.impl; + +import ioio.lib.api.AnalogInput; +import ioio.lib.api.DigitalInput; +import ioio.lib.api.DigitalInput.Spec; +import ioio.lib.api.DigitalInput.Spec.Mode; +import ioio.lib.api.DigitalOutput; +import ioio.lib.api.IOIO; +import ioio.lib.api.IOIOConnection; +import ioio.lib.api.IcspMaster; +import ioio.lib.api.PulseInput; +import ioio.lib.api.PulseInput.ClockRate; +import ioio.lib.api.PulseInput.PulseMode; +import ioio.lib.api.PwmOutput; +import ioio.lib.api.SpiMaster; +import ioio.lib.api.TwiMaster; +import ioio.lib.api.TwiMaster.Rate; +import ioio.lib.api.Uart; +import ioio.lib.api.exception.ConnectionLostException; +import ioio.lib.api.exception.IncompatibilityException; +import ioio.lib.impl.IOIOProtocol.PwmScale; +import ioio.lib.impl.IncomingState.DisconnectListener; + +import java.io.IOException; + +import android.util.Log; + +public class IOIOImpl implements IOIO, DisconnectListener { + private static final String TAG = "IOIOImpl"; + private boolean disconnect_ = false; + + private static final byte[] REQUIRED_INTERFACE_ID = new byte[] { 'I', 'O', + 'I', 'O', '0', '0', '0', '3' }; + + private final IOIOConnection connection_; + private final IncomingState incomingState_ = new IncomingState(); + private final boolean openPins_[] = new boolean[Constants.NUM_PINS]; + private final boolean openTwi_[] = new boolean[Constants.NUM_TWI_MODULES]; + private boolean openIcsp_ = false; + private final ModuleAllocator pwmAllocator_ = new ModuleAllocator( + Constants.NUM_PWM_MODULES, "PWM"); + private final ModuleAllocator uartAllocator_ = new ModuleAllocator( + Constants.NUM_UART_MODULES, "UART"); + private final ModuleAllocator spiAllocator_ = new ModuleAllocator( + Constants.NUM_SPI_MODULES, "SPI"); + private final ModuleAllocator incapAllocatorDouble_ = new ModuleAllocator( + Constants.INCAP_MODULES_DOUBLE, "INCAP_DOUBLE"); + private final ModuleAllocator incapAllocatorSingle_ = new ModuleAllocator( + Constants.INCAP_MODULES_SINGLE, "INCAP_SINGLE"); + IOIOProtocol protocol_; + private State state_ = State.INIT; + + public IOIOImpl(IOIOConnection con) { + connection_ = con; + } + + @Override + public void waitForConnect() throws ConnectionLostException, + IncompatibilityException { + if (state_ == State.CONNECTED) { + return; + } + if (state_ == State.DEAD) { + throw new ConnectionLostException(); + } + addDisconnectListener(this); + Log.d(TAG, "Waiting for IOIO connection"); + try { + try { + Log.v(TAG, "Waiting for underlying connection"); + connection_.waitForConnect(); + synchronized (this) { + if (disconnect_) { + throw new ConnectionLostException(); + } + protocol_ = new IOIOProtocol(connection_.getInputStream(), + connection_.getOutputStream(), incomingState_); + // Once this block exits, a disconnect will also involve + // softClose(). + } + } catch (ConnectionLostException e) { + incomingState_.handleConnectionLost(); + throw e; + } + Log.v(TAG, "Waiting for handshake"); + incomingState_.waitConnectionEstablished(); + Log.v(TAG, "Querying for required interface ID"); + checkInterfaceVersion(); + Log.v(TAG, "Required interface ID is supported"); + state_ = State.CONNECTED; + Log.i(TAG, "IOIO connection established"); + } catch (ConnectionLostException e) { + Log.d(TAG, "Connection lost / aborted"); + state_ = State.DEAD; + throw e; + } catch (InterruptedException e) { + Log.e(TAG, "Unexpected exception", e); + } + } + + @Override + public synchronized void disconnect() { + Log.d(TAG, "Client requested disconnect."); + if (disconnect_) { + return; + } + disconnect_ = true; + try { + if (protocol_ != null) { + protocol_.softClose(); + } + } catch (IOException e) { + Log.e(TAG, "Soft close failed", e); + } + connection_.disconnect(); + } + + @Override + public synchronized void disconnected() { + state_ = State.DEAD; + if (disconnect_) { + return; + } + Log.d(TAG, "Physical disconnect."); + disconnect_ = true; + // The IOIOConnection doesn't necessarily know about the disconnect + connection_.disconnect(); + } + + @Override + public void waitForDisconnect() throws InterruptedException { + incomingState_.waitDisconnect(); + } + + @Override + public State getState() { + return state_; + } + + private void checkInterfaceVersion() throws IncompatibilityException, + ConnectionLostException, InterruptedException { + try { + protocol_.checkInterface(REQUIRED_INTERFACE_ID); + } catch (IOException e) { + throw new ConnectionLostException(e); + } + if (!incomingState_.waitForInterfaceSupport()) { + state_ = State.INCOMPATIBLE; + Log.e(TAG, "Required interface ID is not supported"); + throw new IncompatibilityException( + "IOIO firmware does not support required firmware: " + + new String(REQUIRED_INTERFACE_ID)); + } + } + + synchronized void removeDisconnectListener(DisconnectListener listener) { + incomingState_.removeDisconnectListener(listener); + } + + synchronized void addDisconnectListener(DisconnectListener listener) + throws ConnectionLostException { + incomingState_.addDisconnectListener(listener); + } + + synchronized void closePin(int pin) { + try { + checkState(); + if (!openPins_[pin]) { + throw new IllegalStateException("Pin not open: " + pin); + } + protocol_.setPinDigitalIn(pin, DigitalInput.Spec.Mode.FLOATING); + openPins_[pin] = false; + } catch (IOException e) { + } catch (ConnectionLostException e) { + } + } + + synchronized void closePwm(int pwmNum) { + try { + checkState(); + pwmAllocator_.releaseModule(pwmNum); + protocol_.setPwmPeriod(pwmNum, 0, IOIOProtocol.PwmScale.SCALE_1X); + } catch (IOException e) { + } catch (ConnectionLostException e) { + } + } + + synchronized void closeUart(int uartNum) { + try { + checkState(); + uartAllocator_.releaseModule(uartNum); + protocol_.uartClose(uartNum); + } catch (IOException e) { + } catch (ConnectionLostException e) { + } + } + + synchronized void closeTwi(int twiNum) { + try { + checkState(); + if (!openTwi_[twiNum]) { + throw new IllegalStateException("TWI not open: " + twiNum); + } + openTwi_[twiNum] = false; + openPins_[Constants.TWI_PINS[twiNum][0]] = false; + openPins_[Constants.TWI_PINS[twiNum][1]] = false; + protocol_.i2cClose(twiNum); + } catch (IOException e) { + } catch (ConnectionLostException e) { + } + } + + synchronized void closeIcsp() { + try { + checkState(); + if (!openIcsp_) { + throw new IllegalStateException("ICSP not open"); + } + openIcsp_ = false; + openPins_[Constants.ICSP_PINS[0]] = false; + openPins_[Constants.ICSP_PINS[1]] = false; + protocol_.icspClose(); + } catch (ConnectionLostException e) { + } catch (IOException e) { + } + } + + synchronized void closeSpi(int spiNum) { + try { + checkState(); + spiAllocator_.releaseModule(spiNum); + protocol_.spiClose(spiNum); + } catch (IOException e) { + } catch (ConnectionLostException e) { + } + } + + synchronized void closeIncap(int incapNum, boolean doublePrecision) { + try { + checkState(); + if (doublePrecision) { + incapAllocatorDouble_.releaseModule(incapNum); + } else { + incapAllocatorSingle_.releaseModule(incapNum); + } + protocol_.incapClose(incapNum, doublePrecision); + } catch (IOException e) { + } catch (ConnectionLostException e) { + } + } + + @Override + synchronized public void softReset() throws ConnectionLostException { + checkState(); + try { + protocol_.softReset(); + } catch (IOException e) { + throw new ConnectionLostException(e); + } + } + + @Override + synchronized public void hardReset() throws ConnectionLostException { + checkState(); + try { + protocol_.hardReset(); + } catch (IOException e) { + throw new ConnectionLostException(e); + } + } + + @Override + public String getImplVersion(VersionType v) throws ConnectionLostException { + if (state_ == State.INIT) { + throw new IllegalStateException( + "Connection has not yet been established"); + } + switch (v) { + case HARDWARE_VER: + return incomingState_.hardwareId_; + case BOOTLOADER_VER: + return incomingState_.bootloaderId_; + case APP_FIRMWARE_VER: + return incomingState_.firmwareId_; + case IOIOLIB_VER: + return "IOIO0326"; + } + return null; + } + + @Override + public DigitalInput openDigitalInput(int pin) + throws ConnectionLostException { + return openDigitalInput(new DigitalInput.Spec(pin)); + } + + @Override + public DigitalInput openDigitalInput(int pin, Mode mode) + throws ConnectionLostException { + return openDigitalInput(new DigitalInput.Spec(pin, mode)); + } + + @Override + synchronized public DigitalInput openDigitalInput(DigitalInput.Spec spec) + throws ConnectionLostException { + checkState(); + PinFunctionMap.checkValidPin(spec.pin); + checkPinFree(spec.pin); + DigitalInputImpl result = new DigitalInputImpl(this, spec.pin); + addDisconnectListener(result); + openPins_[spec.pin] = true; + incomingState_.addInputPinListener(spec.pin, result); + try { + protocol_.setPinDigitalIn(spec.pin, spec.mode); + protocol_.setChangeNotify(spec.pin, true); + } catch (IOException e) { + result.close(); + throw new ConnectionLostException(e); + } + return result; + } + + @Override + public DigitalOutput openDigitalOutput(int pin, + ioio.lib.api.DigitalOutput.Spec.Mode mode, boolean startValue) + throws ConnectionLostException { + return openDigitalOutput(new DigitalOutput.Spec(pin, mode), startValue); + } + + @Override + synchronized public DigitalOutput openDigitalOutput( + DigitalOutput.Spec spec, boolean startValue) + throws ConnectionLostException { + checkState(); + PinFunctionMap.checkValidPin(spec.pin); + checkPinFree(spec.pin); + DigitalOutputImpl result = new DigitalOutputImpl(this, spec.pin, startValue); + addDisconnectListener(result); + openPins_[spec.pin] = true; + try { + protocol_.setPinDigitalOut(spec.pin, startValue, spec.mode); + } catch (IOException e) { + result.close(); + throw new ConnectionLostException(e); + } + return result; + } + + @Override + public DigitalOutput openDigitalOutput(int pin, boolean startValue) + throws ConnectionLostException { + return openDigitalOutput(new DigitalOutput.Spec(pin), startValue); + } + + @Override + public DigitalOutput openDigitalOutput(int pin) + throws ConnectionLostException { + return openDigitalOutput(new DigitalOutput.Spec(pin), false); + } + + @Override + synchronized public AnalogInput openAnalogInput(int pin) + throws ConnectionLostException { + checkState(); + PinFunctionMap.checkSupportsAnalogInput(pin); + checkPinFree(pin); + AnalogInputImpl result = new AnalogInputImpl(this, pin); + addDisconnectListener(result); + openPins_[pin] = true; + incomingState_.addInputPinListener(pin, result); + try { + protocol_.setPinAnalogIn(pin); + protocol_.setAnalogInSampling(pin, true); + } catch (IOException e) { + result.close(); + throw new ConnectionLostException(e); + } + return result; + } + + @Override + public PwmOutput openPwmOutput(int pin, int freqHz) + throws ConnectionLostException { + return openPwmOutput(new DigitalOutput.Spec(pin), freqHz); + } + + @Override + synchronized public PwmOutput openPwmOutput(DigitalOutput.Spec spec, + int freqHz) throws ConnectionLostException { + checkState(); + PinFunctionMap.checkSupportsPeripheralOutput(spec.pin); + checkPinFree(spec.pin); + int pwmNum = pwmAllocator_.allocateModule(); + + int scale = 0; + float baseUs; + int period; + while (true) { + final int clk = 16000000 / IOIOProtocol.PwmScale.values()[scale].scale; + period = clk / freqHz; + if (period <= 65536) { + baseUs = 1000000.0f / clk; + break; + } + if (++scale >= PwmScale.values().length) { + throw new IllegalArgumentException("Frequency too low: " + + freqHz); + } + } + + PwmImpl pwm = new PwmImpl(this, spec.pin, pwmNum, period, baseUs); + addDisconnectListener(pwm); + openPins_[spec.pin] = true; + try { + protocol_.setPinDigitalOut(spec.pin, false, spec.mode); + protocol_.setPinPwm(spec.pin, pwmNum, true); + protocol_.setPwmPeriod(pwmNum, period - 1, + IOIOProtocol.PwmScale.values()[scale]); + } catch (IOException e) { + pwm.close(); + throw new ConnectionLostException(e); + } + return pwm; + } + + @Override + public Uart openUart(int rx, int tx, int baud, Uart.Parity parity, + Uart.StopBits stopbits) throws ConnectionLostException { + return openUart(rx == INVALID_PIN ? null : new DigitalInput.Spec(rx), + tx == INVALID_PIN ? null : new DigitalOutput.Spec(tx), baud, + parity, stopbits); + } + + @Override + synchronized public Uart openUart(DigitalInput.Spec rx, + DigitalOutput.Spec tx, int baud, Uart.Parity parity, + Uart.StopBits stopbits) throws ConnectionLostException { + checkState(); + if (rx != null) { + PinFunctionMap.checkSupportsPeripheralInput(rx.pin); + checkPinFree(rx.pin); + } + if (tx != null) { + PinFunctionMap.checkSupportsPeripheralOutput(tx.pin); + checkPinFree(tx.pin); + } + int rxPin = rx != null ? rx.pin : INVALID_PIN; + int txPin = tx != null ? tx.pin : INVALID_PIN; + int uartNum = uartAllocator_.allocateModule(); + UartImpl uart = new UartImpl(this, txPin, rxPin, uartNum); + addDisconnectListener(uart); + incomingState_.addUartListener(uartNum, uart); + try { + if (rx != null) { + openPins_[rx.pin] = true; + protocol_.setPinDigitalIn(rx.pin, rx.mode); + protocol_.setPinUart(rx.pin, uartNum, false, true); + } + if (tx != null) { + openPins_[tx.pin] = true; + protocol_.setPinDigitalOut(tx.pin, true, tx.mode); + protocol_.setPinUart(tx.pin, uartNum, true, true); + } + boolean speed4x = true; + int rate = Math.round(4000000.0f / baud) - 1; + if (rate > 65535) { + speed4x = false; + rate = Math.round(1000000.0f / baud) - 1; + } + protocol_.uartConfigure(uartNum, rate, speed4x, stopbits, parity); + } catch (IOException e) { + uart.close(); + throw new ConnectionLostException(e); + } + return uart; + } + + @Override + synchronized public TwiMaster openTwiMaster(int twiNum, Rate rate, + boolean smbus) throws ConnectionLostException { + checkState(); + checkTwiFree(twiNum); + checkPinFree(Constants.TWI_PINS[twiNum][0]); + checkPinFree(Constants.TWI_PINS[twiNum][1]); + openPins_[Constants.TWI_PINS[twiNum][0]] = true; + openPins_[Constants.TWI_PINS[twiNum][1]] = true; + openTwi_[twiNum] = true; + TwiMasterImpl twi = new TwiMasterImpl(this, twiNum); + addDisconnectListener(twi); + incomingState_.addTwiListener(twiNum, twi); + try { + protocol_.i2cConfigureMaster(twiNum, rate, smbus); + } catch (IOException e) { + twi.close(); + throw new ConnectionLostException(e); + } + return twi; + } + + @Override + synchronized public IcspMaster openIcspMaster() + throws ConnectionLostException { + checkState(); + checkIcspFree(); + checkPinFree(Constants.ICSP_PINS[0]); + checkPinFree(Constants.ICSP_PINS[1]); + checkPinFree(Constants.ICSP_PINS[2]); + openPins_[Constants.ICSP_PINS[0]] = true; + openPins_[Constants.ICSP_PINS[1]] = true; + openPins_[Constants.ICSP_PINS[2]] = true; + openIcsp_ = true; + IcspMasterImpl icsp = new IcspMasterImpl(this); + addDisconnectListener(icsp); + incomingState_.addIcspListener(icsp); + try { + protocol_.icspOpen(); + } catch (IOException e) { + icsp.close(); + throw new ConnectionLostException(e); + } + return icsp; + } + + @Override + public SpiMaster openSpiMaster(int miso, int mosi, int clk, + int slaveSelect, SpiMaster.Rate rate) + throws ConnectionLostException { + return openSpiMaster(miso, mosi, clk, new int[] { slaveSelect }, rate); + } + + @Override + public SpiMaster openSpiMaster(int miso, int mosi, int clk, + int[] slaveSelect, SpiMaster.Rate rate) + throws ConnectionLostException { + DigitalOutput.Spec[] slaveSpecs = new DigitalOutput.Spec[slaveSelect.length]; + for (int i = 0; i < slaveSelect.length; ++i) { + slaveSpecs[i] = new DigitalOutput.Spec(slaveSelect[i]); + } + return openSpiMaster(new DigitalInput.Spec(miso, Mode.PULL_UP), + new DigitalOutput.Spec(mosi), new DigitalOutput.Spec(clk), + slaveSpecs, new SpiMaster.Config(rate)); + } + + @Override + synchronized public SpiMaster openSpiMaster(DigitalInput.Spec miso, + DigitalOutput.Spec mosi, DigitalOutput.Spec clk, + DigitalOutput.Spec[] slaveSelect, SpiMaster.Config config) + throws ConnectionLostException { + checkState(); + int ssPins[] = new int[slaveSelect.length]; + checkPinFree(miso.pin); + PinFunctionMap.checkSupportsPeripheralInput(miso.pin); + checkPinFree(mosi.pin); + PinFunctionMap.checkSupportsPeripheralOutput(mosi.pin); + checkPinFree(clk.pin); + PinFunctionMap.checkSupportsPeripheralOutput(clk.pin); + for (int i = 0; i < slaveSelect.length; ++i) { + checkPinFree(slaveSelect[i].pin); + ssPins[i] = slaveSelect[i].pin; + } + + int spiNum = spiAllocator_.allocateModule(); + SpiMasterImpl spi = new SpiMasterImpl(this, spiNum, mosi.pin, miso.pin, + clk.pin, ssPins); + addDisconnectListener(spi); + + openPins_[miso.pin] = true; + openPins_[mosi.pin] = true; + openPins_[clk.pin] = true; + for (int i = 0; i < slaveSelect.length; ++i) { + openPins_[slaveSelect[i].pin] = true; + } + + incomingState_.addSpiListener(spiNum, spi); + try { + protocol_.setPinDigitalIn(miso.pin, miso.mode); + protocol_.setPinSpi(miso.pin, 1, true, spiNum); + protocol_.setPinDigitalOut(mosi.pin, true, mosi.mode); + protocol_.setPinSpi(mosi.pin, 0, true, spiNum); + protocol_.setPinDigitalOut(clk.pin, config.invertClk, clk.mode); + protocol_.setPinSpi(clk.pin, 2, true, spiNum); + for (DigitalOutput.Spec spec : slaveSelect) { + protocol_.setPinDigitalOut(spec.pin, true, spec.mode); + } + protocol_.spiConfigureMaster(spiNum, config); + } catch (IOException e) { + spi.close(); + throw new ConnectionLostException(e); + } + return spi; + } + + @Override + public PulseInput openPulseInput(Spec spec, ClockRate rate, PulseMode mode, + boolean doublePrecision) throws ConnectionLostException { + checkState(); + checkPinFree(spec.pin); + PinFunctionMap.checkSupportsPeripheralInput(spec.pin); + int incapNum = doublePrecision ? incapAllocatorDouble_.allocateModule() + : incapAllocatorSingle_.allocateModule(); + IncapImpl incap = new IncapImpl(this, mode, incapNum, spec.pin, + rate.hertz, mode.scaling, doublePrecision); + addDisconnectListener(incap); + incomingState_.addIncapListener(incapNum, incap); + openPins_[spec.pin] = true; + try { + protocol_.setPinDigitalIn(spec.pin, spec.mode); + protocol_.setPinIncap(spec.pin, incapNum, true); + protocol_.incapConfigure(incapNum, doublePrecision, + mode.ordinal() + 1, rate.ordinal()); + } catch (IOException e) { + incap.close(); + throw new ConnectionLostException(e); + } + return incap; + } + + @Override + public PulseInput openPulseInput(int pin, PulseMode mode) + throws ConnectionLostException { + return openPulseInput(new DigitalInput.Spec(pin), ClockRate.RATE_16MHz, + mode, true); + } + + private void checkPinFree(int pin) { + if (openPins_[pin]) { + throw new IllegalArgumentException("Pin already open: " + pin); + } + } + + private void checkTwiFree(int twi) { + if (openTwi_[twi]) { + throw new IllegalArgumentException("TWI already open: " + twi); + } + } + + private void checkIcspFree() { + if (openIcsp_) { + throw new IllegalArgumentException("ICSP already open"); + } + } + + private void checkState() throws ConnectionLostException { + if (state_ == State.DEAD) { + throw new ConnectionLostException(); + } + if (state_ == State.INCOMPATIBLE) { + throw new IllegalStateException( + "Incompatibility has been reported - IOIO cannot be used"); + } + if (state_ != State.CONNECTED) { + throw new IllegalStateException( + "Connection has not yet been established"); + } + } + + @Override + public synchronized void beginBatch() throws ConnectionLostException { + checkState(); + protocol_.beginBatch(); + } + + @Override + public synchronized void endBatch() throws ConnectionLostException { + checkState(); + try { + protocol_.endBatch(); + } catch (IOException e) { + throw new ConnectionLostException(e); + } + } +} diff --git a/IOIOLib/src/ioio/lib/impl/IOIOProtocol.java b/IOIOLib/src/ioio/lib/impl/IOIOProtocol.java index 95ac03a..6afb210 100644 --- a/IOIOLib/src/ioio/lib/impl/IOIOProtocol.java +++ b/IOIOLib/src/ioio/lib/impl/IOIOProtocol.java @@ -1,857 +1,862 @@ -/* - * Copyright 2011 Ytai Ben-Tsvi. All rights reserved. - * - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARSHAN POURSOHI OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied. - */ -package ioio.lib.impl; - -import ioio.lib.api.DigitalInput; -import ioio.lib.api.DigitalOutput; -import ioio.lib.api.SpiMaster; -import ioio.lib.api.TwiMaster.Rate; -import ioio.lib.api.Uart; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - -import android.util.Log; - -class IOIOProtocol { - static final int HARD_RESET = 0x00; - static final int ESTABLISH_CONNECTION = 0x00; - static final int SOFT_RESET = 0x01; - static final int CHECK_INTERFACE = 0x02; - static final int CHECK_INTERFACE_RESPONSE = 0x02; - static final int SET_PIN_DIGITAL_OUT = 0x03; - static final int SET_DIGITAL_OUT_LEVEL = 0x04; - static final int REPORT_DIGITAL_IN_STATUS = 0x04; - static final int SET_PIN_DIGITAL_IN = 0x05; - static final int REPORT_PERIODIC_DIGITAL_IN_STATUS = 0x05; - static final int SET_CHANGE_NOTIFY = 0x06; - static final int REGISTER_PERIODIC_DIGITAL_SAMPLING = 0x07; - static final int SET_PIN_PWM = 0x08; - static final int SET_PWM_DUTY_CYCLE = 0x09; - static final int SET_PWM_PERIOD = 0x0A; - static final int SET_PIN_ANALOG_IN = 0x0B; - static final int REPORT_ANALOG_IN_STATUS = 0x0B; - static final int SET_ANALOG_IN_SAMPLING = 0x0C; - static final int REPORT_ANALOG_IN_FORMAT = 0x0C; - static final int UART_CONFIG = 0x0D; - static final int UART_STATUS = 0x0D; - static final int UART_DATA = 0x0E; - static final int SET_PIN_UART = 0x0F; - static final int UART_REPORT_TX_STATUS = 0x0F; - static final int SPI_CONFIGURE_MASTER = 0x10; - static final int SPI_STATUS = 0x10; - static final int SPI_MASTER_REQUEST = 0x11; - static final int SPI_DATA = 0x11; - static final int SET_PIN_SPI = 0x12; - static final int SPI_REPORT_TX_STATUS = 0x12; - static final int I2C_CONFIGURE_MASTER = 0x13; - static final int I2C_STATUS = 0x13; - static final int I2C_WRITE_READ = 0x14; - static final int I2C_RESULT = 0x14; - static final int I2C_REPORT_TX_STATUS = 0x15; - static final int ICSP_SIX = 0x16; - static final int ICSP_REPORT_RX_STATUS = 0x16; - static final int ICSP_REGOUT = 0x17; - static final int ICSP_RESULT = 0x17; - static final int ICSP_PROG_ENTER = 0x18; - static final int ICSP_PROG_EXIT = 0x19; - static final int ICSP_CONFIG = 0x1A; - static final int INCAP_CONFIGURE = 0x1B; - static final int INCAP_STATUS = 0x1B; - static final int SET_PIN_INCAP = 0x1C; - static final int INCAP_REPORT = 0x1C; - static final int SOFT_CLOSE = 0x1D; - - static final int[] SCALE_DIV = new int[] { - 0x1F, // 31.25 - 0x1E, // 35.714 - 0x1D, // 41.667 - 0x1C, // 50 - 0x1B, // 62.5 - 0x1A, // 83.333 - 0x17, // 125 - 0x16, // 142.857 - 0x15, // 166.667 - 0x14, // 200 - 0x13, // 250 - 0x12, // 333.333 - 0x0F, // 500 - 0x0E, // 571.429 - 0x0D, // 666.667 - 0x0C, // 800 - 0x0B, // 1000 - 0x0A, // 1333.333 - 0x07, // 2000 - 0x06, // 2285.714 - 0x05, // 2666.667 - 0x04, // 3200 - 0x03, // 4000 - 0x02, // 5333.333 - 0x01 // 8000 - }; - - private static final String TAG = "IOIOProtocol"; - - enum PwmScale { - SCALE_1X(1, 0), SCALE_8X(8, 3), SCALE_64X(64, 2), SCALE_256X(256, 1); - - public final int scale; - private final int encoding; - - PwmScale(int scale, int encoding) { - this.scale = scale; - this.encoding = encoding; - } - } - - private byte[] outbuf_ = new byte[256]; - private int pos_ = 0; - private int batchCounter_ = 0; - - private void writeByte(int b) throws IOException { - assert (b >= 0 && b < 256); - if (pos_ == outbuf_.length) { - // buffer is full - flush(); - } - //Log.v(TAG, "sending: 0x" + Integer.toHexString(b)); - outbuf_[pos_++] = (byte) b; - } - - public synchronized void beginBatch() { - ++batchCounter_; - } - - public synchronized void endBatch() throws IOException { - if (--batchCounter_ == 0) { - flush(); - } - } - - private void flush() throws IOException { - try { - out_.write(outbuf_, 0, pos_); - } finally { - pos_ = 0; - } - } - - private void writeTwoBytes(int i) throws IOException { - writeByte(i & 0xFF); - writeByte(i >> 8); - } - - private void writeThreeBytes(int i) throws IOException { - writeByte(i & 0xFF); - writeByte((i >> 8) & 0xFF); - writeByte((i >> 16) & 0xFF); - } - - synchronized public void hardReset() throws IOException { - beginBatch(); - writeByte(HARD_RESET); - writeByte('I'); - writeByte('O'); - writeByte('I'); - writeByte('O'); - endBatch(); - } - - synchronized public void softReset() throws IOException { - beginBatch(); - writeByte(SOFT_RESET); - endBatch(); - } - - synchronized public void softClose() throws IOException { - beginBatch(); - writeByte(SOFT_CLOSE); - endBatch(); - } - - synchronized public void checkInterface(byte[] interfaceId) - throws IOException { - if (interfaceId.length != 8) { - throw new IllegalArgumentException( - "interface ID must be exactly 8 bytes long"); - } - beginBatch(); - writeByte(CHECK_INTERFACE); - for (int i = 0; i < 8; ++i) { - writeByte(interfaceId[i]); - } - endBatch(); - } - - synchronized public void setDigitalOutLevel(int pin, boolean level) - throws IOException { - beginBatch(); - writeByte(SET_DIGITAL_OUT_LEVEL); - writeByte(pin << 2 | (level ? 1 : 0)); - endBatch(); - } - - synchronized public void setPinPwm(int pin, int pwmNum, boolean enable) - throws IOException { - beginBatch(); - writeByte(SET_PIN_PWM); - writeByte(pin & 0x3F); - writeByte((enable ? 0x80 : 0x00) | (pwmNum & 0x0F)); - endBatch(); - } - - synchronized public void setPwmDutyCycle(int pwmNum, int dutyCycle, - int fraction) throws IOException { - beginBatch(); - writeByte(SET_PWM_DUTY_CYCLE); - writeByte(pwmNum << 2 | fraction); - writeTwoBytes(dutyCycle); - endBatch(); - } - - synchronized public void setPwmPeriod(int pwmNum, int period, PwmScale scale) - throws IOException { - beginBatch(); - writeByte(SET_PWM_PERIOD); - writeByte(((scale.encoding & 0x02) << 6) | (pwmNum << 1) - | (scale.encoding & 0x01)); - writeTwoBytes(period); - endBatch(); - } - - synchronized public void setPinIncap(int pin, int incapNum, boolean enable) - throws IOException { - beginBatch(); - writeByte(SET_PIN_INCAP); - writeByte(pin); - writeByte(incapNum | (enable ? 0x80 : 0x00)); - endBatch(); - } - - synchronized public void incapClose(int incapNum) throws IOException { - beginBatch(); - writeByte(INCAP_CONFIGURE); - writeByte(incapNum); - writeByte(0x00); - endBatch(); - } - - synchronized public void incapConfigure(int incapNum, boolean double_prec, - int mode, int clock) throws IOException { - beginBatch(); - writeByte(INCAP_CONFIGURE); - writeByte(incapNum); - writeByte((double_prec ? 0x80 : 0x00) | (mode << 3) | clock); - endBatch(); - } - - synchronized public void i2cWriteRead(int i2cNum, boolean tenBitAddr, - int address, int writeSize, int readSize, byte[] writeData) - throws IOException { - beginBatch(); - writeByte(I2C_WRITE_READ); - writeByte(((address >> 8) << 6) | (tenBitAddr ? 0x20 : 0x00) | i2cNum); - writeByte(address & 0xFF); - writeByte(writeSize); - writeByte(readSize); - for (int i = 0; i < writeSize; ++i) { - writeByte(((int) writeData[i]) & 0xFF); - } - endBatch(); - } - - synchronized public void setPinDigitalOut(int pin, boolean value, - DigitalOutput.Spec.Mode mode) throws IOException { - beginBatch(); - writeByte(SET_PIN_DIGITAL_OUT); - writeByte((pin << 2) - | (mode == DigitalOutput.Spec.Mode.OPEN_DRAIN ? 0x01 : 0x00) - | (value ? 0x02 : 0x00)); - endBatch(); - } - - synchronized public void setPinDigitalIn(int pin, - DigitalInput.Spec.Mode mode) throws IOException { - int pull = 0; - if (mode == DigitalInput.Spec.Mode.PULL_UP) { - pull = 1; - } else if (mode == DigitalInput.Spec.Mode.PULL_DOWN) { - pull = 2; - } - beginBatch(); - writeByte(SET_PIN_DIGITAL_IN); - writeByte((pin << 2) | pull); - endBatch(); - } - - synchronized public void setChangeNotify(int pin, boolean changeNotify) - throws IOException { - beginBatch(); - writeByte(SET_CHANGE_NOTIFY); - writeByte((pin << 2) | (changeNotify ? 0x01 : 0x00)); - endBatch(); - } - - synchronized public void registerPeriodicDigitalSampling(int pin, - int freqScale) throws IOException { - // TODO: implement - } - - synchronized public void setPinAnalogIn(int pin) throws IOException { - beginBatch(); - writeByte(SET_PIN_ANALOG_IN); - writeByte(pin); - endBatch(); - } - - synchronized public void setAnalogInSampling(int pin, boolean enable) - throws IOException { - beginBatch(); - writeByte(SET_ANALOG_IN_SAMPLING); - writeByte((enable ? 0x80 : 0x00) | (pin & 0x3F)); - endBatch(); - } - - synchronized public void uartData(int uartNum, int numBytes, byte data[]) - throws IOException { - if (numBytes > 64) { - throw new IllegalArgumentException( - "A maximum of 64 bytes can be sent in one uartData message. Got: " - + numBytes); - } - beginBatch(); - writeByte(UART_DATA); - writeByte((numBytes - 1) | uartNum << 6); - for (int i = 0; i < numBytes; ++i) { - writeByte(((int) data[i]) & 0xFF); - } - endBatch(); - } - - synchronized public void uartConfigure(int uartNum, int rate, - boolean speed4x, Uart.StopBits stopbits, Uart.Parity parity) - throws IOException { - int parbits = parity == Uart.Parity.EVEN ? 1 - : (parity == Uart.Parity.ODD ? 2 : 0); - beginBatch(); - writeByte(UART_CONFIG); - writeByte((uartNum << 6) | (speed4x ? 0x08 : 0x00) - | (stopbits == Uart.StopBits.TWO ? 0x04 : 0x00) | parbits); - writeTwoBytes(rate); - endBatch(); - } - - synchronized public void uartClose(int uartNum) throws IOException { - beginBatch(); - writeByte(UART_CONFIG); - writeByte(uartNum << 6); - writeTwoBytes(0); - endBatch(); - } - - synchronized public void setPinUart(int pin, int uartNum, boolean tx, - boolean enable) throws IOException { - beginBatch(); - writeByte(SET_PIN_UART); - writeByte(pin); - writeByte((enable ? 0x80 : 0x00) | (tx ? 0x40 : 0x00) | uartNum); - endBatch(); - } - - synchronized public void spiConfigureMaster(int spiNum, - SpiMaster.Config config) throws IOException { - beginBatch(); - writeByte(SPI_CONFIGURE_MASTER); - writeByte((spiNum << 5) | SCALE_DIV[config.rate.ordinal()]); - writeByte((config.sampleOnTrailing ? 0x00 : 0x02) - | (config.invertClk ? 0x01 : 0x00)); - endBatch(); - } - - synchronized public void spiClose(int spiNum) throws IOException { - beginBatch(); - writeByte(SPI_CONFIGURE_MASTER); - writeByte(spiNum << 5); - writeByte(0x00); - endBatch(); - } - - synchronized public void setPinSpi(int pin, int mode, boolean enable, - int spiNum) throws IOException { - beginBatch(); - writeByte(SET_PIN_SPI); - writeByte(pin); - writeByte((1 << 4) | (mode << 2) | spiNum); - endBatch(); - } - - synchronized public void spiMasterRequest(int spiNum, int ssPin, - byte data[], int dataBytes, int totalBytes, int responseBytes) - throws IOException { - final boolean dataNeqTotal = (dataBytes != totalBytes); - final boolean resNeqTotal = (responseBytes != totalBytes); - beginBatch(); - writeByte(SPI_MASTER_REQUEST); - writeByte((spiNum << 6) | ssPin); - writeByte((dataNeqTotal ? 0x80 : 0x00) | (resNeqTotal ? 0x40 : 0x00) - | totalBytes - 1); - if (dataNeqTotal) { - writeByte(dataBytes); - } - if (resNeqTotal) { - writeByte(responseBytes); - } - for (int i = 0; i < dataBytes; ++i) { - writeByte(((int) data[i]) & 0xFF); - } - endBatch(); - } - - synchronized public void i2cConfigureMaster(int i2cNum, Rate rate, - boolean smbusLevels) throws IOException { - int rateBits = (rate == Rate.RATE_1MHz ? 3 - : (rate == Rate.RATE_400KHz ? 2 : 1)); - beginBatch(); - writeByte(I2C_CONFIGURE_MASTER); - writeByte((smbusLevels ? 0x80 : 0) | (rateBits << 5) | i2cNum); - endBatch(); - } - - synchronized public void i2cClose(int i2cNum) throws IOException { - beginBatch(); - writeByte(I2C_CONFIGURE_MASTER); - writeByte(i2cNum); - endBatch(); - } - - public void icspOpen() throws IOException { - beginBatch(); - writeByte(ICSP_CONFIG); - writeByte(0x01); - endBatch(); - } - - public void icspClose() throws IOException { - beginBatch(); - writeByte(ICSP_CONFIG); - writeByte(0x00); - endBatch(); - } - - public void icspEnter() throws IOException { - beginBatch(); - writeByte(ICSP_PROG_ENTER); - endBatch(); - } - - public void icspExit() throws IOException { - beginBatch(); - writeByte(ICSP_PROG_EXIT); - endBatch(); - } - - public void icspSix(int instruction) throws IOException { - beginBatch(); - writeByte(ICSP_SIX); - writeThreeBytes(instruction); - endBatch(); - } - - public void icspRegout() throws IOException { - beginBatch(); - writeByte(ICSP_REGOUT); - endBatch(); - } - - public interface IncomingHandler { - public void handleEstablishConnection(byte[] hardwareId, - byte[] bootloaderId, byte[] firmwareId); - - public void handleConnectionLost(); - - public void handleSoftReset(); - - public void handleCheckInterfaceResponse(boolean supported); - - public void handleSetChangeNotify(int pin, boolean changeNotify); - - public void handleReportDigitalInStatus(int pin, boolean level); - - public void handleRegisterPeriodicDigitalSampling(int pin, int freqScale); - - public void handleReportPeriodicDigitalInStatus(int frameNum, - boolean values[]); - - public void handleAnalogPinStatus(int pin, boolean open); - - public void handleReportAnalogInStatus(int pins[], int values[]); - - public void handleUartOpen(int uartNum); - - public void handleUartClose(int uartNum); - - public void handleUartData(int uartNum, int numBytes, byte data[]); - - public void handleUartReportTxStatus(int uartNum, int bytesRemaining); - - public void handleSpiOpen(int spiNum); - - public void handleSpiClose(int spiNum); - - public void handleSpiData(int spiNum, int ssPin, byte data[], - int dataBytes); - - public void handleSpiReportTxStatus(int spiNum, int bytesRemaining); - - public void handleI2cOpen(int i2cNum); - - public void handleI2cClose(int i2cNum); - - public void handleI2cResult(int i2cNum, int size, byte[] data); - - public void handleI2cReportTxStatus(int spiNum, int bytesRemaining); - - void handleIcspOpen(); - - void handleIcspClose(); - - void handleIcspReportRxStatus(int bytesRemaining); - - void handleIcspResult(int size, byte[] data); - - public void handleIncapReport(int incapNum, int size, byte[] data); - - public void handleIncapClose(int incapNum); - - public void handleIncapOpen(int incapNum); - } - - class IncomingThread extends Thread { - private int readOffset_ = 0; - private int validBytes_ = 0; - private byte[] inbuf_ = new byte[64]; - - private int[] analogFramePins_ = new int[0]; - private Set removedPins_ = new HashSet( - Constants.NUM_ANALOG_PINS); - private Set addedPins_ = new HashSet( - Constants.NUM_ANALOG_PINS); - - private void findDelta(int[] newPins) { - removedPins_.clear(); - addedPins_.clear(); - for (int i : analogFramePins_) { - removedPins_.add(i); - } - for (int i : newPins) { - addedPins_.add(i); - } - for (Iterator it = removedPins_.iterator(); it.hasNext();) { - Integer current = it.next(); - if (addedPins_.contains(current)) { - it.remove(); - addedPins_.remove(current); - } - } - } - - private void fillBuf() throws IOException { - try { - validBytes_ = in_.read(inbuf_, 0, inbuf_.length); - if (validBytes_ <= 0) { - throw new IOException("Unexpected stream closure"); - } - //Log.v(TAG, "received " + validBytes_ + " bytes"); - readOffset_ = 0; - } catch (IOException e) { - Log.i(TAG, "IOIO disconnected"); - throw e; - } - } - - private int readByte() throws IOException { - if (readOffset_ == validBytes_) { - fillBuf(); - } - int b = inbuf_[readOffset_++]; - b &= 0xFF; // make unsigned - //Log.v(TAG, "received: 0x" + Integer.toHexString(b)); - return b; - } - - private void readBytes(int size, byte[] buffer) throws IOException { - for (int i = 0; i < size; ++i) { - buffer[i] = (byte) readByte(); - } - } - - @Override - public void run() { - super.run(); - setPriority(MAX_PRIORITY); - int arg1; - int arg2; - int numPins; - int size; - byte[] data = new byte[256]; - try { - while (true) { - switch (arg1 = readByte()) { - case ESTABLISH_CONNECTION: - if (readByte() != 'I' || readByte() != 'O' - || readByte() != 'I' || readByte() != 'O') { - throw new IOException( - "Bad establish connection magic"); - } - byte[] hardwareId = new byte[8]; - byte[] bootloaderId = new byte[8]; - byte[] firmwareId = new byte[8]; - readBytes(8, hardwareId); - readBytes(8, bootloaderId); - readBytes(8, firmwareId); - - handler_.handleEstablishConnection(hardwareId, - bootloaderId, firmwareId); - break; - - case SOFT_RESET: - handler_.handleSoftReset(); - break; - - case REPORT_DIGITAL_IN_STATUS: - arg1 = readByte(); - handler_.handleReportDigitalInStatus(arg1 >> 2, - (arg1 & 0x01) == 1); - break; - - case SET_CHANGE_NOTIFY: - arg1 = readByte(); - handler_.handleSetChangeNotify(arg1 >> 2, - (arg1 & 0x01) == 1); - break; - - case REGISTER_PERIODIC_DIGITAL_SAMPLING: - // TODO: implement - break; - - case REPORT_PERIODIC_DIGITAL_IN_STATUS: - // TODO: implement - break; - - case REPORT_ANALOG_IN_FORMAT: - numPins = readByte(); - int[] newFormat = new int[numPins]; - for (int i = 0; i < numPins; ++i) { - newFormat[i] = readByte(); - } - findDelta(newFormat); - for (Integer i : removedPins_) { - handler_.handleAnalogPinStatus(i, false); - } - for (Integer i : addedPins_) { - handler_.handleAnalogPinStatus(i, true); - } - analogFramePins_ = newFormat; - break; - - case REPORT_ANALOG_IN_STATUS: - numPins = analogFramePins_.length; - int header = 0; - int[] values = new int[numPins]; - for (int i = 0; i < numPins; ++i) { - if (i % 4 == 0) { - header = readByte(); - } - values[i] = (readByte() << 2) | (header & 0x03); - header >>= 2; - } - handler_.handleReportAnalogInStatus(analogFramePins_, - values); - break; - - case UART_REPORT_TX_STATUS: - arg1 = readByte(); - arg2 = readByte(); - handler_.handleUartReportTxStatus(arg1 & 0x03, - (arg1 >> 2) | (arg2 << 6)); - break; - - case UART_DATA: - arg1 = readByte(); - for (int i = 0; i < (arg1 & 0x3F) + 1; ++i) { - data[i] = (byte) readByte(); - } - handler_.handleUartData(arg1 >> 6, (arg1 & 0x3F) + 1, - data); - break; - - case UART_STATUS: - arg1 = readByte(); - if ((arg1 & 0x80) != 0) { - handler_.handleUartOpen(arg1 & 0x03); - } else { - handler_.handleUartClose(arg1 & 0x03); - } - break; - - case SPI_DATA: - arg1 = readByte(); - arg2 = readByte(); - for (int i = 0; i < (arg1 & 0x3F) + 1; ++i) { - data[i] = (byte) readByte(); - } - handler_.handleSpiData(arg1 >> 6, arg2 & 0x3F, data, - (arg1 & 0x3F) + 1); - break; - - case SPI_REPORT_TX_STATUS: - arg1 = readByte(); - arg2 = readByte(); - handler_.handleSpiReportTxStatus(arg1 & 0x03, - (arg1 >> 2) | (arg2 << 6)); - break; - - case SPI_STATUS: - arg1 = readByte(); - if ((arg1 & 0x80) != 0) { - handler_.handleSpiOpen(arg1 & 0x03); - } else { - handler_.handleSpiClose(arg1 & 0x03); - } - break; - - case I2C_STATUS: - arg1 = readByte(); - if ((arg1 & 0x80) != 0) { - handler_.handleI2cOpen(arg1 & 0x03); - } else { - handler_.handleI2cClose(arg1 & 0x03); - } - break; - - case I2C_RESULT: - arg1 = readByte(); - arg2 = readByte(); - if (arg2 != 0xFF) { - for (int i = 0; i < arg2; ++i) { - data[i] = (byte) readByte(); - } - } - handler_.handleI2cResult(arg1 & 0x03, arg2, data); - break; - - case I2C_REPORT_TX_STATUS: - arg1 = readByte(); - arg2 = readByte(); - handler_.handleI2cReportTxStatus(arg1 & 0x03, - (arg1 >> 2) | (arg2 << 6)); - break; - - case CHECK_INTERFACE_RESPONSE: - arg1 = readByte(); - handler_.handleCheckInterfaceResponse((arg1 & 0x01) == 1); - break; - - case ICSP_REPORT_RX_STATUS: - arg1 = readByte(); - arg2 = readByte(); - handler_.handleIcspReportRxStatus(arg1 | (arg2 << 8)); - break; - - case ICSP_RESULT: - data[0] = (byte) readByte(); - data[1] = (byte) readByte(); - handler_.handleIcspResult(2, data); - break; - - case ICSP_CONFIG: - arg1 = readByte(); - if ((arg1 & 0x01) == 1) { - handler_.handleIcspOpen(); - } else { - handler_.handleIcspClose(); - } - break; - - case INCAP_STATUS: - arg1 = readByte(); - if ((arg1 & 0x80) != 0) { - handler_.handleIncapOpen(arg1 & 0x0F); - } else { - handler_.handleIncapClose(arg1 & 0x0F); - } - break; - - case INCAP_REPORT: - arg1 = readByte(); - size = arg1 >> 6; - if (size == 0) { - size = 4; - } - readBytes(size, data); - handler_.handleIncapReport(arg1 & 0x0F, size, data); - break; - - case SOFT_CLOSE: - Log.d(TAG, "Received soft close."); - throw new IOException("Soft close"); - - - default: - in_.close(); - IOException e = new IOException( - "Received unexpected command: 0x" - + Integer.toHexString(arg1)); - Log.e("IOIOProtocol", "Protocol error", e); - throw e; - } - } - } catch (IOException e) { - handler_.handleConnectionLost(); - } - } - } - - private final InputStream in_; - private final OutputStream out_; - private final IncomingHandler handler_; - private final IncomingThread thread_ = new IncomingThread(); - - public IOIOProtocol(InputStream in, OutputStream out, - IncomingHandler handler) { - in_ = in; - out_ = out; - handler_ = handler; - thread_.start(); - } -} +/* + * Copyright 2011 Ytai Ben-Tsvi. All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARSHAN POURSOHI OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied. + */ +package ioio.lib.impl; + +import ioio.lib.api.DigitalInput; +import ioio.lib.api.DigitalOutput; +import ioio.lib.api.SpiMaster; +import ioio.lib.api.TwiMaster.Rate; +import ioio.lib.api.Uart; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import android.util.Log; + +class IOIOProtocol { + static final int HARD_RESET = 0x00; + static final int ESTABLISH_CONNECTION = 0x00; + static final int SOFT_RESET = 0x01; + static final int CHECK_INTERFACE = 0x02; + static final int CHECK_INTERFACE_RESPONSE = 0x02; + static final int SET_PIN_DIGITAL_OUT = 0x03; + static final int SET_DIGITAL_OUT_LEVEL = 0x04; + static final int REPORT_DIGITAL_IN_STATUS = 0x04; + static final int SET_PIN_DIGITAL_IN = 0x05; + static final int REPORT_PERIODIC_DIGITAL_IN_STATUS = 0x05; + static final int SET_CHANGE_NOTIFY = 0x06; + static final int REGISTER_PERIODIC_DIGITAL_SAMPLING = 0x07; + static final int SET_PIN_PWM = 0x08; + static final int SET_PWM_DUTY_CYCLE = 0x09; + static final int SET_PWM_PERIOD = 0x0A; + static final int SET_PIN_ANALOG_IN = 0x0B; + static final int REPORT_ANALOG_IN_STATUS = 0x0B; + static final int SET_ANALOG_IN_SAMPLING = 0x0C; + static final int REPORT_ANALOG_IN_FORMAT = 0x0C; + static final int UART_CONFIG = 0x0D; + static final int UART_STATUS = 0x0D; + static final int UART_DATA = 0x0E; + static final int SET_PIN_UART = 0x0F; + static final int UART_REPORT_TX_STATUS = 0x0F; + static final int SPI_CONFIGURE_MASTER = 0x10; + static final int SPI_STATUS = 0x10; + static final int SPI_MASTER_REQUEST = 0x11; + static final int SPI_DATA = 0x11; + static final int SET_PIN_SPI = 0x12; + static final int SPI_REPORT_TX_STATUS = 0x12; + static final int I2C_CONFIGURE_MASTER = 0x13; + static final int I2C_STATUS = 0x13; + static final int I2C_WRITE_READ = 0x14; + static final int I2C_RESULT = 0x14; + static final int I2C_REPORT_TX_STATUS = 0x15; + static final int ICSP_SIX = 0x16; + static final int ICSP_REPORT_RX_STATUS = 0x16; + static final int ICSP_REGOUT = 0x17; + static final int ICSP_RESULT = 0x17; + static final int ICSP_PROG_ENTER = 0x18; + static final int ICSP_PROG_EXIT = 0x19; + static final int ICSP_CONFIG = 0x1A; + static final int INCAP_CONFIGURE = 0x1B; + static final int INCAP_STATUS = 0x1B; + static final int SET_PIN_INCAP = 0x1C; + static final int INCAP_REPORT = 0x1C; + static final int SOFT_CLOSE = 0x1D; + + static final int[] SCALE_DIV = new int[] { + 0x1F, // 31.25 + 0x1E, // 35.714 + 0x1D, // 41.667 + 0x1C, // 50 + 0x1B, // 62.5 + 0x1A, // 83.333 + 0x17, // 125 + 0x16, // 142.857 + 0x15, // 166.667 + 0x14, // 200 + 0x13, // 250 + 0x12, // 333.333 + 0x0F, // 500 + 0x0E, // 571.429 + 0x0D, // 666.667 + 0x0C, // 800 + 0x0B, // 1000 + 0x0A, // 1333.333 + 0x07, // 2000 + 0x06, // 2285.714 + 0x05, // 2666.667 + 0x04, // 3200 + 0x03, // 4000 + 0x02, // 5333.333 + 0x01 // 8000 + }; + + private static final String TAG = "IOIOProtocol"; + + enum PwmScale { + SCALE_1X(1, 0), SCALE_8X(8, 3), SCALE_64X(64, 2), SCALE_256X(256, 1); + + public final int scale; + private final int encoding; + + PwmScale(int scale, int encoding) { + this.scale = scale; + this.encoding = encoding; + } + } + + private byte[] outbuf_ = new byte[256]; + private int pos_ = 0; + private int batchCounter_ = 0; + + private void writeByte(int b) throws IOException { + assert (b >= 0 && b < 256); + if (pos_ == outbuf_.length) { + // buffer is full + flush(); + } + //Log.v(TAG, "sending: 0x" + Integer.toHexString(b)); + outbuf_[pos_++] = (byte) b; + } + + public synchronized void beginBatch() { + ++batchCounter_; + } + + public synchronized void endBatch() throws IOException { + if (--batchCounter_ == 0) { + flush(); + } + } + + private void flush() throws IOException { + try { + out_.write(outbuf_, 0, pos_); + } finally { + pos_ = 0; + } + } + + private void writeTwoBytes(int i) throws IOException { + writeByte(i & 0xFF); + writeByte(i >> 8); + } + + private void writeThreeBytes(int i) throws IOException { + writeByte(i & 0xFF); + writeByte((i >> 8) & 0xFF); + writeByte((i >> 16) & 0xFF); + } + + synchronized public void hardReset() throws IOException { + beginBatch(); + writeByte(HARD_RESET); + writeByte('I'); + writeByte('O'); + writeByte('I'); + writeByte('O'); + endBatch(); + } + + synchronized public void softReset() throws IOException { + beginBatch(); + writeByte(SOFT_RESET); + endBatch(); + } + + synchronized public void softClose() throws IOException { + beginBatch(); + writeByte(SOFT_CLOSE); + endBatch(); + } + + synchronized public void checkInterface(byte[] interfaceId) + throws IOException { + if (interfaceId.length != 8) { + throw new IllegalArgumentException( + "interface ID must be exactly 8 bytes long"); + } + beginBatch(); + writeByte(CHECK_INTERFACE); + for (int i = 0; i < 8; ++i) { + writeByte(interfaceId[i]); + } + endBatch(); + } + + synchronized public void setDigitalOutLevel(int pin, boolean level) + throws IOException { + beginBatch(); + writeByte(SET_DIGITAL_OUT_LEVEL); + writeByte(pin << 2 | (level ? 1 : 0)); + endBatch(); + } + + synchronized public void setPinPwm(int pin, int pwmNum, boolean enable) + throws IOException { + beginBatch(); + writeByte(SET_PIN_PWM); + writeByte(pin & 0x3F); + writeByte((enable ? 0x80 : 0x00) | (pwmNum & 0x0F)); + endBatch(); + } + + synchronized public void setPwmDutyCycle(int pwmNum, int dutyCycle, + int fraction) throws IOException { + beginBatch(); + writeByte(SET_PWM_DUTY_CYCLE); + writeByte(pwmNum << 2 | fraction); + writeTwoBytes(dutyCycle); + endBatch(); + } + + synchronized public void setPwmPeriod(int pwmNum, int period, PwmScale scale) + throws IOException { + beginBatch(); + writeByte(SET_PWM_PERIOD); + writeByte(((scale.encoding & 0x02) << 6) | (pwmNum << 1) + | (scale.encoding & 0x01)); + writeTwoBytes(period); + endBatch(); + } + + synchronized public void setPinIncap(int pin, int incapNum, boolean enable) + throws IOException { + beginBatch(); + writeByte(SET_PIN_INCAP); + writeByte(pin); + writeByte(incapNum | (enable ? 0x80 : 0x00)); + endBatch(); + } + + synchronized public void incapClose(int incapNum, boolean double_prec) + throws IOException { + beginBatch(); + writeByte(INCAP_CONFIGURE); + writeByte(incapNum); + writeByte(double_prec ? 0x80 : 0x00); + endBatch(); + } + + synchronized public void incapConfigure(int incapNum, boolean double_prec, + int mode, int clock) throws IOException { + beginBatch(); + writeByte(INCAP_CONFIGURE); + writeByte(incapNum); + writeByte((double_prec ? 0x80 : 0x00) | (mode << 3) | clock); + endBatch(); + } + + synchronized public void i2cWriteRead(int i2cNum, boolean tenBitAddr, + int address, int writeSize, int readSize, byte[] writeData) + throws IOException { + beginBatch(); + writeByte(I2C_WRITE_READ); + writeByte(((address >> 8) << 6) | (tenBitAddr ? 0x20 : 0x00) | i2cNum); + writeByte(address & 0xFF); + writeByte(writeSize); + writeByte(readSize); + for (int i = 0; i < writeSize; ++i) { + writeByte(((int) writeData[i]) & 0xFF); + } + endBatch(); + } + + synchronized public void setPinDigitalOut(int pin, boolean value, + DigitalOutput.Spec.Mode mode) throws IOException { + beginBatch(); + writeByte(SET_PIN_DIGITAL_OUT); + writeByte((pin << 2) + | (mode == DigitalOutput.Spec.Mode.OPEN_DRAIN ? 0x01 : 0x00) + | (value ? 0x02 : 0x00)); + endBatch(); + } + + synchronized public void setPinDigitalIn(int pin, + DigitalInput.Spec.Mode mode) throws IOException { + int pull = 0; + if (mode == DigitalInput.Spec.Mode.PULL_UP) { + pull = 1; + } else if (mode == DigitalInput.Spec.Mode.PULL_DOWN) { + pull = 2; + } + beginBatch(); + writeByte(SET_PIN_DIGITAL_IN); + writeByte((pin << 2) | pull); + endBatch(); + } + + synchronized public void setChangeNotify(int pin, boolean changeNotify) + throws IOException { + beginBatch(); + writeByte(SET_CHANGE_NOTIFY); + writeByte((pin << 2) | (changeNotify ? 0x01 : 0x00)); + endBatch(); + } + + synchronized public void registerPeriodicDigitalSampling(int pin, + int freqScale) throws IOException { + // TODO: implement + } + + synchronized public void setPinAnalogIn(int pin) throws IOException { + beginBatch(); + writeByte(SET_PIN_ANALOG_IN); + writeByte(pin); + endBatch(); + } + + synchronized public void setAnalogInSampling(int pin, boolean enable) + throws IOException { + beginBatch(); + writeByte(SET_ANALOG_IN_SAMPLING); + writeByte((enable ? 0x80 : 0x00) | (pin & 0x3F)); + endBatch(); + } + + synchronized public void uartData(int uartNum, int numBytes, byte data[]) + throws IOException { + if (numBytes > 64) { + throw new IllegalArgumentException( + "A maximum of 64 bytes can be sent in one uartData message. Got: " + + numBytes); + } + beginBatch(); + writeByte(UART_DATA); + writeByte((numBytes - 1) | uartNum << 6); + for (int i = 0; i < numBytes; ++i) { + writeByte(((int) data[i]) & 0xFF); + } + endBatch(); + } + + synchronized public void uartConfigure(int uartNum, int rate, + boolean speed4x, Uart.StopBits stopbits, Uart.Parity parity) + throws IOException { + int parbits = parity == Uart.Parity.EVEN ? 1 + : (parity == Uart.Parity.ODD ? 2 : 0); + beginBatch(); + writeByte(UART_CONFIG); + writeByte((uartNum << 6) | (speed4x ? 0x08 : 0x00) + | (stopbits == Uart.StopBits.TWO ? 0x04 : 0x00) | parbits); + writeTwoBytes(rate); + endBatch(); + } + + synchronized public void uartClose(int uartNum) throws IOException { + beginBatch(); + writeByte(UART_CONFIG); + writeByte(uartNum << 6); + writeTwoBytes(0); + endBatch(); + } + + synchronized public void setPinUart(int pin, int uartNum, boolean tx, + boolean enable) throws IOException { + beginBatch(); + writeByte(SET_PIN_UART); + writeByte(pin); + writeByte((enable ? 0x80 : 0x00) | (tx ? 0x40 : 0x00) | uartNum); + endBatch(); + } + + synchronized public void spiConfigureMaster(int spiNum, + SpiMaster.Config config) throws IOException { + beginBatch(); + writeByte(SPI_CONFIGURE_MASTER); + writeByte((spiNum << 5) | SCALE_DIV[config.rate.ordinal()]); + writeByte((config.sampleOnTrailing ? 0x00 : 0x02) + | (config.invertClk ? 0x01 : 0x00)); + endBatch(); + } + + synchronized public void spiClose(int spiNum) throws IOException { + beginBatch(); + writeByte(SPI_CONFIGURE_MASTER); + writeByte(spiNum << 5); + writeByte(0x00); + endBatch(); + } + + synchronized public void setPinSpi(int pin, int mode, boolean enable, + int spiNum) throws IOException { + beginBatch(); + writeByte(SET_PIN_SPI); + writeByte(pin); + writeByte((1 << 4) | (mode << 2) | spiNum); + endBatch(); + } + + synchronized public void spiMasterRequest(int spiNum, int ssPin, + byte data[], int dataBytes, int totalBytes, int responseBytes) + throws IOException { + final boolean dataNeqTotal = (dataBytes != totalBytes); + final boolean resNeqTotal = (responseBytes != totalBytes); + beginBatch(); + writeByte(SPI_MASTER_REQUEST); + writeByte((spiNum << 6) | ssPin); + writeByte((dataNeqTotal ? 0x80 : 0x00) | (resNeqTotal ? 0x40 : 0x00) + | totalBytes - 1); + if (dataNeqTotal) { + writeByte(dataBytes); + } + if (resNeqTotal) { + writeByte(responseBytes); + } + for (int i = 0; i < dataBytes; ++i) { + writeByte(((int) data[i]) & 0xFF); + } + endBatch(); + } + + synchronized public void i2cConfigureMaster(int i2cNum, Rate rate, + boolean smbusLevels) throws IOException { + int rateBits = (rate == Rate.RATE_1MHz ? 3 + : (rate == Rate.RATE_400KHz ? 2 : 1)); + beginBatch(); + writeByte(I2C_CONFIGURE_MASTER); + writeByte((smbusLevels ? 0x80 : 0) | (rateBits << 5) | i2cNum); + endBatch(); + } + + synchronized public void i2cClose(int i2cNum) throws IOException { + beginBatch(); + writeByte(I2C_CONFIGURE_MASTER); + writeByte(i2cNum); + endBatch(); + } + + synchronized public void icspOpen() throws IOException { + beginBatch(); + writeByte(ICSP_CONFIG); + writeByte(0x01); + endBatch(); + } + + synchronized public void icspClose() throws IOException { + beginBatch(); + writeByte(ICSP_CONFIG); + writeByte(0x00); + endBatch(); + } + + synchronized public void icspEnter() throws IOException { + beginBatch(); + writeByte(ICSP_PROG_ENTER); + endBatch(); + } + + synchronized public void icspExit() throws IOException { + beginBatch(); + writeByte(ICSP_PROG_EXIT); + endBatch(); + } + + synchronized public void icspSix(int instruction) throws IOException { + beginBatch(); + writeByte(ICSP_SIX); + writeThreeBytes(instruction); + endBatch(); + } + + synchronized public void icspRegout() throws IOException { + beginBatch(); + writeByte(ICSP_REGOUT); + endBatch(); + } + + public interface IncomingHandler { + public void handleEstablishConnection(byte[] hardwareId, + byte[] bootloaderId, byte[] firmwareId); + + public void handleConnectionLost(); + + public void handleSoftReset(); + + public void handleCheckInterfaceResponse(boolean supported); + + public void handleSetChangeNotify(int pin, boolean changeNotify); + + public void handleReportDigitalInStatus(int pin, boolean level); + + public void handleRegisterPeriodicDigitalSampling(int pin, int freqScale); + + public void handleReportPeriodicDigitalInStatus(int frameNum, + boolean values[]); + + public void handleAnalogPinStatus(int pin, boolean open); + + public void handleReportAnalogInStatus(List pins, + List values); + + public void handleUartOpen(int uartNum); + + public void handleUartClose(int uartNum); + + public void handleUartData(int uartNum, int numBytes, byte data[]); + + public void handleUartReportTxStatus(int uartNum, int bytesRemaining); + + public void handleSpiOpen(int spiNum); + + public void handleSpiClose(int spiNum); + + public void handleSpiData(int spiNum, int ssPin, byte data[], + int dataBytes); + + public void handleSpiReportTxStatus(int spiNum, int bytesRemaining); + + public void handleI2cOpen(int i2cNum); + + public void handleI2cClose(int i2cNum); + + public void handleI2cResult(int i2cNum, int size, byte[] data); + + public void handleI2cReportTxStatus(int spiNum, int bytesRemaining); + + void handleIcspOpen(); + + void handleIcspClose(); + + void handleIcspReportRxStatus(int bytesRemaining); + + void handleIcspResult(int size, byte[] data); + + public void handleIncapReport(int incapNum, int size, byte[] data); + + public void handleIncapClose(int incapNum); + + public void handleIncapOpen(int incapNum); + } + + class IncomingThread extends Thread { + private int readOffset_ = 0; + private int validBytes_ = 0; + private byte[] inbuf_ = new byte[64]; + + private List analogPinValues_ = new ArrayList(); + private List analogFramePins_ = new ArrayList(); + private List newFramePins_ = new ArrayList(); + private Set removedPins_ = new HashSet(); + private Set addedPins_ = new HashSet(); + + private void calculateAnalogFrameDelta() { + removedPins_.clear(); + removedPins_.addAll(analogFramePins_); + addedPins_.clear(); + addedPins_.addAll(newFramePins_); + // Remove the intersection from both. + for (Iterator it = removedPins_.iterator(); it.hasNext();) { + Integer current = it.next(); + if (addedPins_.contains(current)) { + it.remove(); + addedPins_.remove(current); + } + } + // swap + List temp = analogFramePins_; + analogFramePins_ = newFramePins_; + newFramePins_ = temp; + } + + private void fillBuf() throws IOException { + try { + validBytes_ = in_.read(inbuf_, 0, inbuf_.length); + if (validBytes_ <= 0) { + throw new IOException("Unexpected stream closure"); + } + //Log.v(TAG, "received " + validBytes_ + " bytes"); + readOffset_ = 0; + } catch (IOException e) { + Log.i(TAG, "IOIO disconnected"); + throw e; + } + } + + private int readByte() throws IOException { + if (readOffset_ == validBytes_) { + fillBuf(); + } + int b = inbuf_[readOffset_++]; + b &= 0xFF; // make unsigned + //Log.v(TAG, "received: 0x" + Integer.toHexString(b)); + return b; + } + + private void readBytes(int size, byte[] buffer) throws IOException { + for (int i = 0; i < size; ++i) { + buffer[i] = (byte) readByte(); + } + } + + @Override + public void run() { + super.run(); + setPriority(MAX_PRIORITY); + int arg1; + int arg2; + int numPins; + int size; + byte[] data = new byte[256]; + try { + while (true) { + switch (arg1 = readByte()) { + case ESTABLISH_CONNECTION: + if (readByte() != 'I' || readByte() != 'O' + || readByte() != 'I' || readByte() != 'O') { + throw new IOException( + "Bad establish connection magic"); + } + byte[] hardwareId = new byte[8]; + byte[] bootloaderId = new byte[8]; + byte[] firmwareId = new byte[8]; + readBytes(8, hardwareId); + readBytes(8, bootloaderId); + readBytes(8, firmwareId); + + handler_.handleEstablishConnection(hardwareId, + bootloaderId, firmwareId); + break; + + case SOFT_RESET: + analogFramePins_.clear(); + handler_.handleSoftReset(); + break; + + case REPORT_DIGITAL_IN_STATUS: + arg1 = readByte(); + handler_.handleReportDigitalInStatus(arg1 >> 2, + (arg1 & 0x01) == 1); + break; + + case SET_CHANGE_NOTIFY: + arg1 = readByte(); + handler_.handleSetChangeNotify(arg1 >> 2, + (arg1 & 0x01) == 1); + break; + + case REGISTER_PERIODIC_DIGITAL_SAMPLING: + // TODO: implement + break; + + case REPORT_PERIODIC_DIGITAL_IN_STATUS: + // TODO: implement + break; + + case REPORT_ANALOG_IN_FORMAT: + numPins = readByte(); + newFramePins_.clear(); + for (int i = 0; i < numPins; ++i) { + newFramePins_.add(readByte()); + } + calculateAnalogFrameDelta(); + for (Integer i : removedPins_) { + handler_.handleAnalogPinStatus(i, false); + } + for (Integer i : addedPins_) { + handler_.handleAnalogPinStatus(i, true); + } + break; + + case REPORT_ANALOG_IN_STATUS: + numPins = analogFramePins_.size(); + int header = 0; + analogPinValues_.clear(); + for (int i = 0; i < numPins; ++i) { + if (i % 4 == 0) { + header = readByte(); + } + analogPinValues_.add((readByte() << 2) | (header & 0x03)); + header >>= 2; + } + handler_.handleReportAnalogInStatus(analogFramePins_, + analogPinValues_); + break; + + case UART_REPORT_TX_STATUS: + arg1 = readByte(); + arg2 = readByte(); + handler_.handleUartReportTxStatus(arg1 & 0x03, + (arg1 >> 2) | (arg2 << 6)); + break; + + case UART_DATA: + arg1 = readByte(); + for (int i = 0; i < (arg1 & 0x3F) + 1; ++i) { + data[i] = (byte) readByte(); + } + handler_.handleUartData(arg1 >> 6, (arg1 & 0x3F) + 1, + data); + break; + + case UART_STATUS: + arg1 = readByte(); + if ((arg1 & 0x80) != 0) { + handler_.handleUartOpen(arg1 & 0x03); + } else { + handler_.handleUartClose(arg1 & 0x03); + } + break; + + case SPI_DATA: + arg1 = readByte(); + arg2 = readByte(); + for (int i = 0; i < (arg1 & 0x3F) + 1; ++i) { + data[i] = (byte) readByte(); + } + handler_.handleSpiData(arg1 >> 6, arg2 & 0x3F, data, + (arg1 & 0x3F) + 1); + break; + + case SPI_REPORT_TX_STATUS: + arg1 = readByte(); + arg2 = readByte(); + handler_.handleSpiReportTxStatus(arg1 & 0x03, + (arg1 >> 2) | (arg2 << 6)); + break; + + case SPI_STATUS: + arg1 = readByte(); + if ((arg1 & 0x80) != 0) { + handler_.handleSpiOpen(arg1 & 0x03); + } else { + handler_.handleSpiClose(arg1 & 0x03); + } + break; + + case I2C_STATUS: + arg1 = readByte(); + if ((arg1 & 0x80) != 0) { + handler_.handleI2cOpen(arg1 & 0x03); + } else { + handler_.handleI2cClose(arg1 & 0x03); + } + break; + + case I2C_RESULT: + arg1 = readByte(); + arg2 = readByte(); + if (arg2 != 0xFF) { + for (int i = 0; i < arg2; ++i) { + data[i] = (byte) readByte(); + } + } + handler_.handleI2cResult(arg1 & 0x03, arg2, data); + break; + + case I2C_REPORT_TX_STATUS: + arg1 = readByte(); + arg2 = readByte(); + handler_.handleI2cReportTxStatus(arg1 & 0x03, + (arg1 >> 2) | (arg2 << 6)); + break; + + case CHECK_INTERFACE_RESPONSE: + arg1 = readByte(); + handler_.handleCheckInterfaceResponse((arg1 & 0x01) == 1); + break; + + case ICSP_REPORT_RX_STATUS: + arg1 = readByte(); + arg2 = readByte(); + handler_.handleIcspReportRxStatus(arg1 | (arg2 << 8)); + break; + + case ICSP_RESULT: + data[0] = (byte) readByte(); + data[1] = (byte) readByte(); + handler_.handleIcspResult(2, data); + break; + + case ICSP_CONFIG: + arg1 = readByte(); + if ((arg1 & 0x01) == 1) { + handler_.handleIcspOpen(); + } else { + handler_.handleIcspClose(); + } + break; + + case INCAP_STATUS: + arg1 = readByte(); + if ((arg1 & 0x80) != 0) { + handler_.handleIncapOpen(arg1 & 0x0F); + } else { + handler_.handleIncapClose(arg1 & 0x0F); + } + break; + + case INCAP_REPORT: + arg1 = readByte(); + size = arg1 >> 6; + if (size == 0) { + size = 4; + } + readBytes(size, data); + handler_.handleIncapReport(arg1 & 0x0F, size, data); + break; + + case SOFT_CLOSE: + Log.d(TAG, "Received soft close."); + throw new IOException("Soft close"); + + + default: + in_.close(); + IOException e = new IOException( + "Received unexpected command: 0x" + + Integer.toHexString(arg1)); + Log.e("IOIOProtocol", "Protocol error", e); + throw e; + } + } + } catch (IOException e) { + handler_.handleConnectionLost(); + } + } + } + + private final InputStream in_; + private final OutputStream out_; + private final IncomingHandler handler_; + private final IncomingThread thread_ = new IncomingThread(); + + public IOIOProtocol(InputStream in, OutputStream out, + IncomingHandler handler) { + in_ = in; + out_ = out; + handler_ = handler; + thread_.start(); + } +} diff --git a/IOIOLib/src/ioio/lib/impl/IncomingState.java b/IOIOLib/src/ioio/lib/impl/IncomingState.java index 05cbccc..a9a34d4 100644 --- a/IOIOLib/src/ioio/lib/impl/IncomingState.java +++ b/IOIOLib/src/ioio/lib/impl/IncomingState.java @@ -32,6 +32,7 @@ import ioio.lib.api.exception.ConnectionLostException; import ioio.lib.impl.IOIOProtocol.IncomingHandler; import java.util.HashSet; +import java.util.List; import java.util.Queue; import java.util.Set; import java.util.concurrent.ConcurrentLinkedQueue; @@ -395,10 +396,11 @@ class IncomingState implements IncomingHandler { } @Override - public void handleReportAnalogInStatus(int pins[], int values[]) { + public void handleReportAnalogInStatus(List pins, + List values) { // logMethod("handleReportAnalogInStatus", pins, values); - for (int i = 0; i < pins.length; ++i) { - intputPinStates_[pins[i]].setValue(values[i]); + for (int i = 0; i < pins.size(); ++i) { + intputPinStates_[pins.get(i)].setValue(values.get(i)); } } diff --git a/IOIOLib/src/ioio/lib/impl/TwiMasterImpl.java b/IOIOLib/src/ioio/lib/impl/TwiMasterImpl.java index 638a5fc..8f7f86b 100644 --- a/IOIOLib/src/ioio/lib/impl/TwiMasterImpl.java +++ b/IOIOLib/src/ioio/lib/impl/TwiMasterImpl.java @@ -137,7 +137,7 @@ class TwiMasterImpl extends AbstractResource implements TwiMaster, synchronized (result) { result.ready_ = true; result.success_ = (size != 0xFF); - if (result.success_) { + if (result.success_ && size > 0) { System.arraycopy(data, 0, result.data_, 0, size); } result.notify(); diff --git a/IOIOLib/src/ioio/lib/spi/NoRuntimeSupportException.java b/IOIOLib/src/ioio/lib/spi/NoRuntimeSupportException.java index 1b6e901..7ad92a5 100644 --- a/IOIOLib/src/ioio/lib/spi/NoRuntimeSupportException.java +++ b/IOIOLib/src/ioio/lib/spi/NoRuntimeSupportException.java @@ -1,6 +1,6 @@ package ioio.lib.spi; -public class NoRuntimeSupportException extends Exception { +public class NoRuntimeSupportException extends RuntimeException { private static final long serialVersionUID = -6559208663699429514L; public NoRuntimeSupportException(String desc) { diff --git a/IOIOLib/src/ioio/lib/util/AbstractIOIOActivity.java b/IOIOLib/src/ioio/lib/util/AbstractIOIOActivity.java index 8408048..0ba3bf3 100644 --- a/IOIOLib/src/ioio/lib/util/AbstractIOIOActivity.java +++ b/IOIOLib/src/ioio/lib/util/AbstractIOIOActivity.java @@ -1,369 +1,369 @@ -/* - * Copyright 2011 Ytai Ben-Tsvi. All rights reserved. - * - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARSHAN POURSOHI OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied. - */ - -package ioio.lib.util; - -import ioio.lib.api.IOIO; -import ioio.lib.api.IOIOFactory; -import ioio.lib.api.exception.ConnectionLostException; -import ioio.lib.api.exception.IncompatibilityException; -import ioio.lib.spi.IOIOConnectionBootstrap; -import ioio.lib.spi.IOIOConnectionFactory; -import ioio.lib.util.android.ContextWrapperDependent; - -import java.util.Collection; -import java.util.LinkedList; - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.util.Log; - -/** - * A convenience class for easy creation of IOIO-based applications. - * - * It is used by creating a concrete Activity in your application, which extends - * this class. This class then takes care of proper creation and abortion of the - * IOIO connection and of a dedicated thread for IOIO communication. - * - * In the basic usage the client should extend this class and implement - * {@link #createIOIOThread()}, which should return an implementation of the - * {@link AbstractIOIOActivity.IOIOThread} abstract class. In this - * implementation, the client implements the - * {@link AbstractIOIOActivity.IOIOThread#setup()} method, which gets called as - * soon as communication with the IOIO is established, and the - * {@link AbstractIOIOActivity.IOIOThread#loop()} method, which gets called - * repetitively as long as the IOIO is connected. Both methods should access the - * {@link AbstractIOIOActivity.IOIOThread#ioio_} field for controlling the IOIO. - * - * In addition, the {@link AbstractIOIOActivity.IOIOThread#disconnected()} - * method may be overridden in order to execute logic as soon as a disconnection - * occurs for whichever reason. The - * {@link AbstractIOIOActivity.IOIOThread#incompatible()} method may be - * overridden in order to take action in case where a IOIO whose firmware is - * incompatible with the IOIOLib version that application is built with. - * - * In a more advanced use case, more than one IOIO is available. In this case, a - * thread will be created for each IOIO, whose semantics are as defined above. - * If the client needs to be able to distinguish between them, it is possible to - * override {@link #createIOIOThread(String, Object)} instead of - * {@link #createIOIOThread()}. The first argument provided will contain the - * connection class name, such as ioio.lib.impl.SocketIOIOConnection for a - * connection established over a TCP socket (which is used over ADB). The second - * argument will contain information specific to the connection type. For - * example, in the case of SocketIOIOConnection, the second argument will - * contain an {@link Integer} representing the local port number. - * - * @deprecated Please use {@link ioio.lib.util.android.IOIOActivity} instead. - */ -public abstract class AbstractIOIOActivity extends Activity { - private static final String TAG = "AbstractIOIOActivity"; - - static { - IOIOConnectionRegistry - .addBootstraps(new String[] { - "ioio.lib.android.accessory.AccessoryConnectionBootstrap", - "ioio.lib.android.bluetooth.BluetoothIOIOConnectionBootstrap" }); - } - - private Collection threads_ = new LinkedList(); - private Collection bootstraps_ = IOIOConnectionRegistry - .getBootstraps(); - private IOIOConnectionFactory currentConnectionFactory_; - - /** - * Subclasses should call this method from their own onCreate() if - * overloaded. It takes care of connecting with the IOIO. - */ - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - for (IOIOConnectionBootstrap bootstrap : bootstraps_) { - if (bootstrap instanceof ContextWrapperDependent) { - ((ContextWrapperDependent) bootstrap).onCreate(this); - } - } - } - - /** - * Subclasses should call this method from their own onDestroy() if - * overloaded. It takes care of connecting with the IOIO. - */ - @Override - protected void onDestroy() { - for (IOIOConnectionBootstrap bootstrap : bootstraps_) { - if (bootstrap instanceof ContextWrapperDependent) { - ((ContextWrapperDependent) bootstrap).onDestroy(); - } - } - super.onDestroy(); - } - - /** - * Subclasses should call this method from their own onStart() if - * overloaded. It takes care of connecting with the IOIO. - */ - @Override - protected void onStart() { - super.onStart(); - for (IOIOConnectionBootstrap bootstrap : bootstraps_) { - if (bootstrap instanceof ContextWrapperDependent) { - ((ContextWrapperDependent) bootstrap).open(); - } - } - createAllThreads(); - startAllThreads(); - } - - /** - * Subclasses should call this method from their own onStop() if overloaded. - * It takes care of disconnecting from the IOIO. - */ - @Override - protected void onStop() { - abortAllThreads(); - try { - joinAllThreads(); - } catch (InterruptedException e) { - } - for (IOIOConnectionBootstrap bootstrap : bootstraps_) { - if (bootstrap instanceof ContextWrapperDependent) { - ((ContextWrapperDependent) bootstrap).close(); - } - } - super.onStop(); - } - - @Override - protected void onNewIntent(Intent intent) { - super.onNewIntent(intent); - if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { - for (IOIOConnectionBootstrap bootstrap : bootstraps_) { - if (bootstrap instanceof ContextWrapperDependent) { - ((ContextWrapperDependent) bootstrap).open(); - } - } - } - } - - /** - * Subclasses must either implement this method or its other overload by - * returning a concrete subclass of {@link IOIOThread}. null - * may be returned if the client is not interested to create a thread for - * this IOIO. In multi-IOIO scenarios, where you want to identify which IOIO - * the thread is for, consider using {@link #createIOIOThread()} instead. - * - * @return An implementation of {@link IOIOThread}, or null to - * skip. - */ - protected IOIOThread createIOIOThread() { - throw new RuntimeException( - "Client must override on of the createIOIOThread overloads!"); - } - - /** - * Subclasses should implement this method by returning a concrete subclass - * of {@link IOIOThread}. This overload is useful in multi-IOIO scenarios, - * where you want to identify which IOIO the thread is for. The provided - * arguments should provide enough information to be unique per connection. - * null may be returned if the client is not interested to - * connect a thread for this IOIO. This can be used in order to filter out - * unwanted connections, for example if the application is only intended for - * wireless connection, any wired connection attempts may be rejected, thus - * saving resources used for listening for incoming wired connections. - * - * @param connectionType - * A unique name of the connection type. Typically, the - * fully-qualified name of the connection class used to connect - * to the IOIO. - * @param extra - * A connection-type-specific object with extra information on - * the specific connection. Should provide information that - * enables distinguishing between different IOIO instances using - * the same connection class. For example, a Bluetooth connection - * type, might have the remote IOIO's Bluetooth name as extra. - * - * @return An implementation of {@link IOIOThread}, or null to - * skip. - */ - protected IOIOThread createIOIOThread(String connectionType, Object extra) { - return createIOIOThread(); - } - - /** - * An abstract class, which facilitates a thread dedicated for communication - * with a single physical IOIO device. - */ - protected abstract class IOIOThread extends Thread { - /** Subclasses should use this field for controlling the IOIO. */ - protected IOIO ioio_; - private boolean abort_ = false; - private boolean connected_ = true; - private final IOIOConnectionFactory connectionFactory_ = currentConnectionFactory_; - - /** - * Subclasses should override this method for performing operations to - * be done once as soon as IOIO communication is established. Typically, - * this will include opening pins and modules using the openXXX() - * methods of the {@link #ioio_} field. - */ - protected void setup() throws ConnectionLostException, - InterruptedException { - } - - /** - * Subclasses should override this method for performing operations to - * be done repetitively as long as IOIO communication persists. - * Typically, this will be the main logic of the application, processing - * inputs and producing outputs. - */ - protected void loop() throws ConnectionLostException, - InterruptedException { - sleep(100000); - } - - /** - * Subclasses should override this method for performing operations to - * be done once as soon as IOIO communication is lost or closed. - * Typically, this will include GUI changes corresponding to the change. - * This method will only be called if setup() has been called. The - * {@link #ioio_} member must not be used from within this method. This - * method should not block for long, since it may cause an ANR. - */ - protected void disconnected() { - } - - /** - * Subclasses should override this method for performing operations to - * be done if an incompatible IOIO firmware is detected. The - * {@link #ioio_} member must not be used from within this method. This - * method will only be called once, until a compatible IOIO is connected - * (i.e. {@link #setup()} gets called). - */ - protected void incompatible() { - } - - /** Not relevant to subclasses. */ - @Override - public final void run() { - super.run(); - while (!abort_) { - try { - synchronized (this) { - if (abort_) { - break; - } - ioio_ = IOIOFactory.create(connectionFactory_ - .createConnection()); - } - } catch (Exception e) { - Log.e(TAG, "Failed to create IOIO, aborting IOIOThread!"); - return; - } - // if we got here, we have a ioio_! - try { - ioio_.waitForConnect(); - connected_ = true; - setup(); - while (!abort_) { - loop(); - } - } catch (ConnectionLostException e) { - } catch (InterruptedException e) { - ioio_.disconnect(); - } catch (IncompatibilityException e) { - Log.e(TAG, "Incompatible IOIO firmware", e); - incompatible(); - // nothing to do - just wait until physical disconnection - } catch (Exception e) { - Log.e(TAG, "Unexpected exception caught", e); - ioio_.disconnect(); - break; - } finally { - try { - ioio_.waitForDisconnect(); - } catch (InterruptedException e1) { - } - synchronized (this) { - ioio_ = null; - } - if (connected_) { - disconnected(); - connected_ = false; - } - } - } - Log.d(TAG, "IOIOThread is exiting"); - } - - /** Not relevant to subclasses. */ - public synchronized final void abort() { - abort_ = true; - if (ioio_ != null) { - ioio_.disconnect(); - } - if (connected_) { - interrupt(); - } - } - } - - private void abortAllThreads() { - for (IOIOThread thread : threads_) { - thread.abort(); - } - } - - private void joinAllThreads() throws InterruptedException { - for (IOIOThread thread : threads_) { - thread.join(); - } - } - - private void createAllThreads() { - threads_.clear(); - Collection factories = IOIOConnectionRegistry - .getConnectionFactories(); - for (IOIOConnectionFactory factory : factories) { - currentConnectionFactory_ = factory; - IOIOThread thread = createIOIOThread(factory.getType(), - factory.getExtra()); - if (thread != null) { - threads_.add(thread); - } - } - } - - private void startAllThreads() { - for (IOIOThread thread : threads_) { - thread.start(); - } - } - -} +/* + * Copyright 2011 Ytai Ben-Tsvi. All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARSHAN POURSOHI OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied. + */ + +package ioio.lib.util; + +import ioio.lib.api.IOIO; +import ioio.lib.api.IOIOFactory; +import ioio.lib.api.exception.ConnectionLostException; +import ioio.lib.api.exception.IncompatibilityException; +import ioio.lib.spi.IOIOConnectionBootstrap; +import ioio.lib.spi.IOIOConnectionFactory; +import ioio.lib.util.android.ContextWrapperDependent; + +import java.util.Collection; +import java.util.LinkedList; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; + +/** + * A convenience class for easy creation of IOIO-based applications. + * + * It is used by creating a concrete Activity in your application, which extends + * this class. This class then takes care of proper creation and abortion of the + * IOIO connection and of a dedicated thread for IOIO communication. + * + * In the basic usage the client should extend this class and implement + * {@link #createIOIOThread()}, which should return an implementation of the + * {@link AbstractIOIOActivity.IOIOThread} abstract class. In this + * implementation, the client implements the + * {@link AbstractIOIOActivity.IOIOThread#setup()} method, which gets called as + * soon as communication with the IOIO is established, and the + * {@link AbstractIOIOActivity.IOIOThread#loop()} method, which gets called + * repetitively as long as the IOIO is connected. Both methods should access the + * {@link AbstractIOIOActivity.IOIOThread#ioio_} field for controlling the IOIO. + * + * In addition, the {@link AbstractIOIOActivity.IOIOThread#disconnected()} + * method may be overridden in order to execute logic as soon as a disconnection + * occurs for whichever reason. The + * {@link AbstractIOIOActivity.IOIOThread#incompatible()} method may be + * overridden in order to take action in case where a IOIO whose firmware is + * incompatible with the IOIOLib version that application is built with. + * + * In a more advanced use case, more than one IOIO is available. In this case, a + * thread will be created for each IOIO, whose semantics are as defined above. + * If the client needs to be able to distinguish between them, it is possible to + * override {@link #createIOIOThread(String, Object)} instead of + * {@link #createIOIOThread()}. The first argument provided will contain the + * connection class name, such as ioio.lib.impl.SocketIOIOConnection for a + * connection established over a TCP socket (which is used over ADB). The second + * argument will contain information specific to the connection type. For + * example, in the case of SocketIOIOConnection, the second argument will + * contain an {@link Integer} representing the local port number. + * + * @deprecated Please use {@link ioio.lib.util.android.IOIOActivity} instead. + */ +public abstract class AbstractIOIOActivity extends Activity { + private static final String TAG = "AbstractIOIOActivity"; + + static { + IOIOConnectionRegistry + .addBootstraps(new String[] { + "ioio.lib.android.accessory.AccessoryConnectionBootstrap", + "ioio.lib.android.bluetooth.BluetoothIOIOConnectionBootstrap" }); + } + + private Collection threads_ = new LinkedList(); + private Collection bootstraps_ = IOIOConnectionRegistry + .getBootstraps(); + private IOIOConnectionFactory currentConnectionFactory_; + + /** + * Subclasses should call this method from their own onCreate() if + * overloaded. It takes care of connecting with the IOIO. + */ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + for (IOIOConnectionBootstrap bootstrap : bootstraps_) { + if (bootstrap instanceof ContextWrapperDependent) { + ((ContextWrapperDependent) bootstrap).onCreate(this); + } + } + } + + /** + * Subclasses should call this method from their own onDestroy() if + * overloaded. It takes care of connecting with the IOIO. + */ + @Override + protected void onDestroy() { + for (IOIOConnectionBootstrap bootstrap : bootstraps_) { + if (bootstrap instanceof ContextWrapperDependent) { + ((ContextWrapperDependent) bootstrap).onDestroy(); + } + } + super.onDestroy(); + } + + /** + * Subclasses should call this method from their own onStart() if + * overloaded. It takes care of connecting with the IOIO. + */ + @Override + protected void onStart() { + super.onStart(); + for (IOIOConnectionBootstrap bootstrap : bootstraps_) { + if (bootstrap instanceof ContextWrapperDependent) { + ((ContextWrapperDependent) bootstrap).open(); + } + } + createAllThreads(); + startAllThreads(); + } + + /** + * Subclasses should call this method from their own onStop() if overloaded. + * It takes care of disconnecting from the IOIO. + */ + @Override + protected void onStop() { + abortAllThreads(); + try { + joinAllThreads(); + } catch (InterruptedException e) { + } + for (IOIOConnectionBootstrap bootstrap : bootstraps_) { + if (bootstrap instanceof ContextWrapperDependent) { + ((ContextWrapperDependent) bootstrap).close(); + } + } + super.onStop(); + } + + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { + for (IOIOConnectionBootstrap bootstrap : bootstraps_) { + if (bootstrap instanceof ContextWrapperDependent) { + ((ContextWrapperDependent) bootstrap).open(); + } + } + } + } + + /** + * Subclasses must either implement this method or its other overload by + * returning a concrete subclass of {@link IOIOThread}. null + * may be returned if the client is not interested to create a thread for + * this IOIO. In multi-IOIO scenarios, where you want to identify which IOIO + * the thread is for, consider using {@link #createIOIOThread()} instead. + * + * @return An implementation of {@link IOIOThread}, or null to + * skip. + */ + protected IOIOThread createIOIOThread() { + throw new RuntimeException( + "Client must override on of the createIOIOThread overloads!"); + } + + /** + * Subclasses should implement this method by returning a concrete subclass + * of {@link IOIOThread}. This overload is useful in multi-IOIO scenarios, + * where you want to identify which IOIO the thread is for. The provided + * arguments should provide enough information to be unique per connection. + * null may be returned if the client is not interested to + * connect a thread for this IOIO. This can be used in order to filter out + * unwanted connections, for example if the application is only intended for + * wireless connection, any wired connection attempts may be rejected, thus + * saving resources used for listening for incoming wired connections. + * + * @param connectionType + * A unique name of the connection type. Typically, the + * fully-qualified name of the connection class used to connect + * to the IOIO. + * @param extra + * A connection-type-specific object with extra information on + * the specific connection. Should provide information that + * enables distinguishing between different IOIO instances using + * the same connection class. For example, a Bluetooth connection + * type, might have the remote IOIO's Bluetooth name as extra. + * + * @return An implementation of {@link IOIOThread}, or null to + * skip. + */ + protected IOIOThread createIOIOThread(String connectionType, Object extra) { + return createIOIOThread(); + } + + /** + * An abstract class, which facilitates a thread dedicated for communication + * with a single physical IOIO device. + */ + protected abstract class IOIOThread extends Thread { + /** Subclasses should use this field for controlling the IOIO. */ + protected IOIO ioio_; + private boolean abort_ = false; + private boolean connected_ = true; + private final IOIOConnectionFactory connectionFactory_ = currentConnectionFactory_; + + /** + * Subclasses should override this method for performing operations to + * be done once as soon as IOIO communication is established. Typically, + * this will include opening pins and modules using the openXXX() + * methods of the {@link #ioio_} field. + */ + protected void setup() throws ConnectionLostException, + InterruptedException { + } + + /** + * Subclasses should override this method for performing operations to + * be done repetitively as long as IOIO communication persists. + * Typically, this will be the main logic of the application, processing + * inputs and producing outputs. + */ + protected void loop() throws ConnectionLostException, + InterruptedException { + sleep(100000); + } + + /** + * Subclasses should override this method for performing operations to + * be done once as soon as IOIO communication is lost or closed. + * Typically, this will include GUI changes corresponding to the change. + * This method will only be called if setup() has been called. The + * {@link #ioio_} member must not be used from within this method. This + * method should not block for long, since it may cause an ANR. + */ + protected void disconnected() { + } + + /** + * Subclasses should override this method for performing operations to + * be done if an incompatible IOIO firmware is detected. The + * {@link #ioio_} member must not be used from within this method. This + * method will only be called once, until a compatible IOIO is connected + * (i.e. {@link #setup()} gets called). + */ + protected void incompatible() { + } + + /** Not relevant to subclasses. */ + @Override + public final void run() { + super.run(); + while (!abort_) { + try { + synchronized (this) { + if (abort_) { + break; + } + ioio_ = IOIOFactory.create(connectionFactory_ + .createConnection()); + } + } catch (Exception e) { + Log.e(TAG, "Failed to create IOIO, aborting IOIOThread!"); + return; + } + // if we got here, we have a ioio_! + try { + ioio_.waitForConnect(); + connected_ = true; + setup(); + while (!abort_) { + loop(); + } + } catch (ConnectionLostException e) { + } catch (InterruptedException e) { + ioio_.disconnect(); + } catch (IncompatibilityException e) { + Log.e(TAG, "Incompatible IOIO firmware", e); + incompatible(); + // nothing to do - just wait until physical disconnection + } catch (Exception e) { + Log.e(TAG, "Unexpected exception caught", e); + ioio_.disconnect(); + break; + } finally { + try { + ioio_.waitForDisconnect(); + } catch (InterruptedException e1) { + } + synchronized (this) { + ioio_ = null; + } + if (connected_) { + disconnected(); + connected_ = false; + } + } + } + Log.d(TAG, "IOIOThread is exiting"); + } + + /** Not relevant to subclasses. */ + public synchronized final void abort() { + abort_ = true; + if (ioio_ != null) { + ioio_.disconnect(); + } + if (connected_) { + interrupt(); + } + } + } + + private void abortAllThreads() { + for (IOIOThread thread : threads_) { + thread.abort(); + } + } + + private void joinAllThreads() throws InterruptedException { + for (IOIOThread thread : threads_) { + thread.join(); + } + } + + private void createAllThreads() { + threads_.clear(); + Collection factories = IOIOConnectionRegistry + .getConnectionFactories(); + for (IOIOConnectionFactory factory : factories) { + currentConnectionFactory_ = factory; + IOIOThread thread = createIOIOThread(factory.getType(), + factory.getExtra()); + if (thread != null) { + threads_.add(thread); + } + } + } + + private void startAllThreads() { + for (IOIOThread thread : threads_) { + thread.start(); + } + } + +} diff --git a/IOIOLib/src/ioio/lib/util/IOIOConnectionRegistry.java b/IOIOLib/src/ioio/lib/util/IOIOConnectionRegistry.java index 4168b51..acbfa71 100644 --- a/IOIOLib/src/ioio/lib/util/IOIOConnectionRegistry.java +++ b/IOIOLib/src/ioio/lib/util/IOIOConnectionRegistry.java @@ -1,133 +1,131 @@ -/* - * Copyright 2011 Ytai Ben-Tsvi. All rights reserved. - * - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARSHAN POURSOHI OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied. - */ -package ioio.lib.util; - -import ioio.lib.api.IOIOConnection; -import ioio.lib.api.IOIOFactory; -import ioio.lib.spi.IOIOConnectionBootstrap; -import ioio.lib.spi.IOIOConnectionFactory; - -import java.util.Collection; -import java.util.LinkedList; - -import android.util.Log; - -/** - * A utility class for managing available connection types to IOIO. - *

- * For advanced usage only! - *

- * This class facilitates dynamic linkage and instantiation of different IOIO - * connection types. {@link IOIOConnectionBootstrap} classes enable creation of - * {@link IOIOConnectionFactory} instances, from which concrete - * {@link IOIOConnection}s are created. The binding to - * {@link IOIOConnectionBootstrap} is dynamic, thus enabling linkage to succeed - * with or without those bootstraps. Likewise, during runtime, the absence of - * bootstraps is handled gracefully. - * - * A typical usage will call {@link #addBootstraps(String[])} with a list of - * class names to be sought from a static initializer block. It may then call - * {@link #getBootstraps()} to obtain any bootstrap classes that are available - * in runtime, in case the bootstrap classes themselves need some runtime - * handling. Last, the {@link #getConnectionFactories()} will return a - * collection of {@link IOIOConnectionFactory}, each representing one possible - * communication channel to a IOIO. - * - */ -public class IOIOConnectionRegistry { - /** - * Get all available connection specifications. This is a list of all - * currently available communication channels in which a IOIO may be - * available. The client typically passes elements of this collection to - * {@link IOIOFactory#create(IOIOConnection)}, possibly after filtering based on the - * specification's properties. - * - * @return A collection of specifications. - */ - public static Collection getConnectionFactories() { - Collection result = new LinkedList(); - for (IOIOConnectionBootstrap bootstrap : bootstraps_) { - bootstrap.getFactories(result); - } - return result; - } - - /** - * For advanced usage only! Used for special runtime handling of bootstrap - * classes. - * - * @return The bootstraps. - */ - public static Collection getBootstraps() { - return bootstraps_; - } - - /** - * For advanced usage only! Add platform-specific connection bootstrap - * classes. Call before calling {@link #getConnectionFactories()}. - */ - public static void addBootstraps(String[] classNames) { - for (String className : classNames) { - addBootstrap(className); - } - } - - private static final String TAG = "IOIOConnectionRegistry"; - - private static Collection bootstraps_; - - static { - bootstraps_ = new LinkedList(); - String[] classNames = new String[] { "ioio.lib.impl.SocketIOIOConnectionBootstrap" }; - addBootstraps(classNames); - } - - private static void addBootstrap(String className) { - try { - Class bootstrapClass = Class - .forName(className).asSubclass( - IOIOConnectionBootstrap.class); - bootstraps_.add(bootstrapClass.newInstance()); - Log.d(TAG, "Successfully added bootstrap class: " + className); - } catch (ClassNotFoundException e) { - Log.d(TAG, "Bootstrap class not found: " + className - + ". Not adding."); - } catch (RuntimeException e) { - Log.e(TAG, - "Runtime exception caught while attempting to initialize accessory connection factory", - e); - throw e; - } catch (Exception e) { - Log.w(TAG, - "Exception caught while attempting to initialize accessory connection factory", - e); - } - } - -} +/* + * Copyright 2011 Ytai Ben-Tsvi. All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARSHAN POURSOHI OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied. + */ +package ioio.lib.util; + +import ioio.lib.api.IOIOConnection; +import ioio.lib.api.IOIOFactory; +import ioio.lib.spi.IOIOConnectionBootstrap; +import ioio.lib.spi.IOIOConnectionFactory; +import ioio.lib.spi.NoRuntimeSupportException; + +import java.util.Collection; +import java.util.LinkedList; + +import android.util.Log; + +/** + * A utility class for managing available connection types to IOIO. + *

+ * For advanced usage only! + *

+ * This class facilitates dynamic linkage and instantiation of different IOIO + * connection types. {@link IOIOConnectionBootstrap} classes enable creation of + * {@link IOIOConnectionFactory} instances, from which concrete + * {@link IOIOConnection}s are created. The binding to + * {@link IOIOConnectionBootstrap} is dynamic, thus enabling linkage to succeed + * with or without those bootstraps. Likewise, during runtime, the absence of + * bootstraps is handled gracefully. + * + * A typical usage will call {@link #addBootstraps(String[])} with a list of + * class names to be sought from a static initializer block. It may then call + * {@link #getBootstraps()} to obtain any bootstrap classes that are available + * in runtime, in case the bootstrap classes themselves need some runtime + * handling. Last, the {@link #getConnectionFactories()} will return a + * collection of {@link IOIOConnectionFactory}, each representing one possible + * communication channel to a IOIO. + * + */ +public class IOIOConnectionRegistry { + /** + * Get all available connection specifications. This is a list of all + * currently available communication channels in which a IOIO may be + * available. The client typically passes elements of this collection to + * {@link IOIOFactory#create(IOIOConnection)}, possibly after filtering + * based on the specification's properties. + * + * @return A collection of specifications. + */ + public static Collection getConnectionFactories() { + Collection result = new LinkedList(); + for (IOIOConnectionBootstrap bootstrap : bootstraps_) { + bootstrap.getFactories(result); + } + return result; + } + + /** + * For advanced usage only! Used for special runtime handling of bootstrap + * classes. + * + * @return The bootstraps. + */ + public static Collection getBootstraps() { + return bootstraps_; + } + + /** + * For advanced usage only! Add platform-specific connection bootstrap + * classes. Call before calling {@link #getConnectionFactories()}. + */ + public static void addBootstraps(String[] classNames) { + for (String className : classNames) { + addBootstrap(className); + } + } + + private static final String TAG = "IOIOConnectionRegistry"; + + private static Collection bootstraps_; + + static { + bootstraps_ = new LinkedList(); + String[] classNames = new String[] { "ioio.lib.impl.SocketIOIOConnectionBootstrap" }; + addBootstraps(classNames); + } + + private static void addBootstrap(String className) { + try { + Class bootstrapClass = Class + .forName(className).asSubclass( + IOIOConnectionBootstrap.class); + bootstraps_.add(bootstrapClass.newInstance()); + Log.d(TAG, "Successfully added bootstrap class: " + className); + } catch (ClassNotFoundException e) { + Log.d(TAG, "Bootstrap class not found: " + className + + ". Not adding."); + } catch (NoRuntimeSupportException e) { + Log.d(TAG, "No runtime support for: " + className + ". Not adding."); + } catch (Throwable e) { + Log.e(TAG, + "Exception caught while attempting to initialize accessory connection factory", + e); + } + } + +} diff --git a/IOIOLib/src/ioio/lib/util/IOIOLooper.java b/IOIOLib/src/ioio/lib/util/IOIOLooper.java index aa843da..2fffe88 100644 --- a/IOIOLib/src/ioio/lib/util/IOIOLooper.java +++ b/IOIOLib/src/ioio/lib/util/IOIOLooper.java @@ -1,56 +1,56 @@ -package ioio.lib.util; - -import ioio.lib.api.IOIO; -import ioio.lib.api.exception.ConnectionLostException; - -/** - * A handler implementing interaction with a single IOIO over a single - * connection period. The interface utilizes a basic workflow for working with a - * IOIO instance: as soon as a connection is established, {@link #setup(IOIO)} - * will be called. Then, the {@link #loop()} method will be called repeatedly as - * long as the connection is alive. Last, the {@link #disconnected()} method - * will be called upon losing the connection (as result of physical - * disconnection, closing the application, etc). In case a IOIO with an - * incompatible firmware is encountered, {@link #incompatible()} will be called - * instead of {@link #setup(IOIO)}, and the IOIO instance is entirely useless, - * until eventually {@link #disconnected()} gets called. - * - */ -public interface IOIOLooper { - /** - * Subclasses should override this method for performing operations to be - * done once as soon as IOIO communication is established. - */ - public abstract void setup(IOIO ioio) throws ConnectionLostException, - InterruptedException; - - /** - * Subclasses should override this method for performing operations to be - * done repetitively as long as IOIO communication persists. Typically, this - * will be the main logic of the application, processing inputs and - * producing outputs. - */ - public abstract void loop() throws ConnectionLostException, - InterruptedException; - - /** - * Subclasses should override this method for performing operations to be - * done once as soon as IOIO communication is lost or closed. Typically, - * this will include GUI changes corresponding to the change. This method - * will only be called if setup() has been called. The ioio argument passed - * to {@link #setup(IOIO)} must not be used from within this method - it is - * invalid. This method should not block for long, since it may cause an - * ANR. - */ - public abstract void disconnected(); - - /** - * Subclasses should override this method for performing operations to be - * done if an incompatible IOIO firmware is detected. The ioio argument - * passed to {@link #setup(IOIO)} must not be used from within this method - - * it is invalid. This method will only be called once, until a compatible - * IOIO is connected (i.e. {@link #setup(IOIO)} gets called). - */ - public abstract void incompatible(); - +package ioio.lib.util; + +import ioio.lib.api.IOIO; +import ioio.lib.api.exception.ConnectionLostException; + +/** + * A handler implementing interaction with a single IOIO over a single + * connection period. The interface utilizes a basic workflow for working with a + * IOIO instance: as soon as a connection is established, {@link #setup(IOIO)} + * will be called. Then, the {@link #loop()} method will be called repeatedly as + * long as the connection is alive. Last, the {@link #disconnected()} method + * will be called upon losing the connection (as result of physical + * disconnection, closing the application, etc). In case a IOIO with an + * incompatible firmware is encountered, {@link #incompatible()} will be called + * instead of {@link #setup(IOIO)}, and the IOIO instance is entirely useless, + * until eventually {@link #disconnected()} gets called. + * + */ +public interface IOIOLooper { + /** + * Subclasses should override this method for performing operations to be + * done once as soon as IOIO communication is established. + */ + public abstract void setup(IOIO ioio) throws ConnectionLostException, + InterruptedException; + + /** + * Subclasses should override this method for performing operations to be + * done repetitively as long as IOIO communication persists. Typically, this + * will be the main logic of the application, processing inputs and + * producing outputs. + */ + public abstract void loop() throws ConnectionLostException, + InterruptedException; + + /** + * Subclasses should override this method for performing operations to be + * done once as soon as IOIO communication is lost or closed. Typically, + * this will include GUI changes corresponding to the change. This method + * will only be called if setup() has been called. The ioio argument passed + * to {@link #setup(IOIO)} must not be used from within this method - it is + * invalid. This method should not block for long, since it may cause an + * ANR. + */ + public abstract void disconnected(); + + /** + * Subclasses should override this method for performing operations to be + * done if an incompatible IOIO firmware is detected. The ioio argument + * passed to {@link #setup(IOIO)} must not be used from within this method - + * it is invalid. This method will only be called once, until a compatible + * IOIO is connected (i.e. {@link #setup(IOIO)} gets called). + */ + public abstract void incompatible(); + } \ No newline at end of file