From 14a7509d2fde9a083085bfde29ab86201725dd79 Mon Sep 17 00:00:00 2001 From: Jelmer Date: Sat, 21 Jan 2023 11:31:03 +0100 Subject: [PATCH] Improved power consumption --- ap_fw/main.c | 15 +++-- ap_fw/soc/zbs243/uart.c | 2 - tag_fw/fw154.bin | Bin 0 -> 32040 bytes tag_fw/fw29.bin | Bin 0 -> 31818 bytes tag_fw/fw42.bin | Bin 0 -> 31871 bytes tag_fw/syncedproto.c | 128 +++++++++++++++++++++++----------------- 6 files changed, 85 insertions(+), 60 deletions(-) create mode 100644 tag_fw/fw154.bin create mode 100644 tag_fw/fw29.bin create mode 100644 tag_fw/fw42.bin diff --git a/ap_fw/main.c b/ap_fw/main.c index 18762aa6..ee24df17 100644 --- a/ap_fw/main.c +++ b/ap_fw/main.c @@ -168,7 +168,7 @@ extern bool __idata serialBypassActive; // if the serial bypass is uint32_t __xdata nextBlockAttempt = 0; // reference time for when the AP can request a new block from the ESP32 uint8_t seq = 0; // holds current sequence number for transmission uint8_t __xdata blockbuffer[BLOCK_XFER_BUFFER_SIZE]; // block transfer buffer - +uint8_t lastAckMac[8] = {0}; void sendXferCompleteAck(uint8_t *dst); // tools @@ -437,7 +437,7 @@ void processAvailDataReq(uint8_t *buffer) { return; // prepare tx buffer to send a response - memset(radiotxbuffer, 0, sizeof(struct MacFrameNormal)+sizeof(struct AvailDataInfo)+2);//120); + memset(radiotxbuffer, 0, sizeof(struct MacFrameNormal) + sizeof(struct AvailDataInfo) + 2); // 120); struct MacFrameNormal *txHeader = (struct MacFrameNormal *)(radiotxbuffer + 1); struct AvailDataInfo *availDataInfo = (struct AvailDataInfo *)(radiotxbuffer + sizeof(struct MacFrameNormal) + 2); radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + sizeof(struct AvailDataInfo) + RAW_PKT_PADDING; @@ -468,14 +468,19 @@ void processAvailDataReq(uint8_t *buffer) { txHeader->seq = seq++; addCRC(availDataInfo, sizeof(struct AvailDataInfo)); radioTx(radiotxbuffer); + memset(lastAckMac, 0, 8); // reset lastAckMac, so we can record if we've received exactly one ack packet espNotifyAvailDataReq(availDataReq, rxHeader->src); } + void processXferComplete(uint8_t *buffer) { struct MacFrameNormal *rxHeader = (struct MacFrameNormal *)buffer; sendXferCompleteAck(rxHeader->src); - espNotifyXferComplete(rxHeader->src); - int8_t slot = findSlotForMac(rxHeader->src); - if (slot != -1) pendingDataArr[slot].attemptsLeft = 0; + if (memcmp(lastAckMac, rxHeader->src, 8) != 0) { + xMemCopyShort((void *__xdata)lastAckMac, (void *__xdata)rxHeader->src, 8); + espNotifyXferComplete(rxHeader->src); + int8_t slot = findSlotForMac(rxHeader->src); + if (slot != -1) pendingDataArr[slot].attemptsLeft = 0; + } } // send block data to the tag diff --git a/ap_fw/soc/zbs243/uart.c b/ap_fw/soc/zbs243/uart.c index 45d33b5a..9491e66b 100644 --- a/ap_fw/soc/zbs243/uart.c +++ b/ap_fw/soc/zbs243/uart.c @@ -21,7 +21,6 @@ void uartInit(void) { } extern uint8_t __xdata blockbuffer[]; -extern bool __xdata blockRequestInProgress; volatile uint8_t txtail = 0; volatile uint8_t txhead = 0; @@ -79,7 +78,6 @@ void UART_IRQ1(void) __interrupt(0) { *blockp++ = UARTBUF; if (blockp == (blockbuffer+4100)) { serialBypassActive = false; - blockRequestInProgress = false; } } else { rxbuf[rxhead] = UARTBUF; diff --git a/tag_fw/fw154.bin b/tag_fw/fw154.bin new file mode 100644 index 0000000000000000000000000000000000000000..5926bf48977c5baf4091a596498edae7d15835e0 GIT binary patch literal 32040 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 literal 0 HcmV?d00001 diff --git a/tag_fw/fw42.bin b/tag_fw/fw42.bin new file mode 100644 index 0000000000000000000000000000000000000000..f8571ed9d47bca0a4e223e0064ab13206f0021e2 GIT binary patch literal 31871 zcmeHw34Bvk{_o9Anx>`Dl2Qp$AeNx)R6#|lP%WsaXr*;@T*e@@h$2+DQPvXD0gm+8eOEnRb6Len;B-uHLzy=hwT&3pgP=l|a4y${9Q zOq{I!Pj=if4~OFDo3L7qG1SUJl4 zpw;KH>v`^Xi;LFdga4uXjQCzN(#tj(iFKU z#e7eu&$X&VMw;xC%j67x>=*8Mx6vKvHi(i=3YAIWGO43XTJPFWQYx1l%Hzt7pF(z7U;824kTG!u2GLew!z#pstWA z3lec5MKH-C$C>#TMJZK^9LgIkN_}v@vA-y#;XXN4lrF+Ow}&WQjC(}S>wgezZb^91 zEt#jjK>cGKPgho2`0A$rr!2968f~2f@x&PdtJCYe`sK-48oWT3Wsg7)`Bl2h1>J=`eoccUEF?-cbbKJqSz8EdEyKt(PWM#N z*CB=Tjdrt8a&A^w3fuJuB4**abMk7RZj!|sy%frYlPwKslpF0S8n3MiucwMN zyo3QWAetvAIp~*BVhwbTl1E*Ju0(gyKM-@`JOHGSWCzQ1Qm{;FEn@@f%+O%n*w*^7 zZ4G1Fk#k0_E0gQXBb^G zAAbj_XC$-+SM#Q&9G=2Kujhrcf^MtnEPKPHq199S=Y(3*pJ{aF_CiWir@DoPY9dVq ztqMg`Bb#c|XDZ+vXA;zuYHpSi<>8~1*NcP^JK)A{+(I~@BIPF&55WiVB6!-xj@$^+t)i;o~Oxh}*z8Wvnw3l3F z!w%}=4nY@EzA%)vC7zyazVj?8#7#OVR;o9h6)iPvjPnSlZQku_^5xC>$pKl)m#4_G zpmR%ZDYh;~Gu54Co=*N+PdrJHLE`D5e%aYyJbk&8pB&jJ$DyK=A0k!C?P{iY`ZiVr z0~sixRgfp1zPT$(LPUYqnXE#)SuxC~2R4&UXKjtjy;>`dmV0y|>^4^1Jm2 zc-d*ByN)tpFi#I;o+Z63JcE^$56Dz~Q zAZAOw6Fa<$hafQwa(v)QJbcV{?>=-7IEO%O_#-X96Yr@Uf zcK9cN{$Z?H_>8O{V{0`I4K`iV+I(%Be?mLtiF}FVL!7Rce@vu#Y=?3kyG06z&UkhP z>vpu(Z*ObZ*1pE|bje!TnI`0R=@R%~-hlic^=fpi&W#zXD>(7=T-8OTX@Fo*24j&j z7}vShmu!%mqk~Z}jA-{}k&}atLCprTFkn1r6i+XZ+CGe6Ts%&9jK}(-UgGH@sR$et zggDvxh&!GYa`O(?)o_|#bG^>`|8Xhk#{A+vB)!T+;>@sC|FvyYH{yH!iXf=XX!)~K65d49%*hsG39q}|E&olq%uE(k2OmAPv8N$bS{96EM1}6Y=Z8UVF-ic?dYGf-+3@;H<_or*PWPRW8%2l7v-qVu0xd zNS!K=G_gA~#1yQ%GNHBc%EVC9l|6vDJ6>=oeM{1`UT%u^E#zB;5zjCp(HJd>)yZsF zbpS6Z?Aeh$01r)`9heYRCray~{hYif6}nHX?j<{K^xGWdP@N8xBuk-Y&vqmyO6yoD zrXkw|lV@uH?~Q6Ts&|Ww)Exw26j9y?fSD3rdr5!5don%7GqRU*p2i(bTXW-(ic(5e z4=t-0Y@?(U9=a0XsZ8R-Y-8)9h2*q6$R(0=A4XT74%n50#`$AR+ zhSQv(WcbZVA06)3eI%LhzPURFD>y;y0>#`b=iF-db+49ui08783Y)rAJ-41S=$+D*`1!r{HA1?PW?8tA{Wm#Ok5c_%MN5A84RS9BU+B z#%vlX%%(JtXm84bqOdYMv79UBmSU#eK$EUUnsf=1vKPdkV3W)J#T0nIZ{l0VIiOT3g3t4`&`ENxeeLmZ>ZG-Ju^=L&j11;mN^vG z2Y4&mb+{DrVhn$J!Coc{PE@*FFY?IoU2I<1O(>)Ksf7qZeHGr8T8#j~RoBBIwHELaFjpy_Jz!px0ql6OT?wF)l>52y%??B06B?FFJ{5BsR4wVP`zH2950cu8Bs$MTK|?o@b(~ zNY7qHdiF-8NAr%w>UTAFmxQXUjKy`sV)X}1p$ewaA@8KH5I?%jJE>hTjt+V!wF+^g z13kTy0=-a~Df~c^{eIHBQe>@bU5V6zn7N)DF)5I;s;6sJFFYipMP?G1%%-@Lsm!V* zmpSb-AdUzMtIvd}7@GD2|8Ti^LYa)XH}8BdL$en9qLyZ#6c~m8@NoP_yguxW;ct#u z%dOL`k0-DjW%GlE{P^Jex(5Z_@UVA6$9gt9W9fQ*zCL__pK@-_;K7umAF(!WoiV0@ zwWiK_)qixh0&ZZfpIv+=oavKFyt>P!@a#y|W)(p^bQ< zN3v3b)JT8xq~)vrMiuL!_c7jnpR~-ip~g%)yJfvaEiZ=sTJ*i43c9~1g@t3 zOQ+7WN$(vCiO_oG<0#Be3FgP0FpvL7n4fAeV`_aWDRB7*CYi6BDEeOQTon*~Zwfcb z!ep4VmgD9L6CAD{=B#XoE0Le@<>8(cz04Ed6{~i8<-CuI^VU>})hB%s*%2{_RW}Qt z$ih)zcTx&OGR#*lGLQe8dHOx(yH{82F;8E|_dgQ#dq0cud&TO{G{1}7^x6l7GqRv( zLGm&d)Gw9&nq@NIw?~=8wxcWA5*#`kvfJ zF<}s^D-?g}D}xMihvvM>?~wVIsj$#;rHokl3VHulyrImY;iyg&V(lb9{>-+Kv@hr1Rwl_ zxx#T-XkpA0Yv*Gfid@j(V^sA1GBG$y$`4My1Sthl{x6e{qsPmo2%Obmp&ysoLWCyQ z!8z>us3sM`WvDLb%nwXj{zNh23}W?hAwgE|wz^CmMt1G?4lU^Jw>7YyDV+~kV z9&a8$jl6>0a)*#GqFuOHi;^IF{4}L!Bc3x`>$cTz_wOi=r>XOZ0FwK<>x~jk{>AE3!c6K_#kJLpNmy*z&Xfu7)MczSu8a3H zZ`S)ar)29g8f}%ix(s3F@DA^Uh(|E&5K?yL!a+O*AL9jCNZE=mua4rx6d7D^k5DKp z!4MS@tYn)R=V&pR4aFj~svi~fPHe5WiERzzYB6g#rB1(Sm=aay+fORW8?<(@eqqQ_ zZHXeF8{jzrN}Tx*o8H813a!UC+IEJT$F+3i#l>%sV}i-QhS!5+X?h&pn&jv@boF;# zG)$FOu257LAIi`C!71SQ4VB|@K}viBN{m22^XvmnM@iI8C@-aGjd zPwZ%z6p4y&yXVZdy6yEl8g}N+ijiE%?Heww&mgtyRH;4IRcax#oyGQ@c}=XYqRCko zi8T)zt2M-5lAvm2bJjB`i)l)R*wO~9F*wWc6I((gsPsTW->EZ(D~cdSXAB3JcO|P=P>T{bAE< zE?-Fy(d{-^#3e%fFxfj^l}uV2Vv=coK$XadrV!7J2=uPY3YhD!3#9rd2Kto8GZBRF zy@jbP#I95oyFX}R2Z5ukgJ*c>B?s#+p>YoNugaS;zT@qgs`P-0ZuOS49Rb3nQAbG` z+?{IP)3Bv?;}&z%mel4geK4;W{8BPMcyM$Q+y5Lf><4?Z7~$#v-vsZxa(1pfGTW(& z4`jzcvU4f6T$pWF$I4Euy*%UD8m!w!s~`RyFrJ$y)@>eCznQ}lYMr4`6G* zzimC=(mFO;w43#8paAHQMZ(q5u4X=QGC$-&A-ijuSS^uPRLqe|7nyJ8Y2N1Fo;$YL zwz=Iut~RusQ`Sr{X4@$cCec(b)G)k_1;V6yS}^H#kozdvc~Gp~qzvv3GPQ7oB-UW_ zJBE1wJ8_DuY+$akSpB1Lk1SlN#E*nqyC6l#zyzj%E4kB9Qk$a?(5pYQBIKsS4I zhoHk+Q`Sb9zzuSSnfqR~aO=4yo4d7nTt}OKT%=uavQ;Z(Hqv0uy;@leN?Z9fw^oPP zMt1XN9j)6N&P*-p&BDZ;vo>eP)5aAXqTLq>f9Zmz*m6MVkYRKVoPqIG!@4z5*QQR$ zkcFGjBh&DkO8l$QoSkJHDoO30#;p+Xq2)@@YDs9RZ@o(qR`?f}%_NhHkct-T74|Y3 zw15C+2GNxnp$>>)W+~Pf%y)iEJ+KLW1LALSnQ^uax>9}-+NQloG+&_UqWSi%REo;w z>est6lK7$5QJ79hQP!ffX~EDOKZlBBP%kve2#JE@Y|W9_PAh!yU;!6Zgw6QX(rOp= zLZjJu+a8x9LjIy;;UqFU*~yw~R+|&{j)~9;u4iXNaMA*gpSdnrOA}IdsjqG3+|#Ogq|j>gbO?{+AgeTKicJXGx4=u!+ED4<2nH{_7w zHfnu}r~+BRb>N-0tw9KYZC(4+m^%@%&6+p00nDaXKXp2CvD1g#RN$zEqiFTDWxroe z=7(c0xSv*&k*h8%P~4wkhnXbi4spVd(f&doA`Yf_OyaPv7=!M~heiU2&5{*6c!>Wkg(3+8`NW>upz9sbn0Ls|#(<#*; z4I@euPi6R#D( z7yiKHh%GzLOPAR4mf||L{DV!+vAKjMQkRO=VSuU*32>-u1K?gyT2YE{yh|SDvj|jQ7ds@(~FsISn+qXv8I2Q1NIy4VwpJSueLg{Cp-zm<>QxX&%0L{0ZlPX4{WgZjMA~ z3oeNY*_ZS&s+%b4-X}w4{S#J7)6pkvsM*?bQ&^m{QxU*OBP5`Xq9LFF`(LrSxNBEs zKKOsEt42jpAW=Y9b?v)ke$0t(T_sjWXwY=Z_5=SLvQ4{MNr)8bUZz_PAyPI*kr1^n z;ienvr^jIf0fKT7FT{KY?h>Lwmp^a5Gz~l3#$kR;^1ega6y1{)wdoM{zb5mS?3ao;#8K?-+=LDbSLIFv%yO+#ef;s-^7*^O0iG66r)`jQN6>8om7f_`X7pYt`z&MOR>Lp zYmKcl2!D&Fl42nb?c#18nmFeZ2e#6ipLTYbFWYP$7Sck3E$_$l3CtHF`j&1HeE~tj zGQ{kwG4C_;o6Y@?Xwja57t`L4Ju(c@0Qh#@Lb>(?HF7lkCv*B6%Hl(;!q=Z+VY?+z z?9SbhL*c59s%HFas`~oS*O9Ly`y%`H?fZJ4fBDzT_vs>zS2@RfoTC&**vl#FFFA*t zjt_NsrNtM~t5Z@PA98tzR^U}h<<-=Etd!Py+OmvS9~(6F#zzZ_UL0F^%WYhrHk4Hy~p!x^k3 zq_On|X8vLpn7lm|JUSPcP&tYXl+`xDx!t?NyEFUxQXWg}`4ZONvFeWdBkfJJ-hN9P zX2O(l{K(+r4k;ho|EqZ>#jaFYfvV5=>-V~I@Gt3-z z#pJwab!_DvFRXPuXQtV#x3}zjF7tGI-g99*OM&MzFcY8y9Hbx09pxM?6?)Bz$Luu= zy3sOiaxX6@1y^2D?kbnA(8RH`+(pWwmp9F~9tiaDt;O{stqsOR#DU5Y2l`a>;vm&K z>yMyRCv%laL{vsst#tu!UEZ2xK%l8>U~OQ%nn&gTE|B-xM$6g(`smDJyCHk#CJ%3Gw=qvNJ$sGsvT=uYoPA=CbRy{}RkEVc0 zrTkK^=^Z|$@g04V=-VM-Lg0Iewh?0)_MbBL=lWihpyOV)rH2IXl`@t|Hel&e^u4Tf zadV$QCEK>S{>u$t<$P_(`@9`_=wUzYy{+0RS$!#(!&m)L5`Ej`+?Pj<6dpd`~1DUV}8;17tjG@)fM6> zqHODm?-jOn#rFymqr(Y@6RCCDry}~c%ex~`WKdB_hxahlY#o7Tr4H3>czJNS7n(x2D}Yt}28bQQI}%QlJxSgeETgbcVH8Z{eFRMiOS-w_{gN z?^v1Pi~;R?TaI|J*{J}>7JP4GE!k=I2x~T~>jx0Fx9L!$?`_G}UydXvCo2=VII@jI zC;0>jrLe=Um}g>*A?DnvSoLwU%$T4Ic>?!0IdZ56mwoM_Brf+#vC0jN1CAe-{kA{^ z;Vf(`|4YEtJZ>WG_6mztVPw1$O+Z(iP=gd1kPGZJRN4Ek!rqrl3yq?K`0^u5cnX$qK3DNJJx z7=WF8qHkxX!0yBXWOB+L{%|tEHORY?p^H^H-bu1d`y-V(-}n<^mCST{G{F(!@;0{T zY&761a;wNupi;l0lmV6BSB6^7G2ZbR?>N!s`1FUIV+O~+bdE3D92GxQ>_!n%-eBlQ zVCzS;VYBM6(1NRnc70YI5w67bs9?kOpTbyNj|oM%eu98HSj)~4?c1M#}rmbbRw@*1k7Y7+}J_)~;&Zn7b z+U+cXcF3^F|QrS^@iRk-Ck*ds;xSV6-oqESHi=#@v;Ttiwy|v%1 z;|2Y_f$vM>25k6&X~K>F7JVNu$fc(?ew*{PiBxmDrkXz@IrJTt0;RipZ`$)^tU+O# zCsuDn$vW1BtfMMf$9|Kn*BDtJ5LtGRWhSyd)yO)bkmWdL0y$5E91jZ~ulerj@7JDE zsQEUQn(h>wU=(~x6qt#E7`@h|W1`rf?1KFlNWzoZ|=1@o&y?>WktpR`||kdIdxIOF}u7P>ycNXD*uP z`$lO~^nK+E0=Y_GE3V(5Qr=5`W<8}VMBgd$m~!58ioWku4z{dx)Mhwp?s9}UM?2@} z&^yAByp|ReP^zxra$ZXDy=3*a`|X8joB|}bZF$SJoNFH4fn#aP6)iIjihJ`2xe4oR zz(C5B`cekXIMkgYcvUvpAh#p)befjU0^-q3rW|Q?^aO3_W+%pP7?k%Ol)6XwN;xd< zI|`ixGbM68;2?R;+0$~NiN8WrCz42@ap#>WqVHey1mEgwy2DKLK`G=?(GGV!od9^8 zW^p)9g(6`pA97x9Q~Jb#U>M%!ozQh_Fubl)^>ip(E97Z@ z!M`>4$$HO@V8hN<;m^@EJ2RbP>c6TaeU&^QFp$RWoBezjds075{WMI@fj5MMO#N|? zDIEuy2H+smz_7cY`(kC!P7{{T^E@MoF>J&S1U{)aBP{1z)>bU(n#RI9oIQSo;-mc z`K`y=uy@o>&qoI zOAY{I23IL6|H1${WW$#%+*BzC1(~&LK%;}$Tl&i|6a+!^D zE@OxbI~OBYmSBG&J$l&_I)I;iz&xc!Um)uXO7su0jw^AyR;`Thbn}E?hpY^)F0rh3 zSypov?=xlgK6{5GEkjq*vuW>;i_B9;IBR3N!3Ci48GC2OS!yiKAKNEe_db@>kZ;wu zV&3R7-@Ij+i5?pJ5GKBoaU7hkwj)dV{N!Qc)O(*nYxUp#f|+B<_eQ!p*9+GYgcA*W zhbMf|VCSb|G=C{PKu4!QlLE-`t*!`6jzT zNO68Hn4Bl}EzH3?0WOL&-~10}{Nc*OUjUiLd_z&9`Q~kQ0_;5dA;&wPrq>>L{q`(> z;~M@ZpJ1hzR=hNTm_{L!@%(vQm;L6+Mgi&Y|(CwCb&-2--_TFtsKBBi-!4wyR#|rmDYLQZyc-TfPsWaeH z4>9bk%h%cC0dTR-$!>i6k^JQ0gdQ=JYM{M_Qw>pUzCQ(8_RTU1R`Ala&q13&ZoF6{ zi%ukNk!}CRDN=)6>_GR%Wka_9V^7?CXdwW zeV&aThnxr#gF}+#IAsOBSc3$q6(^_L>vDOUzBOOAy-iPxQdtJXFJn!~tFD??OX6G^)SWdJ`?s^4_MWrc_PA9qmN-AJ z_`-RjqSARZv(n_|P_mrMkTM$cbw!s{VB~X+`4)Sx{1m&f;%5u~Dt^LGwybek;$*Z( zxha&3(a+z!1%r@Xd0dZ{oH$x?)b;UEj2LhkTMxL691V~XYG<_$BgH)R4mKpf{0#Cu zS8=XYx{{2{%dZ$a?#ipK9)HdCH{?v7a%1QFjE82@Vs85MCLeR3J8kvUrfQ#mZ8C!PJK#^0QaL;}^`%x+Exw|E~e}ZH{8w zNolwn9fU3xJ+KsZ>(oQKxV$ax&eWVO24^qgh9L?(Zwp+%0Q%`XaUvzSrvzYv%A7o? zy796S zfUHid&eM1c*0fp_KyK-ErTXw7!D*`_=tD8>l&@_QxN%&tj<6Ws=99;-Rm?Nb+F}H- z&1yu35FE0ywKkYg+nRyN6v6uVXvxRNkGhU$n5PL~g?ZX$sSFp=lfUrOHbhgQ7S-gR zm1O8srF4L&O4m{ie{2n@Ov$-7CZ}7a7k)dd>;?Et=WDL)k)rrYx%o@vdGI^#MzqEx zji;7cLC=?7{`P#25W$stf%QO5KsK$`O|_?)R&!_MG9fZV4!||KCZNMgLURnug;rwE zm-h64obVKv@RZIY1$d&H@#K*r0|8bU$NHF87)r(YTkM0BN?Q3&NY@5l}K{;p)As zCA*L3%vgxb*nsR&KJOIga-Q+B+Sugv`bvlehc={Fv7=D=_r^-1&EqIBpt0J1Tja`; zv&5wA5wYo8pDTVECEy`C{!dle`)u&y(W{Q33osOp7WJFpWT}tNDiJ4l+;fP zH{9OgsY`7=lN$6iq_)?mwtfFEYo&n}4>kTNMxMBMXA-!0XA*e9cBQ(R^Dlw_E;!%z zMDk_u6$0qJ>;&&KxIv9Vl`#hgPfQgUz9czq!y^Z6Id8uqON55#|c&Y3fscak)$5A4DA*skf0~z2b$UZj1v72+e#X0tHjt@A8lXL9n zutw<+dB*|Hv5$AWsB;|TaCq#woZUAG`|tW-vLWyR?)!1ypZC_{ybl-W?FkBPckP?Z z2liF`sp8qgo6J|Y@>l;|jrg`H)}>9gE*{mo97Xhy&G}Q*IsYb1=cgYRY@RKyfSiGV z7Xtr_I8ovj8oE!qQjSxBgR2UIf7qaar?C;Jd*0jvpe9f9nIM9N$V^!$YR` zC+%0(L4`=*VBkPtzZ0>7SjjL?KcLK~$r~t*XB#68jrNPl74SaOT1M;s)Yo-#8LcL# zJF5{+)4p@(+vg`LDpJG{M?v68OR|%NpSncy5iCO9LJZiLwHi2gm|53eCm(+H@GjgT z2KbT|JKRp`6Xgn|PK-$)88w+EZ(Zt?BI^;X|OTyOLJ zMb6t3&e_N39OQHU!sopi&UuZlsM;C3Q=%Q_s|Fw=?=|F2l>&RvkQCU5hNJ*?uiqvG z{=$4~v345v@peF>`M?Kx&W^m@p^9BAxC$pnf5?@FNF8$KN_=i$8ja?|N=7pFAY^}= zvs+KesuM&<>Bpce%y(V3$5rv{M&&aFZp;I2M=I8ySPwZ|cd)k+c*B|$OUvwQEWUIF z=QI@CR$wO?^3jvD8kL!*%cw}(W!ZEQ`;?W!MvC|-YY<&!*v%oncKF5U@*GE|tLRWCP%44)E`czT^uw#Wg zF`}V=J7oP1NZt?$4_OkTSufiXJA_BDNQ+DCt>sAlCkWJlm@JTd7rt# zK(%i})m%a?a>$UXd|&rjN~cfwFjdhxS=^Pj>0+_=PVAu(63b+3THIkqcGnJ5MJHdk zLQfk+g|yM^kUa4{nq|K037;#|dxO ziS=SVzFC9Pq~6%6T4Il)`SKLam&Ys#K2@MDQiDk4)Jgv?;eN%DQEJ|$)Vxcn8P_=r z#1_1JKNV}$jLs%)?U=0I`>}t_81eUaE#!Yci~s$L{JpFBd*4B-R-R46%F2XW$pok` zcBjkIPBGpUV-mK6O+E$ zyE{Sa8E68-j!|EaU?fD5ec_|b`%F7E$)e@414)_HlJ-%Vve8ac)$QYM5)) z@RC&{WcFEbY|3Zde2~-I&4ZG$QD0gAz%KBAw^aoRy9{ef@65BQ6q~dL63)I_;wa%V zoE<+q;gP;x@`h_2x^a>8a_}{Itt`DftaTkiK@@CQh>cWKO?g>|5@RB3sn!@2XE#=MOsTw~1Sg{u z8Fnf%?816`ty7U;xGlv@Na-shMOSH}TC9qylILmO>fe^z8($qhk$M8+t>ijQJ;hpA zlkD7&8)*S2TkO*sWZ$;R?tx@{hgELgMiO02B|LNh4*I>A>GzGsLCr-T6(6R*62@WBp@P4;0c>Kz=zRXzwo!nz6{ z5<~e%?MZ4=tp8~2qZ9jNp6#P_VmxBZ)QLYjTfEO8giQN@@@|}*d#&~1f*G?47Fg%a z7p#Tz9rI=-a!UFW1q&9=nLp3^xdrpAmt1EZt0gLxt@Dd!&Yx9aoip!=8FS}E8=qD1#GIK0 zR$=~p>qB#9YgN?Lh4ZZoADc0E?xaf+xvs6unzL}m>;(k{j}^=lv`RqhmMN2`ii+khpt2K&a`_A9;6a#g zEt;`lA&`3*L_SueGH;}H)|^@ME)%Rz&R_88=+UFOg$46w&6ziw%1_CiY#n9gMsrpI zF}FY{7@f#Xo06Az{Y_J>mkn8XSt5Da9M7)*y_a}u-tu3DVd2LA=eoTZjH3Ts@cbpR zI`Ok4owrD`ocuj!DZVP}oAK#MnXHI$U{Y3AW^sCPRu;z@IeS*IWm(pu;^M5rEMuX4 z=FF^R_*Yz5IJ2;@ILn?@$R%-hlpDy|ElKu8DiozDF3FPlIG34}IiAZZzN+xsx#<># zVaBoPg@u`Ri?OhfL;cJ`PgY^!T)Vxn5J`YhNPiXv!9Ts=%0Qe{vyvBN*cfjhUGQ19VNy z%AB}tQC6X)7*tLyoT$^STQZZ-B*92B8n3c1OL_t@GK-UvJ_iKA zu!D}d_D7czj7-3I)KZwFz%a5T5SLVFd6b^#*)x$}SZD+c$djetH`E^%iyeGhQH+Ig z%h;r(^sAN?TEJ@JwB@_PW%j~l%k0G#<0AW`^9z?1F0(KgS(Z%J&0rz=hG5K9U=%SJ zS-^qvt%kvWBp6AV^8tg=VVRHw#v2PQ^Cof}=&*cO%;=b>&@me?;4APPX~|SzOhi&K zFt;QvQefD#hz?7k1-;5~*Sl`Q7%X04oL2}KtUod*BxM$^FcxMO0tfU52VSZDfv!iN z18E~*T!khwlc+x!FBuG#4!e_II+va~HpyOSOacr`dOGCF z;syvsuF#kQ19FuW3j-MphT0zl1Nnt^)*ownZ|lv*NB;@v8wSHZFsV4pxF{<#YkYb- z#)oA^A&n3F#KNqs!eWdMjEO8umIW}1GmS*YL`AL&i<6LF2)VK^8#od97+KV2ifOzF zr8o;lJH4Zdo!-?yYT?|!&Qt}4QUaV;GVFL_e@SQ(ZT4RC_!@f0BS+($?lFJeUez3} z4Tyx=EM=Sv!$RYnTd29x3Jgizl(JV6Zg#`<^S=UjkBcnF&p~XVM z!bGlU#=?bBlb6U96cjC(|Ckk~mFzk*;oTEq>_=J`&VLL}#GJWvtq&Dg9rGLu3*Z+_ znUXvGj%liIQ8;7HTuNky+xqaF*$-Ri0Ef8__z~8HbK%C2pQ4l^ROif_BUlyiiJWSu z7Zl7anDaz|b#{R;;|a7kYlbjm&b-3;-2A!BGZ<-|F?Rv{qQ%x(^PikIcRoC%S>S}0 zxUisL9&G-C8BdatFC@ZL`l9gX6+9WOJCb3p`UBAtDh{)(g>x1>_T-EO1pqL8%ALUe zKJJ10xar)3+yjXmJeUOqMRONh;fc+DXzu)(k1i;9+)=O)E{?EZ#=M2-0qe{e^JW&z z1yigKEw)~tiyi|>1P*mH{6|_dt*koy7h$1w!J^B+r0Mrq8Mx6L%d)CWW8T;d0nQ&# z(y)uR6zx=SU_L={6oGx@)pYV4e6>!yK4-M``iI~_p%7f2>vJZOpfCYF=OK~1;f_1< zr%aw`9ZH;2owG}ZB}RorX`GwkK$p&#`6ztV1v5c0ZgAF~j0LW^pbAzC5;-0I)Ul^q zI1>)yJgYG0v4Z&y2nvKom^1THh%1wlaig!WDn$~xt-62c#_B)jp4R$;JcT#ss_q=|)?gQO5`i17Uj8Rd<>GYTazzZ2mj0zka6vDE9@| zTfc$(8+SRsjw|B^^G*2R#^3Zma0B#@>z~xG)0gS@aTEA``medZ`kVCcaaZ%l_!d5u z-^dqmt8{a?1pQ08OZ3yYp1R+2{rDNW8GH_($NBjj-A}wvSEu_}f1PfzZZSVbcZco{ z{yY6r{d|3ZJF5Ree}KD=-@}dJf6yP$f34r6*OZUO3GMyD{Q?IraNq(5E^y!i2QF~n h0tYT|-~tCOaNq(5E^y!i2QF~n0tYT|;J?O!{{h$R)iVG9 literal 0 HcmV?d00001 diff --git a/tag_fw/syncedproto.c b/tag_fw/syncedproto.c index dfbac9e5..cb390b2d 100644 --- a/tag_fw/syncedproto.c +++ b/tag_fw/syncedproto.c @@ -133,7 +133,6 @@ struct blockRequestAck { } __packed; #define TIMER_TICKS_PER_MS 1333UL -#define RX_WINDOW_SIZE 10UL // ms // #define DEBUGBLOCKS // download-stuff @@ -149,26 +148,27 @@ uint32_t __xdata curHighSlotId = 0; uint8_t __xdata nextImgSlot = 0; uint8_t __xdata imgSlots = 0; -// stuff we need to keep track of because of the network +// stuff we need to keep track of related to the network/AP uint8_t __xdata APmac[8] = {0}; uint16_t __xdata APsrcPan = 0; uint8_t __xdata mSelfMac[8] = {0}; uint8_t __xdata seq = 0; -// timing stuff -bool __xdata isSynced = false; // are we synced to the network? -#define SYNC_CALIB_TIME 10000UL -#define MAX_NEXT_ATTEMPT_DELAY_MS 300000UL -#define MIN_NEXT_ATTEMPT_DELAY_MS 1000UL // wait at least this time -uint32_t __xdata nextAttempt = 1000; // delay before next attempt; -bool __xdata isCalibrated = false; // is the RC oscillator calibrated against the AP? -uint16_t __xdata calib = SYNC_CALIB_TIME; // RC oscillator calibration value -uint32_t __xdata APburstInterval = 0; -int8_t __xdata calibVector = 0; -uint16_t __xdata APburstLengthMs = 0; // burst length in ms -uint8_t __xdata APburstLength = 0; +// power saving algorithm +#define INTERVAL_BASE 40 // interval (in seconds) (when 1 packet is sent/received) for target current (7.2µA) +#define INTERVAL_AT_MAX_ATTEMPTS 600 // interval (in seconds) (at max attempts) for target average current +#define INTERVAL_NO_SIGNAL 1800 // interval (in seconds) when no answer for POWER_SAVING_SMOOTHING attempts, + // (INTERVAL_AT_MAX_ATTEMPTS * POWER_SAVING_SMOOTHING) seconds +#define DATA_REQ_RX_WINDOW_SIZE 5UL // How many milliseconds we should wait for a packet during the data_request. + // If the AP holds a long list of data for tags, it may need a little more time to lookup the mac address +#define DATA_REQ_MAX_ATTEMPTS 14 // How many attempts (at most) we should do to get something back from the AP +#define POWER_SAVING_SMOOTHING 8 // How many samples we should use to smooth the data request interval +#define MINIMUM_INTERVAL 45 // IMPORTANT: Minimum interval for check-in; this determines overal battery life! +uint16_t __xdata dataReqAttemptArr[POWER_SAVING_SMOOTHING] = {0}; // Holds the amount of attempts required per data_req/check-in +uint8_t __xdata dataReqAttemptArrayIndex = 0; +uint8_t __xdata dataReqLastAttempt = 0; -// buffer we use to prepare packets +// buffer we use to prepare/read packets // static uint8_t __xdata mRxBuf[130]; static uint8_t __xdata inBuffer[128] = {0}; static uint8_t __xdata outBuffer[128] = {0}; @@ -187,13 +187,6 @@ uint8_t __xdata getPacketType(void *__xdata buffer) { } return 0; } -uint32_t __xdata getNextAttemptDelay() { - nextAttempt *= 2; - if (nextAttempt > MAX_NEXT_ATTEMPT_DELAY_MS) { - nextAttempt = MAX_NEXT_ATTEMPT_DELAY_MS; - } - return nextAttempt; -} void dump(uint8_t *__xdata a, uint16_t __xdata l) { pr("\n "); #define ROWS 16 @@ -261,15 +254,36 @@ void initAfterWake() { initRadio(); } void doSleep(uint32_t __xdata t) { + pr("s=%lu\n ", t/1000); powerPortsDownForSleep(); // sleepy - sleepForMsec(t * SYNC_CALIB_TIME / (uint32_t)calib); + sleepForMsec(t); initAfterWake(); } +uint16_t getNextSleep() { + uint16_t __xdata curval = INTERVAL_AT_MAX_ATTEMPTS - INTERVAL_BASE; + curval *= dataReqLastAttempt; + curval /= DATA_REQ_MAX_ATTEMPTS; + curval += INTERVAL_BASE; + dataReqAttemptArr[dataReqAttemptArrayIndex % POWER_SAVING_SMOOTHING] = curval; + dataReqAttemptArrayIndex++; + + uint16_t avg = 0; + bool noNetwork = true; + for (uint8_t c = 0; c < POWER_SAVING_SMOOTHING; c++) { + avg += dataReqAttemptArr[c]; + if (dataReqAttemptArr[c] != INTERVAL_AT_MAX_ATTEMPTS) { + noNetwork = false; + } + } + if (noNetwork == true) return INTERVAL_NO_SIGNAL; + avg /= POWER_SAVING_SMOOTHING; + return avg; +} // data xfer stuff void sendAvailDataReq() { - struct MacFrameBcast __xdata *txframe = (struct MacFrameBcast *)(outBuffer+1); + struct MacFrameBcast __xdata *txframe = (struct MacFrameBcast *)(outBuffer + 1); memset(outBuffer, 0, sizeof(struct MacFrameBcast) + sizeof(struct AvailDataReq) + 2 + 4); struct AvailDataReq *__xdata availreq = (struct AvailDataReq *)(outBuffer + 2 + sizeof(struct MacFrameBcast)); outBuffer[0] = sizeof(struct MacFrameBcast) + sizeof(struct AvailDataReq) + 2 + 2; @@ -290,9 +304,9 @@ void sendAvailDataReq() { } struct AvailDataInfo *__xdata getAvailDataInfo() { uint32_t __xdata t; - for (uint8_t c = 0; c < 15; c++) { + for (uint8_t c = 0; c < DATA_REQ_MAX_ATTEMPTS; c++) { sendAvailDataReq(); - t = timerGet() + (TIMER_TICKS_PER_MS * 10UL); + t = timerGet() + (TIMER_TICKS_PER_MS * DATA_REQ_RX_WINDOW_SIZE); while (timerGet() < t) { int8_t __xdata ret = commsRxUnencrypted(inBuffer); if (ret > 1) { @@ -301,12 +315,16 @@ struct AvailDataInfo *__xdata getAvailDataInfo() { struct MacFrameNormal *__xdata f = (struct MacFrameNormal *)inBuffer; memcpy(APmac, f->src, 8); APsrcPan = f->pan; + // pr("RSSI: %d\n", commsGetLastPacketRSSI()); + // pr("LQI: %d\n", commsGetLastPacketLQI()); + dataReqLastAttempt = c; return (struct AvailDataInfo *)(inBuffer + sizeof(struct MacFrameNormal) + 1); } } } } } + dataReqLastAttempt = DATA_REQ_MAX_ATTEMPTS; return NULL; } void processBlockPart(struct blockPart *bp) { @@ -359,7 +377,8 @@ void sendBlockRequest() { struct MacFrameNormal *__xdata f = (struct MacFrameNormal *)(outBuffer + 1); struct blockRequest *__xdata blockreq = (struct blockRequest *)(outBuffer + 2 + sizeof(struct MacFrameNormal)); outBuffer[0] = sizeof(struct MacFrameNormal) + sizeof(struct blockRequest) + 2 + 2; - if (requestPartialBlock) {; + if (requestPartialBlock) { + ; outBuffer[sizeof(struct MacFrameNormal) + 1] = PKT_BLOCK_PARTIAL_REQUEST; } else { outBuffer[sizeof(struct MacFrameNormal) + 1] = PKT_BLOCK_REQUEST; @@ -398,8 +417,8 @@ struct blockRequestAck *__xdata performBlockRequest() { break; case PKT_BLOCK_PART: // block already started while we were waiting for a get block reply - //pr("!"); - //processBlockPart((struct blockPart *)(inBuffer + sizeof(struct MacFrameNormal) + 1)); + // pr("!"); + // processBlockPart((struct blockPart *)(inBuffer + sizeof(struct MacFrameNormal) + 1)); return continueToRX(); break; default: @@ -411,7 +430,7 @@ struct blockRequestAck *__xdata performBlockRequest() { } while (timerGet() < t); } return continueToRX(); - //return NULL; + // return NULL; } void sendXferCompletePacket() { memset(outBuffer, 0, sizeof(struct MacFrameNormal) + 2 + 4); @@ -451,6 +470,15 @@ void sendXferComplete() { pr("XFC NACK!\n"); return; } +bool validateBlockData() { + struct blockData *bd = (struct blockData *)blockXferBuffer; + // pr("expected len = %04X, checksum=%04X\n", bd->size, bd->checksum); + uint16_t t = 0; + for (uint16_t c = 0; c < bd->size; c++) { + t += bd->data[c]; + } + return bd->checksum == t; +} const uint8_t epd_bitmap_ant[] = { 0xff, 0xbf, 0xfd, 0xdf, 0xfe, 0xdf, 0xee, 0xdf, 0xee, 0xdf, 0xed, 0xdf, 0xd7, 0xbf, 0xd7, 0xff, @@ -529,7 +557,6 @@ void saveUpdateBlockData(uint8_t blockId) { if (!eepromWrite(EEPROM_UPDATA_AREA_START + (blockId * BLOCK_DATA_SIZE), blockXferBuffer + sizeof(struct blockData), BLOCK_DATA_SIZE)) pr("EEPROM write failed\n"); } - void saveImgBlockData(uint8_t blockId) { uint16_t length = EEPROM_IMG_EACH - (sizeof(struct EepromImageHeader) + (blockId * BLOCK_DATA_SIZE)); if (length > 4096) length = 4096; @@ -562,19 +589,9 @@ uint32_t getHighSlotId() { return temp; } -bool validateBlockData() { - struct blockData *bd = (struct blockData *)blockXferBuffer; - // pr("expected len = %04X, checksum=%04X\n", bd->size, bd->checksum); - uint16_t t = 0; - for (uint16_t c = 0; c < bd->size; c++) { - t += bd->data[c]; - } - return bd->checksum == t; -} - #define DEBUGBLOCKS // Main download function -void doDataDownload(struct AvailDataInfo* __xdata avail){ +void doDataDownload(struct AvailDataInfo *__xdata avail) { // this is the main function for the download process if (!eepromInit()) { // we'll need the eeprom here, init it. @@ -681,7 +698,7 @@ void doDataDownload(struct AvailDataInfo* __xdata avail){ pr("]\n"); #endif - //timerDelay(TIMER_TICKS_PER_MS*100); + // timerDelay(TIMER_TICKS_PER_MS*100); // DO BLOCK REQUEST - request a block, get an ack with timing info (hopefully) struct blockRequestAck *__xdata ack = performBlockRequest(); @@ -711,14 +728,14 @@ void doDataDownload(struct AvailDataInfo* __xdata avail){ } // BLOCK RX LOOP - receive a block, until the timeout has passed - if (!blockRxLoop(440)) { // was 340 + if (!blockRxLoop(440)) { // was 340 // didn't receive packets blockRequestAttempt++; if (blockRequestAttempt > 5) { pr("bailing on download, 0 blockparts rx'd\n"); return; } else { - //goto startdownload; + // goto startdownload; } } else { // successfull block RX loop @@ -815,7 +832,7 @@ void doDataDownload(struct AvailDataInfo* __xdata avail){ sendXferComplete(); killRadio(); eepromReadStart(EEPROM_UPDATA_AREA_START); - //wdtDeviceReset(); + // wdtDeviceReset(); selfUpdate(); break; @@ -856,8 +873,6 @@ void mainProtocolLoop(void) { // i2ctest(); pr("BOOTED> (new version!)\n\n"); - isSynced = false; - isCalibrated = false; if (!eepromInit()) { pr("failed to init eeprom\n"); @@ -869,20 +884,27 @@ void mainProtocolLoop(void) { curHighSlotId = getHighSlotId(); } + // initialize attempt-array with the default value; + for (uint8_t c = 0; c < POWER_SAVING_SMOOTHING; c++) { + dataReqAttemptArr[c] = INTERVAL_BASE; + } + screenSleep(); eepromDeepPowerDown(); initRadio(); // drawPartial(); // i2ctest(); - + // doSleep(10000); while (1) { radioRxEnable(true, true); struct AvailDataInfo *__xdata avail = getAvailDataInfo(); - if(avail->dataType!=DATATYPE_NOUPDATE){ - doDataDownload(avail); + if (avail == NULL) { } else { - pr("nothing.\n"); + if (avail->dataType != DATATYPE_NOUPDATE) { + doDataDownload(avail); + } else { + } } - doSleep(10000); + doSleep(getNextSleep()*1000UL); } } \ No newline at end of file