| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733 |
- /*!
- * \file LoRaMac.c
- *
- * \brief LoRa MAC layer implementation
- *
- * \copyright Revised BSD License, see section \ref LICENSE.
- *
- * \code
- * ______ _
- * / _____) _ | |
- * ( (____ _____ ____ _| |_ _____ ____| |__
- * \____ \| ___ | (_ _) ___ |/ ___) _ \
- * _____) ) ____| | | || |_| ____( (___| | | |
- * (______/|_____)_|_|_| \__)_____)\____)_| |_|
- * (C)2013-2017 Semtech
- *
- * ___ _____ _ ___ _ _____ ___ ___ ___ ___
- * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
- * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
- * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
- * embedded.connectivity.solutions===============
- *
- * \endcode
- *
- * \author Miguel Luis ( Semtech )
- *
- * \author Gregory Cristian ( Semtech )
- *
- * \author Daniel Jaeckle ( STACKFORCE )
- *
- * \author Johannes Bruder ( STACKFORCE )
- */
- #include "utilities.h"
- #include "Region.h"
- #include "LoRaMacClassB.h"
- #include "LoRaMacCrypto.h"
- #include "secure-element.h"
- #include "LoRaMacTest.h"
- #include "LoRaMacTypes.h"
- #include "LoRaMacConfirmQueue.h"
- #include "LoRaMacHeaderTypes.h"
- #include "LoRaMacMessageTypes.h"
- #include "LoRaMacParser.h"
- #include "LoRaMacCommands.h"
- #include "LoRaMacAdr.h"
- #include "lora-radio-timer.h"
- #include "LoRaMac.h"
- /*!
- * Maximum PHY layer payload size
- */
- #define LORAMAC_PHY_MAXPAYLOAD 255
- /*!
- * Maximum MAC commands buffer size
- */
- #define LORA_MAC_COMMAND_MAX_LENGTH 128
- /*!
- * Maximum length of the fOpts field
- */
- #define LORA_MAC_COMMAND_MAX_FOPTS_LENGTH 15
- /*!
- * LoRaMac duty cycle for the back-off procedure during the first hour.
- */
- #define BACKOFF_DC_1_HOUR 100
- /*!
- * LoRaMac duty cycle for the back-off procedure during the next 10 hours.
- */
- #define BACKOFF_DC_10_HOURS 1000
- /*!
- * LoRaMac duty cycle for the back-off procedure during the next 24 hours.
- */
- #define BACKOFF_DC_24_HOURS 10000
- /*!
- * LoRaMac internal states
- */
- enum eLoRaMacState
- {
- LORAMAC_IDLE = 0x00000000,
- LORAMAC_STOPPED = 0x00000001,
- LORAMAC_TX_RUNNING = 0x00000002,
- LORAMAC_RX = 0x00000004,
- LORAMAC_ACK_RETRY = 0x00000010,
- LORAMAC_TX_DELAYED = 0x00000020,
- LORAMAC_TX_CONFIG = 0x00000040,
- LORAMAC_RX_ABORT = 0x00000080,
- };
- /*
- * Request permission state
- */
- typedef enum eLoRaMacRequestHandling
- {
- LORAMAC_REQUEST_HANDLING_OFF = 0,
- LORAMAC_REQUEST_HANDLING_ON = !LORAMAC_REQUEST_HANDLING_OFF
- }LoRaMacRequestHandling_t;
- typedef struct sLoRaMacNvmCtx
- {
- /*
- * LoRaMac region.
- */
- LoRaMacRegion_t Region;
- /*
- * LoRaMac default parameters
- */
- LoRaMacParams_t MacParamsDefaults;
- /*
- * Network ID ( 3 bytes )
- */
- uint32_t NetID;
- /*
- * Mote Address
- */
- uint32_t DevAddr;
- /*!
- * Multicast channel list
- */
- MulticastCtx_t MulticastChannelList[LORAMAC_MAX_MC_CTX];
- /*
- * Actual device class
- */
- DeviceClass_t DeviceClass;
- /*
- * Indicates if the node is connected to
- * a private or public network
- */
- bool PublicNetwork;
- /*
- * LoRaMac ADR control status
- */
- bool AdrCtrlOn;
- /*
- * Counts the number of missed ADR acknowledgements
- */
- uint32_t AdrAckCounter;
- /*
- * LoRaMac parameters
- */
- LoRaMacParams_t MacParams;
- /*
- * Maximum duty cycle
- * \remark Possibility to shutdown the device.
- */
- uint8_t MaxDCycle;
- /*
- * Enables/Disables duty cycle management (Test only)
- */
- bool DutyCycleOn;
- /*
- * Current channel index
- */
- uint8_t LastTxChannel;
- /*
- * Holds the current rx window slot
- */
- bool RepeaterSupport;
- /*
- * Buffer containing the MAC layer commands
- */
- uint8_t MacCommandsBuffer[LORA_MAC_COMMAND_MAX_LENGTH];
- /*
- * If the server has sent a FRAME_TYPE_DATA_CONFIRMED_DOWN this variable indicates
- * if the ACK bit must be set for the next transmission
- */
- bool SrvAckRequested;
- /*
- * Aggregated duty cycle management
- */
- uint16_t AggregatedDCycle;
- /*
- * Aggregated duty cycle management
- */
- TimerTime_t LastTxDoneTime;
- TimerTime_t AggregatedTimeOff;
- /*
- * Stores the time at LoRaMac initialization.
- *
- * \remark Used for the BACKOFF_DC computation.
- */
- SysTime_t InitializationTime;
- /*
- * Current LoRaWAN Version
- */
- Version_t Version;
- /*
- * End-Device network activation
- */
- ActivationType_t NetworkActivation;
- /*!
- * Last received Message integrity Code (MIC)
- */
- uint32_t LastRxMic;
- }LoRaMacNvmCtx_t;
- typedef struct sLoRaMacCtx
- {
- /*
- * Length of packet in PktBuffer
- */
- uint16_t PktBufferLen;
- /*
- * Buffer containing the data to be sent or received.
- */
- uint8_t PktBuffer[LORAMAC_PHY_MAXPAYLOAD];
- /*!
- * Current processed transmit message
- */
- LoRaMacMessage_t TxMsg;
- /*!
- * Buffer containing the data received by the application.
- */
- uint8_t AppData[LORAMAC_PHY_MAXPAYLOAD];
- /*
- * Size of buffer containing the application data.
- */
- uint8_t AppDataSize;
- /*
- * Buffer containing the upper layer data.
- */
- uint8_t RxPayload[LORAMAC_PHY_MAXPAYLOAD];
- SysTime_t LastTxSysTime;
- /*
- * LoRaMac internal state
- */
- uint32_t MacState;
- /*
- * LoRaMac upper layer event functions
- */
- LoRaMacPrimitives_t* MacPrimitives;
- /*
- * LoRaMac upper layer callback functions
- */
- LoRaMacCallback_t* MacCallbacks;
- /*
- * Radio events function pointer
- */
- RadioEvents_t RadioEvents;
- /*
- * LoRaMac duty cycle delayed Tx timer
- */
- TimerEvent_t TxDelayedTimer;
- /*
- * LoRaMac reception windows timers
- */
- TimerEvent_t RxWindowTimer1;
- TimerEvent_t RxWindowTimer2;
- /*
- * LoRaMac reception windows delay
- * \remark normal frame: RxWindowXDelay = ReceiveDelayX - RADIO_WAKEUP_TIME
- * join frame : RxWindowXDelay = JoinAcceptDelayX - RADIO_WAKEUP_TIME
- */
- uint32_t RxWindow1Delay;
- uint32_t RxWindow2Delay;
- /*
- * LoRaMac Rx windows configuration
- */
- RxConfigParams_t RxWindow1Config;
- RxConfigParams_t RxWindow2Config;
- RxConfigParams_t RxWindowCConfig;
- /*
- * Limit of uplinks without any donwlink response before the ADRACKReq bit will be set.
- */
- uint16_t AdrAckLimit;
- /*
- * Limit of uplinks without any donwlink response after a the first frame with set ADRACKReq bit
- * before the trying to regain the connectivity.
- */
- uint16_t AdrAckDelay;
- /*
- * Acknowledge timeout timer. Used for packet retransmissions.
- */
- TimerEvent_t AckTimeoutTimer;
- /*
- * Uplink messages repetitions counter
- */
- uint8_t ChannelsNbTransCounter;
- /*
- * Number of trials to get a frame acknowledged
- */
- uint8_t AckTimeoutRetries;
- /*
- * Number of trials to get a frame acknowledged
- */
- uint8_t AckTimeoutRetriesCounter;
- /*
- * Indicates if the AckTimeout timer has expired or not
- */
- bool AckTimeoutRetry;
- /*
- * If the node has sent a FRAME_TYPE_DATA_CONFIRMED_UP this variable indicates
- * if the nodes needs to manage the server acknowledgement.
- */
- bool NodeAckRequested;
- /*
- * Current channel index
- */
- uint8_t Channel;
- /*
- * Last transmission time on air
- */
- TimerTime_t TxTimeOnAir;
- /*
- * Structure to hold an MCPS indication data.
- */
- McpsIndication_t McpsIndication;
- /*
- * Structure to hold MCPS confirm data.
- */
- McpsConfirm_t McpsConfirm;
- /*
- * Structure to hold MLME confirm data.
- */
- MlmeConfirm_t MlmeConfirm;
- /*
- * Structure to hold MLME indication data.
- */
- MlmeIndication_t MlmeIndication;
- /*
- * Holds the current rx window slot
- */
- LoRaMacRxSlot_t RxSlot;
- /*
- * LoRaMac tx/rx operation state
- */
- LoRaMacFlags_t MacFlags;
- /*
- * Data structure indicating if a request is allowed or not.
- */
- LoRaMacRequestHandling_t AllowRequests;
- /*
- * Non-volatile module context structure
- */
- LoRaMacNvmCtx_t* NvmCtx;
- }LoRaMacCtx_t;
- /*
- * Module context.
- */
- static LoRaMacCtx_t MacCtx;
- /*
- * Non-volatile module context.
- */
- static LoRaMacNvmCtx_t NvmMacCtx;
- /*
- * List of module contexts.
- */
- LoRaMacCtxs_t Contexts;
- /*!
- * Defines the LoRaMac radio events status
- */
- typedef union uLoRaMacRadioEvents
- {
- uint32_t Value;
- struct sEvents
- {
- uint32_t RxTimeout : 1;
- uint32_t RxError : 1;
- uint32_t TxTimeout : 1;
- uint32_t RxDone : 1;
- uint32_t TxDone : 1;
- }Events;
- }LoRaMacRadioEvents_t;
- /*!
- * LoRaMac radio events status
- */
- LoRaMacRadioEvents_t LoRaMacRadioEvents = { .Value = 0 };
- /*!
- * \brief Function to be executed on Radio Tx Done event
- */
- static void OnRadioTxDone( void );
- /*!
- * \brief This function prepares the MAC to abort the execution of function
- * OnRadioRxDone in case of a reception error.
- */
- static void PrepareRxDoneAbort( void );
- /*!
- * \brief Function to be executed on Radio Rx Done event
- */
- static void OnRadioRxDone( uint8_t* payload, uint16_t size, int16_t rssi, int8_t snr );
- /*!
- * \brief Function executed on Radio Tx Timeout event
- */
- static void OnRadioTxTimeout( void );
- /*!
- * \brief Function executed on Radio Rx error event
- */
- static void OnRadioRxError( void );
- /*!
- * \brief Function executed on Radio Rx Timeout event
- */
- static void OnRadioRxTimeout( void );
- /*!
- * \brief Function executed on duty cycle delayed Tx timer event
- */
- static void OnTxDelayedTimerEvent( void );
- /*!
- * \brief Function executed on first Rx window timer event
- */
- static void OnRxWindow1TimerEvent( void );
- /*!
- * \brief Function executed on second Rx window timer event
- */
- static void OnRxWindow2TimerEvent( void );
- /*!
- * \brief Function executed on AckTimeout timer event
- */
- static void OnAckTimeoutTimerEvent( void );
- /*!
- * \brief Configures the events to trigger an MLME-Indication with
- * a MLME type of MLME_SCHEDULE_UPLINK.
- */
- static void SetMlmeScheduleUplinkIndication( void );
- /*!
- * Computes next 32 bit downlink counter value and determines the frame counter ID.
- *
- * \param[IN] addrID - Address identifier
- * \param[IN] fType - Frame type
- * \param[IN] macMsg - Data message object, holding the current 16 bit transmitted frame counter
- * \param[IN] lrWanVersion - LoRaWAN version
- * \param[IN] maxFCntGap - Maximum allowed frame counter difference (only for 1.0.X necessary)
- * \param[OUT] fCntID - Frame counter identifier
- * \param[OUT] currentDown - Current downlink counter value
- *
- * \retval - Status of the operation
- */
- static LoRaMacCryptoStatus_t GetFCntDown( AddressIdentifier_t addrID, FType_t fType, LoRaMacMessageData_t* macMsg, Version_t lrWanVersion,
- uint16_t maxFCntGap, FCntIdentifier_t* fCntID, uint32_t* currentDown );
- /*!
- * \brief Switches the device class
- *
- * \param [IN] deviceClass Device class to switch to
- */
- static LoRaMacStatus_t SwitchClass( DeviceClass_t deviceClass );
- /*!
- * \brief Gets the maximum application payload length in the absence of the optional FOpt field.
- *
- * \param [IN] datarate Current datarate
- *
- * \retval Max length
- */
- static uint8_t GetMaxAppPayloadWithoutFOptsLength( int8_t datarate );
- /*!
- * \brief Validates if the payload fits into the frame, taking the datarate
- * into account.
- *
- * \details Refer to chapter 4.3.2 of the LoRaWAN specification, v1.0
- *
- * \param lenN Length of the application payload. The length depends on the
- * datarate and is region specific
- *
- * \param datarate Current datarate
- *
- * \param fOptsLen Length of the fOpts field
- *
- * \retval [false: payload does not fit into the frame, true: payload fits into
- * the frame]
- */
- static bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen );
- /*!
- * \brief Decodes MAC commands in the fOpts field and in the payload
- *
- * \param [IN] payload A pointer to the payload
- * \param [IN] macIndex The index of the payload where the MAC commands start
- * \param [IN] commandsSize The size of the MAC commands
- * \param [IN] snr The SNR value of the frame
- * \param [IN] rxSlot The RX slot where the frame was received
- */
- static void ProcessMacCommands( uint8_t* payload, uint8_t macIndex, uint8_t commandsSize, int8_t snr, LoRaMacRxSlot_t rxSlot );
- /*!
- * \brief LoRaMAC layer generic send frame
- *
- * \param [IN] macHdr MAC header field
- * \param [IN] fPort MAC payload port
- * \param [IN] fBuffer MAC data buffer to be sent
- * \param [IN] fBufferSize MAC data buffer size
- * \retval status Status of the operation.
- */
- LoRaMacStatus_t Send( LoRaMacHeader_t* macHdr, uint8_t fPort, void* fBuffer, uint16_t fBufferSize );
- /*!
- * \brief LoRaMAC layer send join/rejoin request
- *
- * \param [IN] joinReqType Type of join-request or rejoin
- *
- * \retval status Status of the operation.
- */
- LoRaMacStatus_t SendReJoinReq( JoinReqIdentifier_t joinReqType );
- /*!
- * \brief LoRaMAC layer frame buffer initialization
- *
- * \param [IN] macHdr MAC header field
- * \param [IN] fCtrl MAC frame control field
- * \param [IN] fOpts MAC commands buffer
- * \param [IN] fPort MAC payload port
- * \param [IN] fBuffer MAC data buffer to be sent
- * \param [IN] fBufferSize MAC data buffer size
- * \retval status Status of the operation.
- */
- LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t* macHdr, LoRaMacFrameCtrl_t* fCtrl, uint8_t fPort, void* fBuffer, uint16_t fBufferSize );
- /*
- * \brief Schedules the frame according to the duty cycle
- *
- * \param [IN] allowDelayedTx When set to true, the a frame will be delayed,
- * the duty cycle restriction is active
- * \retval Status of the operation
- */
- static LoRaMacStatus_t ScheduleTx( bool allowDelayedTx );
- /*
- * \brief Secures the current processed frame ( TxMsg )
- * \param[IN] txDr Data rate used for the transmission
- * \param[IN] txCh Index of the channel used for the transmission
- * \retval status Status of the operation
- */
- static LoRaMacStatus_t SecureFrame( uint8_t txDr, uint8_t txCh );
- /*
- * \brief Calculates the back-off time for the band of a channel.
- *
- * \param [IN] channel The last Tx channel index
- */
- static void CalculateBackOff( uint8_t channel );
- /*
- * \brief Function to remove pending MAC commands
- *
- * \param [IN] rxSlot The RX slot on which the frame was received
- * \param [IN] fCtrl The frame control field of the received frame
- * \param [IN] request The request type
- */
- static void RemoveMacCommands( LoRaMacRxSlot_t rxSlot, LoRaMacFrameCtrl_t fCtrl, Mcps_t request );
- /*!
- * \brief LoRaMAC layer prepared frame buffer transmission with channel specification
- *
- * \remark PrepareFrame must be called at least once before calling this
- * function.
- *
- * \param [IN] channel Channel to transmit on
- * \retval status Status of the operation.
- */
- LoRaMacStatus_t SendFrameOnChannel( uint8_t channel );
- /*!
- * \brief Sets the radio in continuous transmission mode
- *
- * \remark Uses the radio parameters set on the previous transmission.
- *
- * \param [IN] timeout Time in seconds while the radio is kept in continuous wave mode
- * \retval status Status of the operation.
- */
- LoRaMacStatus_t SetTxContinuousWave( uint16_t timeout );
- /*!
- * \brief Sets the radio in continuous transmission mode
- *
- * \remark Uses the radio parameters set on the previous transmission.
- *
- * \param [IN] timeout Time in seconds while the radio is kept in continuous wave mode
- * \param [IN] frequency RF frequency to be set.
- * \param [IN] power RF output power to be set.
- * \retval status Status of the operation.
- */
- LoRaMacStatus_t SetTxContinuousWave1( uint16_t timeout, uint32_t frequency, uint8_t power );
- /*!
- * \brief Resets MAC specific parameters to default
- */
- static void ResetMacParameters( void );
- /*!
- * \brief Initializes and opens the reception window
- *
- * \param [IN] rxTimer Window timer to be topped.
- * \param [IN] rxConfig Window parameters to be setup
- */
- static void RxWindowSetup( TimerEvent_t* rxTimer, RxConfigParams_t* rxConfig );
- /*!
- * \brief Opens up a continuous RX C window. This is used for
- * class c devices.
- */
- static void OpenContinuousRxCWindow( void );
- /*!
- * \brief Returns a pointer to the internal contexts structure.
- *
- * \retval void Points to a structure containing all contexts
- */
- LoRaMacCtxs_t* GetCtxs( void );
- /*!
- * \brief Restoring of internal module contexts
- *
- * \details This function allows to restore module contexts by a given pointer.
- *
- *
- * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
- * returns are:
- * \ref LORAMAC_STATUS_OK,
- * \ref LORAMAC_STATUS_PARAMETER_INVALID,
- */
- LoRaMacStatus_t RestoreCtxs( LoRaMacCtxs_t* contexts );
- /*!
- * \brief Determines the frame type
- *
- * \param [IN] macMsg Data message object
- *
- * \param [OUT] fType Frame type
- *
- * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
- * returns are:
- * \ref LORAMAC_STATUS_OK,
- * \ref LORAMAC_STATUS_PARAMETER_INVALID,
- */
- LoRaMacStatus_t DetermineFrameType( LoRaMacMessageData_t* macMsg, FType_t* fType );
- /*!
- * \brief Checks if the retransmission should be stopped in case of a unconfirmed uplink
- *
- * \retval Returns true if it should be stopped.
- */
- static bool CheckRetransUnconfirmedUplink( void );
- /*!
- * \brief Checks if the retransmission should be stopped in case of a confirmed uplink
- *
- * \retval Returns true it should be stopped.
- */
- static bool CheckRetransConfirmedUplink( void );
- /*!
- * \brief Stops the uplink retransmission
- *
- * \retval Returns true if successful.
- */
- static bool StopRetransmission( void );
- /*!
- * \brief Handles the ACK retries algorithm.
- * Increments the re-tries counter up until the specified number of
- * trials or the allowed maximum. Decrease the uplink datarate every 2
- * trials.
- */
- static void AckTimeoutRetriesProcess( void );
- /*!
- * \brief Finalizes the ACK retries algorithm.
- * If no ACK is received restores the default channels
- */
- static void AckTimeoutRetriesFinalize( void );
- /*!
- * \brief Calls the callback to indicate that a context changed
- */
- static void CallNvmCtxCallback( LoRaMacNvmCtxModule_t module );
- /*!
- * \brief MAC NVM Context has been changed
- */
- static void EventMacNvmCtxChanged( void );
- /*!
- * \brief Region NVM Context has been changed
- */
- static void EventRegionNvmCtxChanged( void );
- /*!
- * \brief Crypto NVM Context has been changed
- */
- static void EventCryptoNvmCtxChanged( void );
- /*!
- * \brief Secure Element NVM Context has been changed
- */
- static void EventSecureElementNvmCtxChanged( void );
- /*!
- * \brief MAC commands module nvm context has been changed
- */
- static void EventCommandsNvmCtxChanged( void );
- /*!
- * \brief Class B module nvm context has been changed
- */
- static void EventClassBNvmCtxChanged( void );
- /*!
- * \brief Confirm Queue module nvm context has been changed
- */
- static void EventConfirmQueueNvmCtxChanged( void );
- /*!
- * \brief Verifies if a request is pending currently
- *
- *\retval 1: Request pending, 0: request not pending
- */
- static uint8_t IsRequestPending( void );
- /*!
- * \brief Enabled the possibility to perform requests
- *
- * \param [IN] requestState Request permission state
- */
- static void LoRaMacEnableRequests( LoRaMacRequestHandling_t requestState );
- /*!
- * \brief This function verifies if a RX abort occurred
- */
- static void LoRaMacCheckForRxAbort( void );
- /*!
- * \brief This function verifies if a beacon acquisition MLME
- * request was pending
- *
- * \retval 1: Request pending, 0: no request pending
- */
- static uint8_t LoRaMacCheckForBeaconAcquisition( void );
- /*!
- * \brief This function handles join request
- */
- static void LoRaMacHandleMlmeRequest( void );
- /*!
- * \brief This function handles mcps request
- */
- static void LoRaMacHandleMcpsRequest( void );
- /*!
- * \brief This function handles callback events for requests
- */
- static void LoRaMacHandleRequestEvents( void );
- /*!
- * \brief This function handles callback events for indications
- */
- static void LoRaMacHandleIndicationEvents( void );
- /*!
- * Structure used to store the radio Tx event data
- */
- struct
- {
- TimerTime_t CurTime;
- }TxDoneParams;
- /*!
- * Structure used to store the radio Rx event data
- */
- struct
- {
- TimerTime_t LastRxDone;
- uint8_t *Payload;
- uint16_t Size;
- int16_t Rssi;
- int8_t Snr;
- }RxDoneParams;
- static void OnRadioTxDone( void )
- {
- TxDoneParams.CurTime = TimerGetCurrentTime( );
- // MacCtx.LastTxSysTime = SysTimeGet( );
- LoRaMacRadioEvents.Events.TxDone = 1;
- if( ( MacCtx.MacCallbacks != NULL ) && ( MacCtx.MacCallbacks->MacProcessNotify != NULL ) )
- {
- MacCtx.MacCallbacks->MacProcessNotify( );
- }
- }
- static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
- {
- RxDoneParams.LastRxDone = TimerGetCurrentTime( );
- RxDoneParams.Payload = payload;
- RxDoneParams.Size = size;
- RxDoneParams.Rssi = rssi;
- RxDoneParams.Snr = snr;
- LoRaMacRadioEvents.Events.RxDone = 1;
- if( ( MacCtx.MacCallbacks != NULL ) && ( MacCtx.MacCallbacks->MacProcessNotify != NULL ) )
- {
- MacCtx.MacCallbacks->MacProcessNotify( );
- }
- }
- static void OnRadioTxTimeout( void )
- {
- LoRaMacRadioEvents.Events.TxTimeout = 1;
- if( ( MacCtx.MacCallbacks != NULL ) && ( MacCtx.MacCallbacks->MacProcessNotify != NULL ) )
- {
- MacCtx.MacCallbacks->MacProcessNotify( );
- }
- }
- static void OnRadioRxError( void )
- {
- LoRaMacRadioEvents.Events.RxError = 1;
- if( ( MacCtx.MacCallbacks != NULL ) && ( MacCtx.MacCallbacks->MacProcessNotify != NULL ) )
- {
- MacCtx.MacCallbacks->MacProcessNotify( );
- }
- }
- static void OnRadioRxTimeout( void )
- {
- LoRaMacRadioEvents.Events.RxTimeout = 1;
- if( ( MacCtx.MacCallbacks != NULL ) && ( MacCtx.MacCallbacks->MacProcessNotify != NULL ) )
- {
- MacCtx.MacCallbacks->MacProcessNotify( );
- }
- }
- static void UpdateRxSlotIdleState( void )
- {
- if( MacCtx.NvmCtx->DeviceClass != CLASS_C )
- {
- MacCtx.RxSlot = RX_SLOT_NONE;
- }
- else
- {
- MacCtx.RxSlot = RX_SLOT_WIN_CLASS_C;
- }
- }
- static void ProcessRadioTxDone( void )
- {
- GetPhyParams_t getPhy;
- PhyParam_t phyParam;
- SetBandTxDoneParams_t txDone;
- if( MacCtx.NvmCtx->DeviceClass != CLASS_C )
- {
- Radio.Sleep( );
- }
- // Setup timers
- TimerSetValue( &MacCtx.RxWindowTimer1, MacCtx.RxWindow1Delay );
- TimerStart( &MacCtx.RxWindowTimer1 );
- TimerSetValue( &MacCtx.RxWindowTimer2, MacCtx.RxWindow2Delay );
- TimerStart( &MacCtx.RxWindowTimer2 );
- if( ( MacCtx.NvmCtx->DeviceClass == CLASS_C ) || ( MacCtx.NodeAckRequested == true ) )
- {
- getPhy.Attribute = PHY_ACK_TIMEOUT;
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- TimerSetValue( &MacCtx.AckTimeoutTimer, MacCtx.RxWindow2Delay + phyParam.Value );
- TimerStart( &MacCtx.AckTimeoutTimer );
- }
- // Store last Tx channel
- MacCtx.NvmCtx->LastTxChannel = MacCtx.Channel;
- // Update last tx done time for the current channel
- txDone.Channel = MacCtx.Channel;
- if( MacCtx.NvmCtx->NetworkActivation == ACTIVATION_TYPE_NONE )
- {
- txDone.Joined = false;
- }
- else
- {
- txDone.Joined = true;
- }
- txDone.LastTxDoneTime = TxDoneParams.CurTime;
- RegionSetBandTxDone( MacCtx.NvmCtx->Region, &txDone );
- // Update Aggregated last tx done time
- MacCtx.NvmCtx->LastTxDoneTime = TxDoneParams.CurTime;
- if( MacCtx.NodeAckRequested == false )
- {
- MacCtx.McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
- }
- }
- static void PrepareRxDoneAbort( void )
- {
- MacCtx.MacState |= LORAMAC_RX_ABORT;
- if( MacCtx.NodeAckRequested == true )
- {
- OnAckTimeoutTimerEvent( );
- }
- MacCtx.MacFlags.Bits.McpsInd = 1;
- MacCtx.MacFlags.Bits.MacDone = 1;
- UpdateRxSlotIdleState( );
- }
- static void ProcessRadioRxDone( void )
- {
- LoRaMacHeader_t macHdr;
- ApplyCFListParams_t applyCFList;
- GetPhyParams_t getPhy;
- PhyParam_t phyParam;
- LoRaMacCryptoStatus_t macCryptoStatus = LORAMAC_CRYPTO_ERROR;
- LoRaMacMessageData_t macMsgData;
- LoRaMacMessageJoinAccept_t macMsgJoinAccept;
- uint8_t *payload = RxDoneParams.Payload;
- uint16_t size = RxDoneParams.Size;
- int16_t rssi = RxDoneParams.Rssi;
- int8_t snr = RxDoneParams.Snr;
- uint8_t pktHeaderLen = 0;
- uint32_t downLinkCounter = 0;
- uint32_t address = MacCtx.NvmCtx->DevAddr;
- uint8_t multicast = 0;
- AddressIdentifier_t addrID = UNICAST_DEV_ADDR;
- FCntIdentifier_t fCntID;
- MacCtx.McpsConfirm.AckReceived = false;
- MacCtx.McpsIndication.Rssi = rssi;
- MacCtx.McpsIndication.Snr = snr;
- MacCtx.McpsIndication.RxSlot = MacCtx.RxSlot;
- MacCtx.McpsIndication.Port = 0;
- MacCtx.McpsIndication.Multicast = 0;
- MacCtx.McpsIndication.FramePending = 0;
- MacCtx.McpsIndication.Buffer = NULL;
- MacCtx.McpsIndication.BufferSize = 0;
- MacCtx.McpsIndication.RxData = false;
- MacCtx.McpsIndication.AckReceived = false;
- MacCtx.McpsIndication.DownLinkCounter = 0;
- MacCtx.McpsIndication.McpsIndication = MCPS_UNCONFIRMED;
- MacCtx.McpsIndication.DevAddress = 0;
- MacCtx.McpsIndication.DeviceTimeAnsReceived = false;
- Radio.Sleep( );
- TimerStop( &MacCtx.RxWindowTimer2 );
- // This function must be called even if we are not in class b mode yet.
- if( LoRaMacClassBRxBeacon( payload, size ) == true )
- {
- MacCtx.MlmeIndication.BeaconInfo.Rssi = rssi;
- MacCtx.MlmeIndication.BeaconInfo.Snr = snr;
- return;
- }
- // Check if we expect a ping or a multicast slot.
- if( MacCtx.NvmCtx->DeviceClass == CLASS_B )
- {
- if( LoRaMacClassBIsPingExpected( ) == true )
- {
- LoRaMacClassBSetPingSlotState( PINGSLOT_STATE_CALC_PING_OFFSET );
- LoRaMacClassBPingSlotTimerEvent( NULL );
- MacCtx.McpsIndication.RxSlot = RX_SLOT_WIN_CLASS_B_PING_SLOT;
- }
- else if( LoRaMacClassBIsMulticastExpected( ) == true )
- {
- LoRaMacClassBSetMulticastSlotState( PINGSLOT_STATE_CALC_PING_OFFSET );
- LoRaMacClassBMulticastSlotTimerEvent( NULL );
- MacCtx.McpsIndication.RxSlot = RX_SLOT_WIN_CLASS_B_MULTICAST_SLOT;
- }
- }
- macHdr.Value = payload[pktHeaderLen++];
- switch( macHdr.Bits.MType )
- {
- case FRAME_TYPE_JOIN_ACCEPT:
- macMsgJoinAccept.Buffer = payload;
- macMsgJoinAccept.BufSize = size;
- // Abort in case if the device isn't joined yet and no rejoin request is ongoing.
- if( MacCtx.NvmCtx->NetworkActivation != ACTIVATION_TYPE_NONE )
- {
- MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
- PrepareRxDoneAbort( );
- return;
- }
- macCryptoStatus = LoRaMacCryptoHandleJoinAccept( JOIN_REQ, SecureElementGetJoinEui( ), &macMsgJoinAccept );
- if( LORAMAC_CRYPTO_SUCCESS == macCryptoStatus )
- {
- // Network ID
- MacCtx.NvmCtx->NetID = ( uint32_t ) macMsgJoinAccept.NetID[0];
- MacCtx.NvmCtx->NetID |= ( ( uint32_t ) macMsgJoinAccept.NetID[1] << 8 );
- MacCtx.NvmCtx->NetID |= ( ( uint32_t ) macMsgJoinAccept.NetID[2] << 16 );
- // Device Address
- MacCtx.NvmCtx->DevAddr = macMsgJoinAccept.DevAddr;
- // DLSettings
- MacCtx.NvmCtx->MacParams.Rx1DrOffset = macMsgJoinAccept.DLSettings.Bits.RX1DRoffset;
- MacCtx.NvmCtx->MacParams.Rx2Channel.Datarate = macMsgJoinAccept.DLSettings.Bits.RX2DataRate;
- MacCtx.NvmCtx->MacParams.RxCChannel.Datarate = macMsgJoinAccept.DLSettings.Bits.RX2DataRate;
- // RxDelay
- MacCtx.NvmCtx->MacParams.ReceiveDelay1 = macMsgJoinAccept.RxDelay;
- if( MacCtx.NvmCtx->MacParams.ReceiveDelay1 == 0 )
- {
- MacCtx.NvmCtx->MacParams.ReceiveDelay1 = 1;
- }
- MacCtx.NvmCtx->MacParams.ReceiveDelay1 *= 1000;
- MacCtx.NvmCtx->MacParams.ReceiveDelay2 = MacCtx.NvmCtx->MacParams.ReceiveDelay1 + 1000;
- MacCtx.NvmCtx->Version.Fields.Minor = 0;
- // Apply CF list
- applyCFList.Payload = macMsgJoinAccept.CFList;
- // Size of the regular payload is 12. Plus 1 byte MHDR and 4 bytes MIC
- applyCFList.Size = size - 17;
- RegionApplyCFList( MacCtx.NvmCtx->Region, &applyCFList );
- MacCtx.NvmCtx->NetworkActivation = ACTIVATION_TYPE_OTAA;
- // MLME handling
- if( LoRaMacConfirmQueueIsCmdActive( MLME_JOIN ) == true )
- {
- LoRaMacConfirmQueueSetStatus( LORAMAC_EVENT_INFO_STATUS_OK, MLME_JOIN );
- }
- }
- else
- {
- // MLME handling
- if( LoRaMacConfirmQueueIsCmdActive( MLME_JOIN ) == true )
- {
- LoRaMacConfirmQueueSetStatus( LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL, MLME_JOIN );
- }
- }
- break;
- case FRAME_TYPE_DATA_CONFIRMED_DOWN:
- MacCtx.McpsIndication.McpsIndication = MCPS_CONFIRMED;
- // Intentional fall through
- case FRAME_TYPE_DATA_UNCONFIRMED_DOWN:
- // Check if the received payload size is valid
- getPhy.UplinkDwellTime = MacCtx.NvmCtx->MacParams.DownlinkDwellTime;
- getPhy.Datarate = MacCtx.McpsIndication.RxDatarate;
- getPhy.Attribute = PHY_MAX_PAYLOAD;
- // Get the maximum payload length
- if( MacCtx.NvmCtx->RepeaterSupport == true )
- {
- getPhy.Attribute = PHY_MAX_PAYLOAD_REPEATER;
- }
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- if( MAX( 0, ( int16_t )( ( int16_t ) size - ( int16_t ) LORA_MAC_FRMPAYLOAD_OVERHEAD ) ) > ( int16_t )phyParam.Value )
- {
- MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
- PrepareRxDoneAbort( );
- return;
- }
- macMsgData.Buffer = payload;
- macMsgData.BufSize = size;
- macMsgData.FRMPayload = MacCtx.RxPayload;
- macMsgData.FRMPayloadSize = LORAMAC_PHY_MAXPAYLOAD;
- if( LORAMAC_PARSER_SUCCESS != LoRaMacParserData( &macMsgData ) )
- {
- MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
- PrepareRxDoneAbort( );
- return;
- }
- // Store device address
- MacCtx.McpsIndication.DevAddress = macMsgData.FHDR.DevAddr;
- FType_t fType;
- if( LORAMAC_STATUS_OK != DetermineFrameType( &macMsgData, &fType ) )
- {
- MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
- PrepareRxDoneAbort( );
- return;
- }
- //Check if it is a multicast message
- multicast = 0;
- downLinkCounter = 0;
- for( uint8_t i = 0; i < LORAMAC_MAX_MC_CTX; i++ )
- {
- if( ( MacCtx.NvmCtx->MulticastChannelList[i].ChannelParams.Address == macMsgData.FHDR.DevAddr ) &&
- ( MacCtx.NvmCtx->MulticastChannelList[i].ChannelParams.IsEnabled == true ) )
- {
- multicast = 1;
- addrID = MacCtx.NvmCtx->MulticastChannelList[i].ChannelParams.GroupID;
- downLinkCounter = *( MacCtx.NvmCtx->MulticastChannelList[i].DownLinkCounter );
- address = MacCtx.NvmCtx->MulticastChannelList[i].ChannelParams.Address;
- if( MacCtx.NvmCtx->DeviceClass == CLASS_C )
- {
- MacCtx.McpsIndication.RxSlot = RX_SLOT_WIN_CLASS_C_MULTICAST;
- }
- break;
- }
- }
- // Get maximum allowed counter difference
- getPhy.Attribute = PHY_MAX_FCNT_GAP;
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- // Get downlink frame counter value
- macCryptoStatus = GetFCntDown( addrID, fType, &macMsgData, MacCtx.NvmCtx->Version, phyParam.Value, &fCntID, &downLinkCounter );
- if( macCryptoStatus != LORAMAC_CRYPTO_SUCCESS )
- {
- if( macCryptoStatus == LORAMAC_CRYPTO_FAIL_FCNT_DUPLICATED )
- {
- // Catch the case of repeated downlink frame counter
- MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED;
- if( ( MacCtx.NvmCtx->Version.Fields.Minor == 0 ) && ( macHdr.Bits.MType == FRAME_TYPE_DATA_CONFIRMED_DOWN ) && ( MacCtx.NvmCtx->LastRxMic == macMsgData.MIC ) )
- {
- MacCtx.NvmCtx->SrvAckRequested = true;
- }
- }
- else if( macCryptoStatus == LORAMAC_CRYPTO_FAIL_MAX_GAP_FCNT )
- {
- // Lost too many frames
- MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS;
- }
- else
- {
- // Other errors
- MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
- }
- MacCtx.McpsIndication.DownLinkCounter = downLinkCounter;
- PrepareRxDoneAbort( );
- return;
- }
- macCryptoStatus = LoRaMacCryptoUnsecureMessage( addrID, address, fCntID, downLinkCounter, &macMsgData );
- if( macCryptoStatus != LORAMAC_CRYPTO_SUCCESS )
- {
- if( macCryptoStatus == LORAMAC_CRYPTO_FAIL_ADDRESS )
- {
- // We are not the destination of this frame.
- MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL;
- }
- else
- {
- // MIC calculation fail
- MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL;
- }
- PrepareRxDoneAbort( );
- return;
- }
- // Frame is valid
- MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK;
- MacCtx.McpsIndication.Multicast = multicast;
- MacCtx.McpsIndication.FramePending = macMsgData.FHDR.FCtrl.Bits.FPending;
- MacCtx.McpsIndication.Buffer = NULL;
- MacCtx.McpsIndication.BufferSize = 0;
- MacCtx.McpsIndication.DownLinkCounter = downLinkCounter;
- MacCtx.McpsIndication.AckReceived = macMsgData.FHDR.FCtrl.Bits.Ack;
- MacCtx.McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
- MacCtx.McpsConfirm.AckReceived = macMsgData.FHDR.FCtrl.Bits.Ack;
- // Reset ADR ACK Counter only, when RX1 or RX2 slot
- if( ( MacCtx.McpsIndication.RxSlot == RX_SLOT_WIN_1 ) ||
- ( MacCtx.McpsIndication.RxSlot == RX_SLOT_WIN_2 ) )
- {
- MacCtx.NvmCtx->AdrAckCounter = 0;
- }
- // MCPS Indication and ack requested handling
- if( multicast == 1 )
- {
- MacCtx.McpsIndication.McpsIndication = MCPS_MULTICAST;
- }
- else
- {
- if( macHdr.Bits.MType == FRAME_TYPE_DATA_CONFIRMED_DOWN )
- {
- MacCtx.NvmCtx->SrvAckRequested = true;
- if( MacCtx.NvmCtx->Version.Fields.Minor == 0 )
- {
- MacCtx.NvmCtx->LastRxMic = macMsgData.MIC;
- }
- MacCtx.McpsIndication.McpsIndication = MCPS_CONFIRMED;
- }
- else
- {
- MacCtx.NvmCtx->SrvAckRequested = false;
- MacCtx.McpsIndication.McpsIndication = MCPS_UNCONFIRMED;
- }
- }
- RemoveMacCommands( MacCtx.McpsIndication.RxSlot, macMsgData.FHDR.FCtrl, MacCtx.McpsConfirm.McpsRequest );
- switch( fType )
- {
- case FRAME_TYPE_A:
- { /* +----------+------+-------+--------------+
- * | FOptsLen | Fopt | FPort | FRMPayload |
- * +----------+------+-------+--------------+
- * | > 0 | X | > 0 | X |
- * +----------+------+-------+--------------+
- */
- // Decode MAC commands in FOpts field
- ProcessMacCommands( macMsgData.FHDR.FOpts, 0, macMsgData.FHDR.FCtrl.Bits.FOptsLen, snr, MacCtx.McpsIndication.RxSlot );
- MacCtx.McpsIndication.Port = macMsgData.FPort;
- MacCtx.McpsIndication.Buffer = macMsgData.FRMPayload;
- MacCtx.McpsIndication.BufferSize = macMsgData.FRMPayloadSize;
- MacCtx.McpsIndication.RxData = true;
- break;
- }
- case FRAME_TYPE_B:
- { /* +----------+------+-------+--------------+
- * | FOptsLen | Fopt | FPort | FRMPayload |
- * +----------+------+-------+--------------+
- * | > 0 | X | - | - |
- * +----------+------+-------+--------------+
- */
- // Decode MAC commands in FOpts field
- ProcessMacCommands( macMsgData.FHDR.FOpts, 0, macMsgData.FHDR.FCtrl.Bits.FOptsLen, snr, MacCtx.McpsIndication.RxSlot );
- MacCtx.McpsIndication.Port = macMsgData.FPort;
- break;
- }
- case FRAME_TYPE_C:
- { /* +----------+------+-------+--------------+
- * | FOptsLen | Fopt | FPort | FRMPayload |
- * +----------+------+-------+--------------+
- * | = 0 | - | = 0 | MAC commands |
- * +----------+------+-------+--------------+
- */
- // Decode MAC commands in FRMPayload
- ProcessMacCommands( macMsgData.FRMPayload, 0, macMsgData.FRMPayloadSize, snr, MacCtx.McpsIndication.RxSlot );
- MacCtx.McpsIndication.Port = macMsgData.FPort;
- break;
- }
- case FRAME_TYPE_D:
- { /* +----------+------+-------+--------------+
- * | FOptsLen | Fopt | FPort | FRMPayload |
- * +----------+------+-------+--------------+
- * | = 0 | - | > 0 | X |
- * +----------+------+-------+--------------+
- */
- // No MAC commands just application payload
- MacCtx.McpsIndication.Port = macMsgData.FPort;
- MacCtx.McpsIndication.Buffer = macMsgData.FRMPayload;
- MacCtx.McpsIndication.BufferSize = macMsgData.FRMPayloadSize;
- MacCtx.McpsIndication.RxData = true;
- break;
- }
- default:
- MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
- PrepareRxDoneAbort( );
- break;
- }
- // Provide always an indication, skip the callback to the user application,
- // in case of a confirmed downlink retransmission.
- MacCtx.MacFlags.Bits.McpsInd = 1;
- break;
- case FRAME_TYPE_PROPRIETARY:
- memcpy1( MacCtx.RxPayload, &payload[pktHeaderLen], size - pktHeaderLen );
- MacCtx.McpsIndication.McpsIndication = MCPS_PROPRIETARY;
- MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK;
- MacCtx.McpsIndication.Buffer = MacCtx.RxPayload;
- MacCtx.McpsIndication.BufferSize = size - pktHeaderLen;
- MacCtx.MacFlags.Bits.McpsInd = 1;
- break;
- default:
- MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
- PrepareRxDoneAbort( );
- break;
- }
- // Verify if we need to disable the AckTimeoutTimer
- if( MacCtx.NodeAckRequested == true )
- {
- if( MacCtx.McpsConfirm.AckReceived == true )
- {
- OnAckTimeoutTimerEvent( );
- }
- }
- else
- {
- if( MacCtx.NvmCtx->DeviceClass == CLASS_C )
- {
- OnAckTimeoutTimerEvent( );
- }
- }
- MacCtx.MacFlags.Bits.MacDone = 1;
- UpdateRxSlotIdleState( );
- }
- static void ProcessRadioTxTimeout( void )
- {
- if( MacCtx.NvmCtx->DeviceClass != CLASS_C )
- {
- Radio.Sleep( );
- }
- UpdateRxSlotIdleState( );
- MacCtx.McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT;
- LoRaMacConfirmQueueSetStatusCmn( LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT );
- if( MacCtx.NodeAckRequested == true )
- {
- MacCtx.AckTimeoutRetry = true;
- }
- MacCtx.MacFlags.Bits.MacDone = 1;
- }
- static void HandleRadioRxErrorTimeout( LoRaMacEventInfoStatus_t rx1EventInfoStatus, LoRaMacEventInfoStatus_t rx2EventInfoStatus )
- {
- bool classBRx = false;
- if( MacCtx.NvmCtx->DeviceClass != CLASS_C )
- {
- Radio.Sleep( );
- }
- if( LoRaMacClassBIsBeaconExpected( ) == true )
- {
- LoRaMacClassBSetBeaconState( BEACON_STATE_TIMEOUT );
- LoRaMacClassBBeaconTimerEvent( NULL );
- classBRx = true;
- }
- if( MacCtx.NvmCtx->DeviceClass == CLASS_B )
- {
- if( LoRaMacClassBIsPingExpected( ) == true )
- {
- LoRaMacClassBSetPingSlotState( PINGSLOT_STATE_CALC_PING_OFFSET );
- LoRaMacClassBPingSlotTimerEvent( NULL );
- classBRx = true;
- }
- if( LoRaMacClassBIsMulticastExpected( ) == true )
- {
- LoRaMacClassBSetMulticastSlotState( PINGSLOT_STATE_CALC_PING_OFFSET );
- LoRaMacClassBMulticastSlotTimerEvent( NULL );
- classBRx = true;
- }
- }
- if( classBRx == false )
- {
- if( MacCtx.RxSlot == RX_SLOT_WIN_1 )
- {
- if( MacCtx.NodeAckRequested == true )
- {
- MacCtx.McpsConfirm.Status = rx1EventInfoStatus;
- }
- LoRaMacConfirmQueueSetStatusCmn( rx1EventInfoStatus );
- if( TimerGetElapsedTime( MacCtx.NvmCtx->LastTxDoneTime ) >= MacCtx.RxWindow2Delay )
- {
- TimerStop( &MacCtx.RxWindowTimer2 );
- MacCtx.MacFlags.Bits.MacDone = 1;
- }
- }
- else
- {
- if( MacCtx.NodeAckRequested == true )
- {
- MacCtx.McpsConfirm.Status = rx2EventInfoStatus;
- }
- LoRaMacConfirmQueueSetStatusCmn( rx2EventInfoStatus );
- if( MacCtx.NvmCtx->DeviceClass != CLASS_C )
- {
- MacCtx.MacFlags.Bits.MacDone = 1;
- }
- }
- }
- UpdateRxSlotIdleState( );
- }
- static void ProcessRadioRxError( void )
- {
- HandleRadioRxErrorTimeout( LORAMAC_EVENT_INFO_STATUS_RX1_ERROR, LORAMAC_EVENT_INFO_STATUS_RX2_ERROR );
- }
- static void ProcessRadioRxTimeout( void )
- {
- HandleRadioRxErrorTimeout( LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT, LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT );
- }
- static void LoRaMacHandleIrqEvents( void )
- {
- LoRaMacRadioEvents_t events;
- CRITICAL_SECTION_BEGIN( );
- events = LoRaMacRadioEvents;
- LoRaMacRadioEvents.Value = 0;
- CRITICAL_SECTION_END( );
- if( events.Value != 0 )
- {
- if( events.Events.TxDone == 1 )
- {
- ProcessRadioTxDone( );
- }
- if( events.Events.RxDone == 1 )
- {
- ProcessRadioRxDone( );
- }
- if( events.Events.TxTimeout == 1 )
- {
- ProcessRadioTxTimeout( );
- }
- if( events.Events.RxError == 1 )
- {
- ProcessRadioRxError( );
- }
- if( events.Events.RxTimeout == 1 )
- {
- ProcessRadioRxTimeout( );
- }
- }
- }
- bool LoRaMacIsBusy( void )
- {
- if( ( MacCtx.MacState == LORAMAC_IDLE ) &&
- ( MacCtx.AllowRequests == LORAMAC_REQUEST_HANDLING_ON ) )
- {
- return false;
- }
- return true;
- }
- static void LoRaMacEnableRequests( LoRaMacRequestHandling_t requestState )
- {
- MacCtx.AllowRequests = requestState;
- }
- static void LoRaMacHandleRequestEvents( void )
- {
- // Handle events
- LoRaMacFlags_t reqEvents = MacCtx.MacFlags;
- if( MacCtx.MacState == LORAMAC_IDLE )
- {
- // Update event bits
- if( MacCtx.MacFlags.Bits.McpsReq == 1 )
- {
- MacCtx.MacFlags.Bits.McpsReq = 0;
- }
- if( MacCtx.MacFlags.Bits.MlmeReq == 1 )
- {
- MacCtx.MacFlags.Bits.MlmeReq = 0;
- }
- // Allow requests again
- LoRaMacEnableRequests( LORAMAC_REQUEST_HANDLING_ON );
- // Handle callbacks
- if( reqEvents.Bits.McpsReq == 1 )
- {
- MacCtx.MacPrimitives->MacMcpsConfirm( &MacCtx.McpsConfirm );
- }
- if( reqEvents.Bits.MlmeReq == 1 )
- {
- LoRaMacConfirmQueueHandleCb( &MacCtx.MlmeConfirm );
- if( LoRaMacConfirmQueueGetCnt( ) > 0 )
- {
- MacCtx.MacFlags.Bits.MlmeReq = 1;
- }
- }
- // Start beaconing again
- LoRaMacClassBResumeBeaconing( );
- // Procedure done. Reset variables.
- MacCtx.MacFlags.Bits.MacDone = 0;
- }
- }
- static void LoRaMacHandleScheduleUplinkEvent( void )
- {
- // Handle events
- if( MacCtx.MacState == LORAMAC_IDLE )
- {
- // Verify if sticky MAC commands are pending or not
- bool isStickyMacCommandPending = false;
- LoRaMacCommandsStickyCmdsPending( &isStickyMacCommandPending );
- if( isStickyMacCommandPending == true )
- {// Setup MLME indication
- SetMlmeScheduleUplinkIndication( );
- }
- }
- }
- static void LoRaMacHandleIndicationEvents( void )
- {
- // Handle MLME indication
- if( MacCtx.MacFlags.Bits.MlmeInd == 1 )
- {
- MacCtx.MacFlags.Bits.MlmeInd = 0;
- MacCtx.MacPrimitives->MacMlmeIndication( &MacCtx.MlmeIndication );
- }
- if( MacCtx.MacFlags.Bits.MlmeSchedUplinkInd == 1 )
- {
- MlmeIndication_t schduleUplinkIndication;
- schduleUplinkIndication.MlmeIndication = MLME_SCHEDULE_UPLINK;
- schduleUplinkIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK;
- MacCtx.MacPrimitives->MacMlmeIndication( &schduleUplinkIndication );
- MacCtx.MacFlags.Bits.MlmeSchedUplinkInd = 0;
- }
- // Handle MCPS indication
- if( MacCtx.MacFlags.Bits.McpsInd == 1 )
- {
- MacCtx.MacFlags.Bits.McpsInd = 0;
- MacCtx.MacPrimitives->MacMcpsIndication( &MacCtx.McpsIndication );
- }
- }
- static void LoRaMacHandleMcpsRequest( void )
- {
- // Handle MCPS uplinks
- if( MacCtx.MacFlags.Bits.McpsReq == 1 )
- {
- bool stopRetransmission = false;
- bool waitForRetransmission = false;
- if( ( MacCtx.McpsConfirm.McpsRequest == MCPS_UNCONFIRMED ) ||
- ( MacCtx.McpsConfirm.McpsRequest == MCPS_PROPRIETARY ) )
- {
- stopRetransmission = CheckRetransUnconfirmedUplink( );
- }
- else if( MacCtx.McpsConfirm.McpsRequest == MCPS_CONFIRMED )
- {
- if( MacCtx.AckTimeoutRetry == true )
- {
- stopRetransmission = CheckRetransConfirmedUplink( );
- if( MacCtx.NvmCtx->Version.Fields.Minor == 0 )
- {
- if( stopRetransmission == false )
- {
- AckTimeoutRetriesProcess( );
- }
- else
- {
- AckTimeoutRetriesFinalize( );
- }
- }
- }
- else
- {
- waitForRetransmission = true;
- }
- }
- if( stopRetransmission == true )
- {// Stop retransmission
- TimerStop( &MacCtx.TxDelayedTimer );
- MacCtx.MacState &= ~LORAMAC_TX_DELAYED;
- StopRetransmission( );
- }
- else if( waitForRetransmission == false )
- {// Arrange further retransmission
- MacCtx.MacFlags.Bits.MacDone = 0;
- // Reset the state of the AckTimeout
- MacCtx.AckTimeoutRetry = false;
- // Sends the same frame again
- OnTxDelayedTimerEvent( );
- }
- }
- }
- static void LoRaMacHandleMlmeRequest( void )
- {
- // Handle join request
- if( MacCtx.MacFlags.Bits.MlmeReq == 1 )
- {
- if( ( LoRaMacConfirmQueueIsCmdActive( MLME_JOIN ) == true ) )
- {
- if( LoRaMacConfirmQueueGetStatus( MLME_JOIN ) == LORAMAC_EVENT_INFO_STATUS_OK )
- {// Node joined successfully
- MacCtx.ChannelsNbTransCounter = 0;
- }
- MacCtx.MacState &= ~LORAMAC_TX_RUNNING;
- }
- else if( ( LoRaMacConfirmQueueIsCmdActive( MLME_TXCW ) == true ) ||
- ( LoRaMacConfirmQueueIsCmdActive( MLME_TXCW_1 ) == true ) )
- {
- MacCtx.MacState &= ~LORAMAC_TX_RUNNING;
- }
- }
- }
- static uint8_t LoRaMacCheckForBeaconAcquisition( void )
- {
- if( ( LoRaMacConfirmQueueIsCmdActive( MLME_BEACON_ACQUISITION ) == true ) &&
- ( MacCtx.MacFlags.Bits.McpsReq == 0 ) )
- {
- if( MacCtx.MacFlags.Bits.MlmeReq == 1 )
- {
- MacCtx.MacState &= ~LORAMAC_TX_RUNNING;
- return 0x01;
- }
- }
- return 0x00;
- }
- static void LoRaMacCheckForRxAbort( void )
- {
- // A error occurs during receiving
- if( ( MacCtx.MacState & LORAMAC_RX_ABORT ) == LORAMAC_RX_ABORT )
- {
- MacCtx.MacState &= ~LORAMAC_RX_ABORT;
- MacCtx.MacState &= ~LORAMAC_TX_RUNNING;
- }
- }
- void LoRaMacProcess( void )
- {
- uint8_t noTx = false;
- LoRaMacHandleIrqEvents( );
- LoRaMacClassBProcess( );
- // MAC proceeded a state and is ready to check
- if( MacCtx.MacFlags.Bits.MacDone == 1 )
- {
- LoRaMacEnableRequests( LORAMAC_REQUEST_HANDLING_OFF );
- LoRaMacCheckForRxAbort( );
- // An error occurs during transmitting
- if( IsRequestPending( ) > 0 )
- {
- noTx |= LoRaMacCheckForBeaconAcquisition( );
- }
- if( noTx == 0x00 )
- {
- LoRaMacHandleMlmeRequest( );
- LoRaMacHandleMcpsRequest( );
- }
- LoRaMacHandleRequestEvents( );
- LoRaMacHandleScheduleUplinkEvent( );
- LoRaMacEnableRequests( LORAMAC_REQUEST_HANDLING_ON );
- }
- LoRaMacHandleIndicationEvents( );
- if( MacCtx.RxSlot == RX_SLOT_WIN_CLASS_C )
- {
- OpenContinuousRxCWindow( );
- }
- }
- static void OnTxDelayedTimerEvent( void )
- {
- TimerStop( &MacCtx.TxDelayedTimer );
- MacCtx.MacState &= ~LORAMAC_TX_DELAYED;
- // Schedule frame, allow delayed frame transmissions
- switch( ScheduleTx( true ) )
- {
- case LORAMAC_STATUS_OK:
- case LORAMAC_STATUS_DUTYCYCLE_RESTRICTED:
- {
- break;
- }
- default:
- {
- // Stop retransmission attempt
- MacCtx.McpsConfirm.Datarate = MacCtx.NvmCtx->MacParams.ChannelsDatarate;
- MacCtx.McpsConfirm.NbRetries = MacCtx.AckTimeoutRetriesCounter;
- MacCtx.McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_TX_DR_PAYLOAD_SIZE_ERROR;
- LoRaMacConfirmQueueSetStatusCmn( LORAMAC_EVENT_INFO_STATUS_TX_DR_PAYLOAD_SIZE_ERROR );
- StopRetransmission( );
- break;
- }
- }
- }
- static void OnRxWindow1TimerEvent( void )
- {
- MacCtx.RxWindow1Config.Channel = MacCtx.Channel;
- MacCtx.RxWindow1Config.DrOffset = MacCtx.NvmCtx->MacParams.Rx1DrOffset;
- MacCtx.RxWindow1Config.DownlinkDwellTime = MacCtx.NvmCtx->MacParams.DownlinkDwellTime;
- MacCtx.RxWindow1Config.RepeaterSupport = MacCtx.NvmCtx->RepeaterSupport;
- MacCtx.RxWindow1Config.RxContinuous = false;
- MacCtx.RxWindow1Config.RxSlot = RX_SLOT_WIN_1;
- RxWindowSetup( &MacCtx.RxWindowTimer1, &MacCtx.RxWindow1Config );
- }
- static void OnRxWindow2TimerEvent( void )
- {
- // Check if we are processing Rx1 window.
- // If yes, we don't setup the Rx2 window.
- if( MacCtx.RxSlot == RX_SLOT_WIN_1 )
- {
- return;
- }
- MacCtx.RxWindow2Config.Channel = MacCtx.Channel;
- MacCtx.RxWindow2Config.Frequency = MacCtx.NvmCtx->MacParams.Rx2Channel.Frequency;
- MacCtx.RxWindow2Config.DownlinkDwellTime = MacCtx.NvmCtx->MacParams.DownlinkDwellTime;
- MacCtx.RxWindow2Config.RepeaterSupport = MacCtx.NvmCtx->RepeaterSupport;
- MacCtx.RxWindow2Config.RxContinuous = false;
- MacCtx.RxWindow2Config.RxSlot = RX_SLOT_WIN_2;
- RxWindowSetup( &MacCtx.RxWindowTimer2, &MacCtx.RxWindow2Config );
- }
- static void OnAckTimeoutTimerEvent( void )
- {
- TimerStop( &MacCtx.AckTimeoutTimer );
- if( MacCtx.NodeAckRequested == true )
- {
- MacCtx.AckTimeoutRetry = true;
- }
- if( MacCtx.NvmCtx->DeviceClass == CLASS_C )
- {
- MacCtx.MacFlags.Bits.MacDone = 1;
- }
- if( ( MacCtx.MacCallbacks != NULL ) && ( MacCtx.MacCallbacks->MacProcessNotify != NULL ) )
- {
- MacCtx.MacCallbacks->MacProcessNotify( );
- }
- }
- static LoRaMacCryptoStatus_t GetFCntDown( AddressIdentifier_t addrID, FType_t fType, LoRaMacMessageData_t* macMsg, Version_t lrWanVersion,
- uint16_t maxFCntGap, FCntIdentifier_t* fCntID, uint32_t* currentDown )
- {
- if( ( macMsg == NULL ) || ( fCntID == NULL ) ||
- ( currentDown == NULL ) )
- {
- return LORAMAC_CRYPTO_ERROR_NPE;
- }
- // Determine the frame counter identifier and choose counter from FCntList
- switch( addrID )
- {
- case UNICAST_DEV_ADDR:
- if( lrWanVersion.Fields.Minor == 1 )
- {
- if( ( fType == FRAME_TYPE_A ) || ( fType == FRAME_TYPE_D ) )
- {
- *fCntID = A_FCNT_DOWN;
- }
- else
- {
- *fCntID = N_FCNT_DOWN;
- }
- }
- else
- { // For LoRaWAN 1.0.X
- *fCntID = FCNT_DOWN;
- }
- break;
- case MULTICAST_0_ADDR:
- *fCntID = MC_FCNT_DOWN_0;
- break;
- case MULTICAST_1_ADDR:
- *fCntID = MC_FCNT_DOWN_1;
- break;
- case MULTICAST_2_ADDR:
- *fCntID = MC_FCNT_DOWN_2;
- break;
- case MULTICAST_3_ADDR:
- *fCntID = MC_FCNT_DOWN_3;
- break;
- default:
- return LORAMAC_CRYPTO_FAIL_FCNT_ID;
- }
- return LoRaMacCryptoGetFCntDown( *fCntID, maxFCntGap, macMsg->FHDR.FCnt, currentDown );
- }
- static LoRaMacStatus_t SwitchClass( DeviceClass_t deviceClass )
- {
- LoRaMacStatus_t status = LORAMAC_STATUS_PARAMETER_INVALID;
- switch( MacCtx.NvmCtx->DeviceClass )
- {
- case CLASS_A:
- {
- if( deviceClass == CLASS_A )
- {
- // Revert back RxC parameters
- MacCtx.NvmCtx->MacParams.RxCChannel = MacCtx.NvmCtx->MacParams.Rx2Channel;
- }
- if( deviceClass == CLASS_B )
- {
- status = LoRaMacClassBSwitchClass( deviceClass );
- if( status == LORAMAC_STATUS_OK )
- {
- MacCtx.NvmCtx->DeviceClass = deviceClass;
- }
- }
- if( deviceClass == CLASS_C )
- {
- MacCtx.NvmCtx->DeviceClass = deviceClass;
- MacCtx.RxWindowCConfig = MacCtx.RxWindow2Config;
- MacCtx.RxWindowCConfig.RxSlot = RX_SLOT_WIN_CLASS_C;
- for( int8_t i = 0; i < LORAMAC_MAX_MC_CTX; i++ )
- {
- if( MacCtx.NvmCtx->MulticastChannelList[i].ChannelParams.IsEnabled == true )
- // TODO: Check multicast channel device class.
- {
- MacCtx.NvmCtx->MacParams.RxCChannel.Frequency = MacCtx.NvmCtx->MulticastChannelList[i].ChannelParams.RxParams.ClassC.Frequency;
- MacCtx.NvmCtx->MacParams.RxCChannel.Datarate = MacCtx.NvmCtx->MulticastChannelList[i].ChannelParams.RxParams.ClassC.Datarate;
- MacCtx.RxWindowCConfig.Channel = MacCtx.Channel;
- MacCtx.RxWindowCConfig.Frequency = MacCtx.NvmCtx->MacParams.RxCChannel.Frequency;
- MacCtx.RxWindowCConfig.DownlinkDwellTime = MacCtx.NvmCtx->MacParams.DownlinkDwellTime;
- MacCtx.RxWindowCConfig.RepeaterSupport = MacCtx.NvmCtx->RepeaterSupport;
- MacCtx.RxWindowCConfig.RxSlot = RX_SLOT_WIN_CLASS_C_MULTICAST;
- MacCtx.RxWindowCConfig.RxContinuous = true;
- break;
- }
- }
- // Set the NodeAckRequested indicator to default
- MacCtx.NodeAckRequested = false;
- // Set the radio into sleep mode in case we are still in RX mode
- Radio.Sleep( );
- OpenContinuousRxCWindow( );
- status = LORAMAC_STATUS_OK;
- }
- break;
- }
- case CLASS_B:
- {
- status = LoRaMacClassBSwitchClass( deviceClass );
- if( status == LORAMAC_STATUS_OK )
- {
- MacCtx.NvmCtx->DeviceClass = deviceClass;
- }
- break;
- }
- case CLASS_C:
- {
- if( deviceClass == CLASS_A )
- {
- MacCtx.NvmCtx->DeviceClass = deviceClass;
- // Set the radio into sleep to setup a defined state
- Radio.Sleep( );
- status = LORAMAC_STATUS_OK;
- }
- break;
- }
- }
- return status;
- }
- static uint8_t GetMaxAppPayloadWithoutFOptsLength( int8_t datarate )
- {
- GetPhyParams_t getPhy;
- PhyParam_t phyParam;
- // Setup PHY request
- getPhy.UplinkDwellTime = MacCtx.NvmCtx->MacParams.UplinkDwellTime;
- getPhy.Datarate = datarate;
- getPhy.Attribute = PHY_MAX_PAYLOAD;
- // Get the maximum payload length
- if( MacCtx.NvmCtx->RepeaterSupport == true )
- {
- getPhy.Attribute = PHY_MAX_PAYLOAD_REPEATER;
- }
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- return phyParam.Value;
- }
- static bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen )
- {
- uint16_t maxN = 0;
- uint16_t payloadSize = 0;
- maxN = GetMaxAppPayloadWithoutFOptsLength( datarate );
- // Calculate the resulting payload size
- payloadSize = ( lenN + fOptsLen );
- // Validation of the application payload size
- if( ( payloadSize <= maxN ) && ( payloadSize <= LORAMAC_PHY_MAXPAYLOAD ) )
- {
- return true;
- }
- return false;
- }
- static void SetMlmeScheduleUplinkIndication( void )
- {
- MacCtx.MacFlags.Bits.MlmeSchedUplinkInd = 1;
- }
- static void ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, int8_t snr, LoRaMacRxSlot_t rxSlot )
- {
- uint8_t status = 0;
- bool adrBlockFound = false;
- uint8_t macCmdPayload[2] = { 0x00, 0x00 };
- while( macIndex < commandsSize )
- {
- // Decode Frame MAC commands
- switch( payload[macIndex++] )
- {
- case SRV_MAC_LINK_CHECK_ANS:
- {
- if( LoRaMacConfirmQueueIsCmdActive( MLME_LINK_CHECK ) == true )
- {
- LoRaMacConfirmQueueSetStatus( LORAMAC_EVENT_INFO_STATUS_OK, MLME_LINK_CHECK );
- MacCtx.MlmeConfirm.DemodMargin = payload[macIndex++];
- MacCtx.MlmeConfirm.NbGateways = payload[macIndex++];
- }
- break;
- }
- case SRV_MAC_LINK_ADR_REQ:
- {
- LinkAdrReqParams_t linkAdrReq;
- int8_t linkAdrDatarate = DR_0;
- int8_t linkAdrTxPower = TX_POWER_0;
- uint8_t linkAdrNbRep = 0;
- uint8_t linkAdrNbBytesParsed = 0;
- if( adrBlockFound == false )
- {
- adrBlockFound = true;
- // Fill parameter structure
- linkAdrReq.Payload = &payload[macIndex - 1];
- linkAdrReq.PayloadSize = commandsSize - ( macIndex - 1 );
- linkAdrReq.AdrEnabled = MacCtx.NvmCtx->AdrCtrlOn;
- linkAdrReq.UplinkDwellTime = MacCtx.NvmCtx->MacParams.UplinkDwellTime;
- linkAdrReq.CurrentDatarate = MacCtx.NvmCtx->MacParams.ChannelsDatarate;
- linkAdrReq.CurrentTxPower = MacCtx.NvmCtx->MacParams.ChannelsTxPower;
- linkAdrReq.CurrentNbRep = MacCtx.NvmCtx->MacParams.ChannelsNbTrans;
- linkAdrReq.Version = MacCtx.NvmCtx->Version;
- // Process the ADR requests
- status = RegionLinkAdrReq( MacCtx.NvmCtx->Region, &linkAdrReq, &linkAdrDatarate,
- &linkAdrTxPower, &linkAdrNbRep, &linkAdrNbBytesParsed );
- if( ( status & 0x07 ) == 0x07 )
- {
- MacCtx.NvmCtx->MacParams.ChannelsDatarate = linkAdrDatarate;
- MacCtx.NvmCtx->MacParams.ChannelsTxPower = linkAdrTxPower;
- MacCtx.NvmCtx->MacParams.ChannelsNbTrans = linkAdrNbRep;
- }
- // Add the answers to the buffer
- for( uint8_t i = 0; i < ( linkAdrNbBytesParsed / 5 ); i++ )
- {
- LoRaMacCommandsAddCmd( MOTE_MAC_LINK_ADR_ANS, &status, 1 );
- }
- // Update MAC index
- macIndex += linkAdrNbBytesParsed - 1;
- }
- break;
- }
- case SRV_MAC_DUTY_CYCLE_REQ:
- {
- MacCtx.NvmCtx->MaxDCycle = payload[macIndex++] & 0x0F;
- MacCtx.NvmCtx->AggregatedDCycle = 1 << MacCtx.NvmCtx->MaxDCycle;
- LoRaMacCommandsAddCmd( MOTE_MAC_DUTY_CYCLE_ANS, macCmdPayload, 0 );
- break;
- }
- case SRV_MAC_RX_PARAM_SETUP_REQ:
- {
- RxParamSetupReqParams_t rxParamSetupReq;
- status = 0x07;
- rxParamSetupReq.DrOffset = ( payload[macIndex] >> 4 ) & 0x07;
- rxParamSetupReq.Datarate = payload[macIndex] & 0x0F;
- macIndex++;
- rxParamSetupReq.Frequency = ( uint32_t ) payload[macIndex++];
- rxParamSetupReq.Frequency |= ( uint32_t ) payload[macIndex++] << 8;
- rxParamSetupReq.Frequency |= ( uint32_t ) payload[macIndex++] << 16;
- rxParamSetupReq.Frequency *= 100;
- // Perform request on region
- status = RegionRxParamSetupReq( MacCtx.NvmCtx->Region, &rxParamSetupReq );
- if( ( status & 0x07 ) == 0x07 )
- {
- MacCtx.NvmCtx->MacParams.Rx2Channel.Datarate = rxParamSetupReq.Datarate;
- MacCtx.NvmCtx->MacParams.RxCChannel.Datarate = rxParamSetupReq.Datarate;
- MacCtx.NvmCtx->MacParams.Rx2Channel.Frequency = rxParamSetupReq.Frequency;
- MacCtx.NvmCtx->MacParams.RxCChannel.Frequency = rxParamSetupReq.Frequency;
- MacCtx.NvmCtx->MacParams.Rx1DrOffset = rxParamSetupReq.DrOffset;
- }
- macCmdPayload[0] = status;
- LoRaMacCommandsAddCmd( MOTE_MAC_RX_PARAM_SETUP_ANS, macCmdPayload, 1 );
- // Setup indication to inform the application
- SetMlmeScheduleUplinkIndication( );
- break;
- }
- case SRV_MAC_DEV_STATUS_REQ:
- {
- uint8_t batteryLevel = BAT_LEVEL_NO_MEASURE;
- if( ( MacCtx.MacCallbacks != NULL ) && ( MacCtx.MacCallbacks->GetBatteryLevel != NULL ) )
- {
- batteryLevel = MacCtx.MacCallbacks->GetBatteryLevel( );
- }
- macCmdPayload[0] = batteryLevel;
- macCmdPayload[1] = ( uint8_t )( snr & 0x3F );
- LoRaMacCommandsAddCmd( MOTE_MAC_DEV_STATUS_ANS, macCmdPayload, 2 );
- break;
- }
- case SRV_MAC_NEW_CHANNEL_REQ:
- {
- NewChannelReqParams_t newChannelReq;
- ChannelParams_t chParam;
- status = 0x03;
- newChannelReq.ChannelId = payload[macIndex++];
- newChannelReq.NewChannel = &chParam;
- chParam.Frequency = ( uint32_t ) payload[macIndex++];
- chParam.Frequency |= ( uint32_t ) payload[macIndex++] << 8;
- chParam.Frequency |= ( uint32_t ) payload[macIndex++] << 16;
- chParam.Frequency *= 100;
- chParam.Rx1Frequency = 0;
- chParam.DrRange.Value = payload[macIndex++];
- status = RegionNewChannelReq( MacCtx.NvmCtx->Region, &newChannelReq );
- macCmdPayload[0] = status;
- LoRaMacCommandsAddCmd( MOTE_MAC_NEW_CHANNEL_ANS, macCmdPayload, 1 );
- break;
- }
- case SRV_MAC_RX_TIMING_SETUP_REQ:
- {
- uint8_t delay = payload[macIndex++] & 0x0F;
- if( delay == 0 )
- {
- delay++;
- }
- MacCtx.NvmCtx->MacParams.ReceiveDelay1 = delay * 1000;
- MacCtx.NvmCtx->MacParams.ReceiveDelay2 = MacCtx.NvmCtx->MacParams.ReceiveDelay1 + 1000;
- LoRaMacCommandsAddCmd( MOTE_MAC_RX_TIMING_SETUP_ANS, macCmdPayload, 0 );
- // Setup indication to inform the application
- SetMlmeScheduleUplinkIndication( );
- break;
- }
- case SRV_MAC_TX_PARAM_SETUP_REQ:
- {
- TxParamSetupReqParams_t txParamSetupReq;
- GetPhyParams_t getPhy;
- PhyParam_t phyParam;
- uint8_t eirpDwellTime = payload[macIndex++];
- txParamSetupReq.UplinkDwellTime = 0;
- txParamSetupReq.DownlinkDwellTime = 0;
- if( ( eirpDwellTime & 0x20 ) == 0x20 )
- {
- txParamSetupReq.DownlinkDwellTime = 1;
- }
- if( ( eirpDwellTime & 0x10 ) == 0x10 )
- {
- txParamSetupReq.UplinkDwellTime = 1;
- }
- txParamSetupReq.MaxEirp = eirpDwellTime & 0x0F;
- // Check the status for correctness
- if( RegionTxParamSetupReq( MacCtx.NvmCtx->Region, &txParamSetupReq ) != -1 )
- {
- // Accept command
- MacCtx.NvmCtx->MacParams.UplinkDwellTime = txParamSetupReq.UplinkDwellTime;
- MacCtx.NvmCtx->MacParams.DownlinkDwellTime = txParamSetupReq.DownlinkDwellTime;
- MacCtx.NvmCtx->MacParams.MaxEirp = LoRaMacMaxEirpTable[txParamSetupReq.MaxEirp];
- // Update the datarate in case of the new configuration limits it
- getPhy.Attribute = PHY_MIN_TX_DR;
- getPhy.UplinkDwellTime = MacCtx.NvmCtx->MacParams.UplinkDwellTime;
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- MacCtx.NvmCtx->MacParams.ChannelsDatarate = MAX( MacCtx.NvmCtx->MacParams.ChannelsDatarate, ( int8_t )phyParam.Value );
- // Add command response
- LoRaMacCommandsAddCmd( MOTE_MAC_TX_PARAM_SETUP_ANS, macCmdPayload, 0 );
- }
- break;
- }
- case SRV_MAC_DL_CHANNEL_REQ:
- {
- DlChannelReqParams_t dlChannelReq;
- status = 0x03;
- dlChannelReq.ChannelId = payload[macIndex++];
- dlChannelReq.Rx1Frequency = ( uint32_t ) payload[macIndex++];
- dlChannelReq.Rx1Frequency |= ( uint32_t ) payload[macIndex++] << 8;
- dlChannelReq.Rx1Frequency |= ( uint32_t ) payload[macIndex++] << 16;
- dlChannelReq.Rx1Frequency *= 100;
- status = RegionDlChannelReq( MacCtx.NvmCtx->Region, &dlChannelReq );
- macCmdPayload[0] = status;
- LoRaMacCommandsAddCmd( MOTE_MAC_DL_CHANNEL_ANS, macCmdPayload, 1 );
- // Setup indication to inform the application
- SetMlmeScheduleUplinkIndication( );
- break;
- }
- case SRV_MAC_DEVICE_TIME_ANS:
- {
- SysTime_t gpsEpochTime = { 0 };
- SysTime_t sysTime = { 0 };
- //SysTime_t sysTimeCurrent = { 0 };
- gpsEpochTime.Seconds = ( uint32_t )payload[macIndex++];
- gpsEpochTime.Seconds |= ( uint32_t )payload[macIndex++] << 8;
- gpsEpochTime.Seconds |= ( uint32_t )payload[macIndex++] << 16;
- gpsEpochTime.Seconds |= ( uint32_t )payload[macIndex++] << 24;
- gpsEpochTime.SubSeconds = payload[macIndex++];
- // Convert the fractional second received in ms
- // round( pow( 0.5, 8.0 ) * 1000 ) = 3.90625
- gpsEpochTime.SubSeconds = ( int16_t )( ( ( int32_t )gpsEpochTime.SubSeconds * 1000 ) >> 8 );
- // Copy received GPS Epoch time into system time
- sysTime = gpsEpochTime;
- // Add Unix to Gps epcoh offset. The system time is based on Unix time.
- sysTime.Seconds += UNIX_GPS_EPOCH_OFFSET;
- // Compensate time difference between Tx Done time and now
- //sysTimeCurrent = SysTimeGet( );
- //sysTime = SysTimeAdd( sysTimeCurrent, SysTimeSub( sysTime, MacCtx.LastTxSysTime ) );
- // Apply the new system time.
- // SysTimeSet( sysTime );
- LoRaMacClassBDeviceTimeAns( );
- MacCtx.McpsIndication.DeviceTimeAnsReceived = true;
- break;
- }
- case SRV_MAC_PING_SLOT_INFO_ANS:
- {
- // According to the specification, it is not allowed to process this answer in
- // a ping or multicast slot
- if( ( MacCtx.RxSlot != RX_SLOT_WIN_CLASS_B_PING_SLOT ) && ( MacCtx.RxSlot != RX_SLOT_WIN_CLASS_B_MULTICAST_SLOT ) )
- {
- LoRaMacClassBPingSlotInfoAns( );
- }
- break;
- }
- case SRV_MAC_PING_SLOT_CHANNEL_REQ:
- {
- uint8_t status = 0x03;
- uint32_t frequency = 0;
- uint8_t datarate;
- frequency = ( uint32_t )payload[macIndex++];
- frequency |= ( uint32_t )payload[macIndex++] << 8;
- frequency |= ( uint32_t )payload[macIndex++] << 16;
- frequency *= 100;
- datarate = payload[macIndex++] & 0x0F;
- status = LoRaMacClassBPingSlotChannelReq( datarate, frequency );
- macCmdPayload[0] = status;
- LoRaMacCommandsAddCmd( MOTE_MAC_PING_SLOT_FREQ_ANS, macCmdPayload, 1 );
- break;
- }
- case SRV_MAC_BEACON_TIMING_ANS:
- {
- uint16_t beaconTimingDelay = 0;
- uint8_t beaconTimingChannel = 0;
- beaconTimingDelay = ( uint16_t )payload[macIndex++];
- beaconTimingDelay |= ( uint16_t )payload[macIndex++] << 8;
- beaconTimingChannel = payload[macIndex++];
- LoRaMacClassBBeaconTimingAns( beaconTimingDelay, beaconTimingChannel, RxDoneParams.LastRxDone );
- break;
- }
- case SRV_MAC_BEACON_FREQ_REQ:
- {
- uint32_t frequency = 0;
- frequency = ( uint32_t )payload[macIndex++];
- frequency |= ( uint32_t )payload[macIndex++] << 8;
- frequency |= ( uint32_t )payload[macIndex++] << 16;
- frequency *= 100;
- if( LoRaMacClassBBeaconFreqReq( frequency ) == true )
- {
- macCmdPayload[0] = 1;
- }
- else
- {
- macCmdPayload[0] = 0;
- }
- LoRaMacCommandsAddCmd( MOTE_MAC_BEACON_FREQ_ANS, macCmdPayload, 1 );
- }
- break;
- default:
- // Unknown command. ABORT MAC commands processing
- return;
- }
- }
- }
- LoRaMacStatus_t Send( LoRaMacHeader_t* macHdr, uint8_t fPort, void* fBuffer, uint16_t fBufferSize )
- {
- LoRaMacFrameCtrl_t fCtrl;
- LoRaMacStatus_t status = LORAMAC_STATUS_PARAMETER_INVALID;
- int8_t datarate = MacCtx.NvmCtx->MacParams.ChannelsDatarate;
- int8_t txPower = MacCtx.NvmCtx->MacParams.ChannelsTxPower;
- uint32_t adrAckCounter = MacCtx.NvmCtx->AdrAckCounter;
- CalcNextAdrParams_t adrNext;
- // Check if we are joined
- if( MacCtx.NvmCtx->NetworkActivation == ACTIVATION_TYPE_NONE )
- {
- return LORAMAC_STATUS_NO_NETWORK_JOINED;
- }
- if( MacCtx.NvmCtx->MaxDCycle == 0 )
- {
- MacCtx.NvmCtx->AggregatedTimeOff = 0;
- }
- fCtrl.Value = 0;
- fCtrl.Bits.FOptsLen = 0;
- fCtrl.Bits.Adr = MacCtx.NvmCtx->AdrCtrlOn;
- // Check class b
- if( MacCtx.NvmCtx->DeviceClass == CLASS_B )
- {
- fCtrl.Bits.FPending = 1;
- }
- else
- {
- fCtrl.Bits.FPending = 0;
- }
- // Check server ack
- if( MacCtx.NvmCtx->SrvAckRequested == true )
- {
- fCtrl.Bits.Ack = 1;
- }
- // ADR next request
- adrNext.Version = MacCtx.NvmCtx->Version;
- adrNext.UpdateChanMask = true;
- adrNext.AdrEnabled = fCtrl.Bits.Adr;
- adrNext.AdrAckCounter = MacCtx.NvmCtx->AdrAckCounter;
- adrNext.AdrAckLimit = MacCtx.AdrAckLimit;
- adrNext.AdrAckDelay = MacCtx.AdrAckDelay;
- adrNext.Datarate = MacCtx.NvmCtx->MacParams.ChannelsDatarate;
- adrNext.TxPower = MacCtx.NvmCtx->MacParams.ChannelsTxPower;
- adrNext.UplinkDwellTime = MacCtx.NvmCtx->MacParams.UplinkDwellTime;
- adrNext.Region = MacCtx.NvmCtx->Region;
- fCtrl.Bits.AdrAckReq = LoRaMacAdrCalcNext( &adrNext, &MacCtx.NvmCtx->MacParams.ChannelsDatarate,
- &MacCtx.NvmCtx->MacParams.ChannelsTxPower, &adrAckCounter );
- // Prepare the frame
- status = PrepareFrame( macHdr, &fCtrl, fPort, fBuffer, fBufferSize );
- // Validate status
- if( ( status == LORAMAC_STATUS_OK ) || ( status == LORAMAC_STATUS_SKIPPED_APP_DATA ) )
- {
- // Schedule frame, do not allow delayed transmissions
- status = ScheduleTx( false );
- }
- // Post processing
- if( status != LORAMAC_STATUS_OK )
- {
- // Bad case - restore
- // Store local variables
- MacCtx.NvmCtx->MacParams.ChannelsDatarate = datarate;
- MacCtx.NvmCtx->MacParams.ChannelsTxPower = txPower;
- }
- else
- {
- // Good case
- MacCtx.NvmCtx->SrvAckRequested = false;
- MacCtx.NvmCtx->AdrAckCounter = adrAckCounter;
- // Remove all none sticky MAC commands
- if( LoRaMacCommandsRemoveNoneStickyCmds( ) != LORAMAC_COMMANDS_SUCCESS )
- {
- return LORAMAC_STATUS_MAC_COMMAD_ERROR;
- }
- }
- return status;
- }
- LoRaMacStatus_t SendReJoinReq( JoinReqIdentifier_t joinReqType )
- {
- LoRaMacStatus_t status = LORAMAC_STATUS_OK;
- LoRaMacHeader_t macHdr;
- macHdr.Value = 0;
- bool allowDelayedTx = true;
- // Setup join/rejoin message
- switch( joinReqType )
- {
- case JOIN_REQ:
- {
- SwitchClass( CLASS_A );
- MacCtx.TxMsg.Type = LORAMAC_MSG_TYPE_JOIN_REQUEST;
- MacCtx.TxMsg.Message.JoinReq.Buffer = MacCtx.PktBuffer;
- MacCtx.TxMsg.Message.JoinReq.BufSize = LORAMAC_PHY_MAXPAYLOAD;
- macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ;
- MacCtx.TxMsg.Message.JoinReq.MHDR.Value = macHdr.Value;
- memcpy1( MacCtx.TxMsg.Message.JoinReq.JoinEUI, SecureElementGetJoinEui( ), LORAMAC_JOIN_EUI_FIELD_SIZE );
- memcpy1( MacCtx.TxMsg.Message.JoinReq.DevEUI, SecureElementGetDevEui( ), LORAMAC_DEV_EUI_FIELD_SIZE );
- allowDelayedTx = false;
- break;
- }
- default:
- status = LORAMAC_STATUS_SERVICE_UNKNOWN;
- break;
- }
- // Schedule frame
- status = ScheduleTx( allowDelayedTx );
- return status;
- }
- static LoRaMacStatus_t CheckForClassBCollision( void )
- {
- if( LoRaMacClassBIsBeaconExpected( ) == true )
- {
- return LORAMAC_STATUS_BUSY_BEACON_RESERVED_TIME;
- }
- if( MacCtx.NvmCtx->DeviceClass == CLASS_B )
- {
- if( LoRaMacClassBIsPingExpected( ) == true )
- {
- return LORAMAC_STATUS_BUSY_PING_SLOT_WINDOW_TIME;
- }
- else if( LoRaMacClassBIsMulticastExpected( ) == true )
- {
- return LORAMAC_STATUS_BUSY_PING_SLOT_WINDOW_TIME;
- }
- }
- return LORAMAC_STATUS_OK;
- }
- static LoRaMacStatus_t ScheduleTx( bool allowDelayedTx )
- {
- LoRaMacStatus_t status = LORAMAC_STATUS_PARAMETER_INVALID;
- TimerTime_t dutyCycleTimeOff = 0;
- NextChanParams_t nextChan;
- size_t macCmdsSize = 0;
- // Check class b collisions
- status = CheckForClassBCollision( );
- if( status != LORAMAC_STATUS_OK )
- {
- return status;
- }
- // Update back-off
- CalculateBackOff( MacCtx.NvmCtx->LastTxChannel );
- nextChan.AggrTimeOff = MacCtx.NvmCtx->AggregatedTimeOff;
- nextChan.Datarate = MacCtx.NvmCtx->MacParams.ChannelsDatarate;
- nextChan.DutyCycleEnabled = MacCtx.NvmCtx->DutyCycleOn;
- if( MacCtx.NvmCtx->NetworkActivation == ACTIVATION_TYPE_NONE )
- {
- nextChan.Joined = false;
- }
- else
- {
- nextChan.Joined = true;
- }
- nextChan.LastAggrTx = MacCtx.NvmCtx->LastTxDoneTime;
- // Select channel
- status = RegionNextChannel( MacCtx.NvmCtx->Region, &nextChan, &MacCtx.Channel, &dutyCycleTimeOff, &MacCtx.NvmCtx->AggregatedTimeOff );
- if( status != LORAMAC_STATUS_OK )
- {
- if( ( status == LORAMAC_STATUS_DUTYCYCLE_RESTRICTED ) &&
- ( allowDelayedTx == true ) )
- {
- // Allow delayed transmissions. We have to allow it in case
- // the MAC must retransmit a frame with the frame repetitions
- if( dutyCycleTimeOff != 0 )
- {// Send later - prepare timer
- MacCtx.MacState |= LORAMAC_TX_DELAYED;
- TimerSetValue( &MacCtx.TxDelayedTimer, dutyCycleTimeOff );
- TimerStart( &MacCtx.TxDelayedTimer );
- }
- return LORAMAC_STATUS_OK;
- }
- else
- {// State where the MAC cannot send a frame
- return status;
- }
- }
- // Compute Rx1 windows parameters
- RegionComputeRxWindowParameters( MacCtx.NvmCtx->Region,
- RegionApplyDrOffset( MacCtx.NvmCtx->Region, MacCtx.NvmCtx->MacParams.DownlinkDwellTime, MacCtx.NvmCtx->MacParams.ChannelsDatarate, MacCtx.NvmCtx->MacParams.Rx1DrOffset ),
- MacCtx.NvmCtx->MacParams.MinRxSymbols,
- MacCtx.NvmCtx->MacParams.SystemMaxRxError,
- &MacCtx.RxWindow1Config );
- // Compute Rx2 windows parameters
- RegionComputeRxWindowParameters( MacCtx.NvmCtx->Region,
- MacCtx.NvmCtx->MacParams.Rx2Channel.Datarate,
- MacCtx.NvmCtx->MacParams.MinRxSymbols,
- MacCtx.NvmCtx->MacParams.SystemMaxRxError,
- &MacCtx.RxWindow2Config );
- if( MacCtx.NvmCtx->NetworkActivation == ACTIVATION_TYPE_NONE )
- {
- MacCtx.RxWindow1Delay = MacCtx.NvmCtx->MacParams.JoinAcceptDelay1 + MacCtx.RxWindow1Config.WindowOffset;
- MacCtx.RxWindow2Delay = MacCtx.NvmCtx->MacParams.JoinAcceptDelay2 + MacCtx.RxWindow2Config.WindowOffset;
- }
- else
- {
- if( LoRaMacCommandsGetSizeSerializedCmds( &macCmdsSize ) != LORAMAC_COMMANDS_SUCCESS )
- {
- return LORAMAC_STATUS_MAC_COMMAD_ERROR;
- }
- if( ValidatePayloadLength( MacCtx.AppDataSize, MacCtx.NvmCtx->MacParams.ChannelsDatarate, macCmdsSize ) == false )
- {
- return LORAMAC_STATUS_LENGTH_ERROR;
- }
- MacCtx.RxWindow1Delay = MacCtx.NvmCtx->MacParams.ReceiveDelay1 + MacCtx.RxWindow1Config.WindowOffset;
- MacCtx.RxWindow2Delay = MacCtx.NvmCtx->MacParams.ReceiveDelay2 + MacCtx.RxWindow2Config.WindowOffset;
- }
- // Secure frame
- LoRaMacStatus_t retval = SecureFrame( MacCtx.NvmCtx->MacParams.ChannelsDatarate, MacCtx.Channel );
- if( retval != LORAMAC_STATUS_OK )
- {
- return retval;
- }
- // Try to send now
- return SendFrameOnChannel( MacCtx.Channel );
- }
- static LoRaMacStatus_t SecureFrame( uint8_t txDr, uint8_t txCh )
- {
- LoRaMacCryptoStatus_t macCryptoStatus = LORAMAC_CRYPTO_ERROR;
- uint32_t fCntUp = 0;
- switch( MacCtx.TxMsg.Type )
- {
- case LORAMAC_MSG_TYPE_JOIN_REQUEST:
- macCryptoStatus = LoRaMacCryptoPrepareJoinRequest( &MacCtx.TxMsg.Message.JoinReq );
- if( LORAMAC_CRYPTO_SUCCESS != macCryptoStatus )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- MacCtx.PktBufferLen = MacCtx.TxMsg.Message.JoinReq.BufSize;
- break;
- case LORAMAC_MSG_TYPE_DATA:
- if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoGetFCntUp( &fCntUp ) )
- {
- return LORAMAC_STATUS_FCNT_HANDLER_ERROR;
- }
- if( ( MacCtx.ChannelsNbTransCounter >= 1 ) || ( MacCtx.AckTimeoutRetriesCounter > 1 ) )
- {
- fCntUp -= 1;
- }
- macCryptoStatus = LoRaMacCryptoSecureMessage( fCntUp, txDr, txCh, &MacCtx.TxMsg.Message.Data );
- if( LORAMAC_CRYPTO_SUCCESS != macCryptoStatus )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- MacCtx.PktBufferLen = MacCtx.TxMsg.Message.Data.BufSize;
- break;
- case LORAMAC_MSG_TYPE_JOIN_ACCEPT:
- case LORAMAC_MSG_TYPE_UNDEF:
- default:
- return LORAMAC_STATUS_PARAMETER_INVALID;
- }
- return LORAMAC_STATUS_OK;
- }
- static void CalculateBackOff( uint8_t channel )
- {
- CalcBackOffParams_t calcBackOff;
- if( MacCtx.NvmCtx->NetworkActivation == ACTIVATION_TYPE_NONE )
- {
- calcBackOff.Joined = false;
- }
- else
- {
- calcBackOff.Joined = true;
- }
- calcBackOff.DutyCycleEnabled = MacCtx.NvmCtx->DutyCycleOn;
- calcBackOff.Channel = channel;
- //calcBackOff.ElapsedTime = SysTimeSub( SysTimeGetMcuTime( ), MacCtx.NvmCtx->InitializationTime );
- calcBackOff.TxTimeOnAir = MacCtx.TxTimeOnAir;
- calcBackOff.LastTxIsJoinRequest = false;
- if( ( MacCtx.MacFlags.Bits.MlmeReq == 1 ) && ( LoRaMacConfirmQueueIsCmdActive( MLME_JOIN ) == true ) )
- {
- calcBackOff.LastTxIsJoinRequest = true;
- }
- // Update regional back-off
- RegionCalcBackOff( MacCtx.NvmCtx->Region, &calcBackOff );
- // Update aggregated time-off. This must be an assignment and no incremental
- // update as we do only calculate the time-off based on the last transmission
- MacCtx.NvmCtx->AggregatedTimeOff = ( MacCtx.TxTimeOnAir * MacCtx.NvmCtx->AggregatedDCycle - MacCtx.TxTimeOnAir );
- }
- static void RemoveMacCommands( LoRaMacRxSlot_t rxSlot, LoRaMacFrameCtrl_t fCtrl, Mcps_t request )
- {
- if( rxSlot == RX_SLOT_WIN_1 || rxSlot == RX_SLOT_WIN_2 )
- {
- // Remove all sticky MAC commands answers since we can assume
- // that they have been received by the server.
- if( request == MCPS_CONFIRMED )
- {
- if( fCtrl.Bits.Ack == 1 )
- { // For confirmed uplinks only if we have received an ACK.
- LoRaMacCommandsRemoveStickyAnsCmds( );
- }
- }
- else
- {
- LoRaMacCommandsRemoveStickyAnsCmds( );
- }
- }
- }
- static void ResetMacParameters( void )
- {
- MacCtx.NvmCtx->NetworkActivation = ACTIVATION_TYPE_NONE;
- // ADR counter
- MacCtx.NvmCtx->AdrAckCounter = 0;
- MacCtx.ChannelsNbTransCounter = 0;
- MacCtx.AckTimeoutRetries = 1;
- MacCtx.AckTimeoutRetriesCounter = 1;
- MacCtx.AckTimeoutRetry = false;
- MacCtx.NvmCtx->MaxDCycle = 0;
- MacCtx.NvmCtx->AggregatedDCycle = 1;
- MacCtx.NvmCtx->MacParams.ChannelsTxPower = MacCtx.NvmCtx->MacParamsDefaults.ChannelsTxPower;
- MacCtx.NvmCtx->MacParams.ChannelsDatarate = MacCtx.NvmCtx->MacParamsDefaults.ChannelsDatarate;
- MacCtx.NvmCtx->MacParams.Rx1DrOffset = MacCtx.NvmCtx->MacParamsDefaults.Rx1DrOffset;
- MacCtx.NvmCtx->MacParams.Rx2Channel = MacCtx.NvmCtx->MacParamsDefaults.Rx2Channel;
- MacCtx.NvmCtx->MacParams.RxCChannel = MacCtx.NvmCtx->MacParamsDefaults.RxCChannel;
- MacCtx.NvmCtx->MacParams.UplinkDwellTime = MacCtx.NvmCtx->MacParamsDefaults.UplinkDwellTime;
- MacCtx.NvmCtx->MacParams.DownlinkDwellTime = MacCtx.NvmCtx->MacParamsDefaults.DownlinkDwellTime;
- MacCtx.NvmCtx->MacParams.MaxEirp = MacCtx.NvmCtx->MacParamsDefaults.MaxEirp;
- MacCtx.NvmCtx->MacParams.AntennaGain = MacCtx.NvmCtx->MacParamsDefaults.AntennaGain;
- MacCtx.NodeAckRequested = false;
- MacCtx.NvmCtx->SrvAckRequested = false;
- // Reset to application defaults
- InitDefaultsParams_t params;
- params.Type = INIT_TYPE_RESTORE_DEFAULT_CHANNELS;
- params.NvmCtx = NULL;
- RegionInitDefaults( MacCtx.NvmCtx->Region, ¶ms );
- // Initialize channel index.
- MacCtx.Channel = 0;
- MacCtx.NvmCtx->LastTxChannel = MacCtx.Channel;
- // Initialize Rx2 config parameters.
- MacCtx.RxWindow2Config.Channel = MacCtx.Channel;
- MacCtx.RxWindow2Config.Frequency = MacCtx.NvmCtx->MacParams.Rx2Channel.Frequency;
- MacCtx.RxWindow2Config.DownlinkDwellTime = MacCtx.NvmCtx->MacParams.DownlinkDwellTime;
- MacCtx.RxWindow2Config.RepeaterSupport = MacCtx.NvmCtx->RepeaterSupport;
- MacCtx.RxWindow2Config.RxContinuous = false;
- MacCtx.RxWindow2Config.RxSlot = RX_SLOT_WIN_2;
- // Initialize RxC config parameters.
- MacCtx.RxWindowCConfig = MacCtx.RxWindow2Config;
- MacCtx.RxWindowCConfig.RxContinuous = true;
- MacCtx.RxWindowCConfig.RxSlot = RX_SLOT_WIN_CLASS_C;
- }
- /*!
- * \brief Initializes and opens the reception window
- *
- * \param [IN] rxTimer Window timer to be topped.
- * \param [IN] rxConfig Window parameters to be setup
- */
- static void RxWindowSetup( TimerEvent_t* rxTimer, RxConfigParams_t* rxConfig )
- {
- TimerStop( rxTimer );
- // Ensure the radio is Idle
- Radio.Standby( );
- if( RegionRxConfig( MacCtx.NvmCtx->Region, rxConfig, ( int8_t* )&MacCtx.McpsIndication.RxDatarate ) == true )
- {
- Radio.Rx( MacCtx.NvmCtx->MacParams.MaxRxWindow );
- MacCtx.RxSlot = rxConfig->RxSlot;
- }
- }
- static void OpenContinuousRxCWindow( void )
- {
- // Compute RxC windows parameters
- RegionComputeRxWindowParameters( MacCtx.NvmCtx->Region,
- MacCtx.NvmCtx->MacParams.RxCChannel.Datarate,
- MacCtx.NvmCtx->MacParams.MinRxSymbols,
- MacCtx.NvmCtx->MacParams.SystemMaxRxError,
- &MacCtx.RxWindowCConfig );
- MacCtx.RxWindowCConfig.RxSlot = RX_SLOT_WIN_CLASS_C;
- // Setup continuous listening
- MacCtx.RxWindowCConfig.RxContinuous = true;
- // At this point the Radio should be idle.
- // Thus, there is no need to set the radio in standby mode.
- if( RegionRxConfig( MacCtx.NvmCtx->Region, &MacCtx.RxWindowCConfig, ( int8_t* )&MacCtx.McpsIndication.RxDatarate ) == true )
- {
- Radio.Rx( 0 ); // Continuous mode
- MacCtx.RxSlot = MacCtx.RxWindowCConfig.RxSlot;
- }
- }
- LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t* macHdr, LoRaMacFrameCtrl_t* fCtrl, uint8_t fPort, void* fBuffer, uint16_t fBufferSize )
- {
- MacCtx.PktBufferLen = 0;
- MacCtx.NodeAckRequested = false;
- uint32_t fCntUp = 0;
- size_t macCmdsSize = 0;
- uint8_t availableSize = 0;
- if( fBuffer == NULL )
- {
- fBufferSize = 0;
- }
- memcpy1( MacCtx.AppData, ( uint8_t* ) fBuffer, fBufferSize );
- MacCtx.AppDataSize = fBufferSize;
- MacCtx.PktBuffer[0] = macHdr->Value;
- switch( macHdr->Bits.MType )
- {
- case FRAME_TYPE_DATA_CONFIRMED_UP:
- MacCtx.NodeAckRequested = true;
- // Intentional fall through
- case FRAME_TYPE_DATA_UNCONFIRMED_UP:
- MacCtx.TxMsg.Type = LORAMAC_MSG_TYPE_DATA;
- MacCtx.TxMsg.Message.Data.Buffer = MacCtx.PktBuffer;
- MacCtx.TxMsg.Message.Data.BufSize = LORAMAC_PHY_MAXPAYLOAD;
- MacCtx.TxMsg.Message.Data.MHDR.Value = macHdr->Value;
- MacCtx.TxMsg.Message.Data.FPort = fPort;
- MacCtx.TxMsg.Message.Data.FHDR.DevAddr = MacCtx.NvmCtx->DevAddr;
- MacCtx.TxMsg.Message.Data.FHDR.FCtrl.Value = fCtrl->Value;
- MacCtx.TxMsg.Message.Data.FRMPayloadSize = MacCtx.AppDataSize;
- MacCtx.TxMsg.Message.Data.FRMPayload = MacCtx.AppData;
- if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoGetFCntUp( &fCntUp ) )
- {
- return LORAMAC_STATUS_FCNT_HANDLER_ERROR;
- }
- MacCtx.TxMsg.Message.Data.FHDR.FCnt = ( uint16_t )fCntUp;
- // Reset confirm parameters
- MacCtx.McpsConfirm.NbRetries = 0;
- MacCtx.McpsConfirm.AckReceived = false;
- MacCtx.McpsConfirm.UpLinkCounter = fCntUp;
- // Handle the MAC commands if there are any available
- if( LoRaMacCommandsGetSizeSerializedCmds( &macCmdsSize ) != LORAMAC_COMMANDS_SUCCESS )
- {
- return LORAMAC_STATUS_MAC_COMMAD_ERROR;
- }
- if( macCmdsSize > 0 )
- {
- availableSize = GetMaxAppPayloadWithoutFOptsLength( MacCtx.NvmCtx->MacParams.ChannelsDatarate );
- // There is application payload available and the MAC commands fit into FOpts field.
- if( ( MacCtx.AppDataSize > 0 ) && ( macCmdsSize <= LORA_MAC_COMMAND_MAX_FOPTS_LENGTH ) )
- {
- if( LoRaMacCommandsSerializeCmds( LORA_MAC_COMMAND_MAX_FOPTS_LENGTH, &macCmdsSize, MacCtx.TxMsg.Message.Data.FHDR.FOpts ) != LORAMAC_COMMANDS_SUCCESS )
- {
- return LORAMAC_STATUS_MAC_COMMAD_ERROR;
- }
- fCtrl->Bits.FOptsLen = macCmdsSize;
- // Update FCtrl field with new value of FOptionsLength
- MacCtx.TxMsg.Message.Data.FHDR.FCtrl.Value = fCtrl->Value;
- }
- // There is application payload available but the MAC commands does NOT fit into FOpts field.
- else if( ( MacCtx.AppDataSize > 0 ) && ( macCmdsSize > LORA_MAC_COMMAND_MAX_FOPTS_LENGTH ) )
- {
- if( LoRaMacCommandsSerializeCmds( availableSize, &macCmdsSize, MacCtx.NvmCtx->MacCommandsBuffer ) != LORAMAC_COMMANDS_SUCCESS )
- {
- return LORAMAC_STATUS_MAC_COMMAD_ERROR;
- }
- return LORAMAC_STATUS_SKIPPED_APP_DATA;
- }
- // No application payload available therefore add all mac commands to the FRMPayload.
- else
- {
- if( LoRaMacCommandsSerializeCmds( availableSize, &macCmdsSize, MacCtx.NvmCtx->MacCommandsBuffer ) != LORAMAC_COMMANDS_SUCCESS )
- {
- return LORAMAC_STATUS_MAC_COMMAD_ERROR;
- }
- // Force FPort to be zero
- MacCtx.TxMsg.Message.Data.FPort = 0;
- MacCtx.TxMsg.Message.Data.FRMPayload = MacCtx.NvmCtx->MacCommandsBuffer;
- MacCtx.TxMsg.Message.Data.FRMPayloadSize = macCmdsSize;
- }
- }
- break;
- case FRAME_TYPE_PROPRIETARY:
- if( ( fBuffer != NULL ) && ( MacCtx.AppDataSize > 0 ) )
- {
- memcpy1( MacCtx.PktBuffer + LORAMAC_MHDR_FIELD_SIZE, ( uint8_t* ) fBuffer, MacCtx.AppDataSize );
- MacCtx.PktBufferLen = LORAMAC_MHDR_FIELD_SIZE + MacCtx.AppDataSize;
- }
- break;
- default:
- return LORAMAC_STATUS_SERVICE_UNKNOWN;
- }
- return LORAMAC_STATUS_OK;
- }
- LoRaMacStatus_t SendFrameOnChannel( uint8_t channel )
- {
- TxConfigParams_t txConfig;
- int8_t txPower = 0;
- txConfig.Channel = channel;
- txConfig.Datarate = MacCtx.NvmCtx->MacParams.ChannelsDatarate;
- txConfig.TxPower = MacCtx.NvmCtx->MacParams.ChannelsTxPower;
- txConfig.MaxEirp = MacCtx.NvmCtx->MacParams.MaxEirp;
- txConfig.AntennaGain = MacCtx.NvmCtx->MacParams.AntennaGain;
- txConfig.PktLen = MacCtx.PktBufferLen;
- RegionTxConfig( MacCtx.NvmCtx->Region, &txConfig, &txPower, &MacCtx.TxTimeOnAir );
- MacCtx.McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
- MacCtx.McpsConfirm.Datarate = MacCtx.NvmCtx->MacParams.ChannelsDatarate;
- MacCtx.McpsConfirm.TxPower = txPower;
- MacCtx.McpsConfirm.Channel = channel;
- // Store the time on air
- MacCtx.McpsConfirm.TxTimeOnAir = MacCtx.TxTimeOnAir;
- MacCtx.MlmeConfirm.TxTimeOnAir = MacCtx.TxTimeOnAir;
- if( LoRaMacClassBIsBeaconModeActive( ) == true )
- {
- // Currently, the Time-On-Air can only be computed when the radio is configured with
- // the TX configuration
- TimerTime_t collisionTime = LoRaMacClassBIsUplinkCollision( MacCtx.TxTimeOnAir );
- if( collisionTime > 0 )
- {
- return LORAMAC_STATUS_BUSY_UPLINK_COLLISION;
- }
- }
- if( MacCtx.NvmCtx->DeviceClass == CLASS_B )
- {
- // Stop slots for class b
- LoRaMacClassBStopRxSlots( );
- }
- LoRaMacClassBHaltBeaconing( );
- MacCtx.MacState |= LORAMAC_TX_RUNNING;
- if( MacCtx.NodeAckRequested == false )
- {
- MacCtx.ChannelsNbTransCounter++;
- }
- // Send now
- Radio.Send( MacCtx.PktBuffer, MacCtx.PktBufferLen );
- return LORAMAC_STATUS_OK;
- }
- LoRaMacStatus_t SetTxContinuousWave( uint16_t timeout )
- {
- ContinuousWaveParams_t continuousWave;
- continuousWave.Channel = MacCtx.Channel;
- continuousWave.Datarate = MacCtx.NvmCtx->MacParams.ChannelsDatarate;
- continuousWave.TxPower = MacCtx.NvmCtx->MacParams.ChannelsTxPower;
- continuousWave.MaxEirp = MacCtx.NvmCtx->MacParams.MaxEirp;
- continuousWave.AntennaGain = MacCtx.NvmCtx->MacParams.AntennaGain;
- continuousWave.Timeout = timeout;
- RegionSetContinuousWave( MacCtx.NvmCtx->Region, &continuousWave );
- MacCtx.MacState |= LORAMAC_TX_RUNNING;
- return LORAMAC_STATUS_OK;
- }
- LoRaMacStatus_t SetTxContinuousWave1( uint16_t timeout, uint32_t frequency, uint8_t power )
- {
- Radio.SetTxContinuousWave( frequency, power, timeout );
- MacCtx.MacState |= LORAMAC_TX_RUNNING;
- return LORAMAC_STATUS_OK;
- }
- LoRaMacCtxs_t* GetCtxs( void )
- {
- Contexts.MacNvmCtx = &NvmMacCtx;
- Contexts.MacNvmCtxSize = sizeof( NvmMacCtx );
- Contexts.CryptoNvmCtx = LoRaMacCryptoGetNvmCtx( &Contexts.CryptoNvmCtxSize );
- GetNvmCtxParams_t params ={ 0 };
- Contexts.RegionNvmCtx = RegionGetNvmCtx( MacCtx.NvmCtx->Region, ¶ms );
- Contexts.RegionNvmCtxSize = params.nvmCtxSize;
- Contexts.SecureElementNvmCtx = SecureElementGetNvmCtx( &Contexts.SecureElementNvmCtxSize );
- Contexts.CommandsNvmCtx = LoRaMacCommandsGetNvmCtx( &Contexts.CommandsNvmCtxSize );
- Contexts.ClassBNvmCtx = LoRaMacClassBGetNvmCtx( &Contexts.ClassBNvmCtxSize );
- Contexts.ConfirmQueueNvmCtx = LoRaMacConfirmQueueGetNvmCtx( &Contexts.ConfirmQueueNvmCtxSize );
- return &Contexts;
- }
- LoRaMacStatus_t RestoreCtxs( LoRaMacCtxs_t* contexts )
- {
- if( contexts == NULL )
- {
- return LORAMAC_STATUS_PARAMETER_INVALID;
- }
- if( MacCtx.MacState != LORAMAC_STOPPED )
- {
- return LORAMAC_STATUS_BUSY;
- }
- if( contexts->MacNvmCtx != NULL )
- {
- memcpy1( ( uint8_t* ) &NvmMacCtx, ( uint8_t* ) contexts->MacNvmCtx, contexts->MacNvmCtxSize );
- }
- InitDefaultsParams_t params;
- params.Type = INIT_TYPE_RESTORE_CTX;
- params.NvmCtx = contexts->RegionNvmCtx;
- RegionInitDefaults( MacCtx.NvmCtx->Region, ¶ms );
- // Initialize RxC config parameters.
- MacCtx.RxWindowCConfig.Channel = MacCtx.Channel;
- MacCtx.RxWindowCConfig.Frequency = MacCtx.NvmCtx->MacParams.RxCChannel.Frequency;
- MacCtx.RxWindowCConfig.DownlinkDwellTime = MacCtx.NvmCtx->MacParams.DownlinkDwellTime;
- MacCtx.RxWindowCConfig.RepeaterSupport = MacCtx.NvmCtx->RepeaterSupport;
- MacCtx.RxWindowCConfig.RxContinuous = true;
- MacCtx.RxWindowCConfig.RxSlot = RX_SLOT_WIN_CLASS_C;
- if( SecureElementRestoreNvmCtx( contexts->SecureElementNvmCtx ) != SECURE_ELEMENT_SUCCESS )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- if( LoRaMacCryptoRestoreNvmCtx( contexts->CryptoNvmCtx ) != LORAMAC_CRYPTO_SUCCESS )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- if( LoRaMacCommandsRestoreNvmCtx( contexts->CommandsNvmCtx ) != LORAMAC_COMMANDS_SUCCESS )
- {
- return LORAMAC_STATUS_MAC_COMMAD_ERROR;
- }
- if( LoRaMacClassBRestoreNvmCtx( contexts->ClassBNvmCtx ) != true )
- {
- return LORAMAC_STATUS_CLASS_B_ERROR;
- }
- if( LoRaMacConfirmQueueRestoreNvmCtx( contexts->ConfirmQueueNvmCtx ) != true )
- {
- return LORAMAC_STATUS_CONFIRM_QUEUE_ERROR;
- }
- return LORAMAC_STATUS_OK;
- }
- LoRaMacStatus_t DetermineFrameType( LoRaMacMessageData_t* macMsg, FType_t* fType )
- {
- if( ( macMsg == NULL ) || ( fType == NULL ) )
- {
- return LORAMAC_STATUS_PARAMETER_INVALID;
- }
- /* The LoRaWAN specification allows several possible configurations how data up/down frames are built up.
- * In sake of clearness the following naming is applied. Please keep in mind that this is
- * implementation specific since there is no definition in the LoRaWAN specification included.
- *
- * X -> Field is available
- * - -> Field is not available
- *
- * +-------+ +----------+------+-------+--------------+
- * | FType | | FOptsLen | Fopt | FPort | FRMPayload |
- * +-------+ +----------+------+-------+--------------+
- * | A | | > 0 | X | > 0 | X |
- * +-------+ +----------+------+-------+--------------+
- * | B | | >= 0 | X/- | - | - |
- * +-------+ +----------+------+-------+--------------+
- * | C | | = 0 | - | = 0 | MAC commands |
- * +-------+ +----------+------+-------+--------------+
- * | D | | = 0 | - | > 0 | X |
- * +-------+ +----------+------+-------+--------------+
- */
- if( ( macMsg->FHDR.FCtrl.Bits.FOptsLen > 0 ) && ( macMsg->FPort > 0 ) )
- {
- *fType = FRAME_TYPE_A;
- }
- else if( macMsg->FRMPayloadSize == 0 )
- {
- *fType = FRAME_TYPE_B;
- }
- else if( ( macMsg->FHDR.FCtrl.Bits.FOptsLen == 0 ) && ( macMsg->FPort == 0 ) )
- {
- *fType = FRAME_TYPE_C;
- }
- else if( ( macMsg->FHDR.FCtrl.Bits.FOptsLen == 0 ) && ( macMsg->FPort > 0 ) )
- {
- *fType = FRAME_TYPE_D;
- }
- else
- {
- // Should never happen.
- return LORAMAC_STATUS_ERROR;
- }
- return LORAMAC_STATUS_OK;
- }
- static bool CheckRetransUnconfirmedUplink( void )
- {
- // Unconfirmed uplink, when all retransmissions are done.
- if( MacCtx.ChannelsNbTransCounter >=
- MacCtx.NvmCtx->MacParams.ChannelsNbTrans )
- {
- return true;
- }
- else if( MacCtx.MacFlags.Bits.McpsInd == 1 )
- {
- // For Class A stop in each case
- if( MacCtx.NvmCtx->DeviceClass == CLASS_A )
- {
- return true;
- }
- else
- {// For Class B & C stop only if the frame was received in RX1 window
- if( MacCtx.McpsIndication.RxSlot == RX_SLOT_WIN_1 )
- {
- return true;
- }
- }
- }
- return false;
- }
- static bool CheckRetransConfirmedUplink( void )
- {
- // Confirmed uplink, when all retransmissions ( tries to get a ack ) are done.
- if( MacCtx.AckTimeoutRetriesCounter >=
- MacCtx.AckTimeoutRetries )
- {
- return true;
- }
- else if( MacCtx.MacFlags.Bits.McpsInd == 1 )
- {
- if( MacCtx.McpsConfirm.AckReceived == true )
- {
- return true;
- }
- }
- return false;
- }
- static bool StopRetransmission( void )
- {
- if( ( MacCtx.MacFlags.Bits.McpsInd == 0 ) ||
- ( ( MacCtx.McpsIndication.RxSlot != RX_SLOT_WIN_1 ) &&
- ( MacCtx.McpsIndication.RxSlot != RX_SLOT_WIN_2 ) ) )
- { // Maximum repetitions without downlink. Increase ADR Ack counter.
- // Only process the case when the MAC did not receive a downlink.
- if( MacCtx.NvmCtx->AdrCtrlOn == true )
- {
- MacCtx.NvmCtx->AdrAckCounter++;
- }
- }
- MacCtx.ChannelsNbTransCounter = 0;
- MacCtx.NodeAckRequested = false;
- MacCtx.AckTimeoutRetry = false;
- MacCtx.MacState &= ~LORAMAC_TX_RUNNING;
- return true;
- }
- static void AckTimeoutRetriesProcess( void )
- {
- if( MacCtx.AckTimeoutRetriesCounter < MacCtx.AckTimeoutRetries )
- {
- MacCtx.AckTimeoutRetriesCounter++;
- if( ( MacCtx.AckTimeoutRetriesCounter % 2 ) == 1 )
- {
- GetPhyParams_t getPhy;
- PhyParam_t phyParam;
- getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
- getPhy.UplinkDwellTime = MacCtx.NvmCtx->MacParams.UplinkDwellTime;
- getPhy.Datarate = MacCtx.NvmCtx->MacParams.ChannelsDatarate;
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- MacCtx.NvmCtx->MacParams.ChannelsDatarate = phyParam.Value;
- }
- }
- }
- static void AckTimeoutRetriesFinalize( void )
- {
- if( MacCtx.McpsConfirm.AckReceived == false )
- {
- InitDefaultsParams_t params;
- params.Type = INIT_TYPE_RESTORE_DEFAULT_CHANNELS;
- params.NvmCtx = Contexts.RegionNvmCtx;
- RegionInitDefaults( MacCtx.NvmCtx->Region, ¶ms );
- MacCtx.NodeAckRequested = false;
- MacCtx.McpsConfirm.AckReceived = false;
- }
- MacCtx.McpsConfirm.NbRetries = MacCtx.AckTimeoutRetriesCounter;
- }
- static void CallNvmCtxCallback( LoRaMacNvmCtxModule_t module )
- {
- if( ( MacCtx.MacCallbacks != NULL ) && ( MacCtx.MacCallbacks->NvmContextChange != NULL ) )
- {
- MacCtx.MacCallbacks->NvmContextChange( module );
- }
- }
- static void EventMacNvmCtxChanged( void )
- {
- CallNvmCtxCallback( LORAMAC_NVMCTXMODULE_MAC );
- }
- static void EventRegionNvmCtxChanged( void )
- {
- CallNvmCtxCallback( LORAMAC_NVMCTXMODULE_REGION );
- }
- static void EventCryptoNvmCtxChanged( void )
- {
- CallNvmCtxCallback( LORAMAC_NVMCTXMODULE_CRYPTO );
- }
- static void EventSecureElementNvmCtxChanged( void )
- {
- CallNvmCtxCallback( LORAMAC_NVMCTXMODULE_SECURE_ELEMENT );
- }
- static void EventCommandsNvmCtxChanged( void )
- {
- CallNvmCtxCallback( LORAMAC_NVMCTXMODULE_COMMANDS );
- }
- static void EventClassBNvmCtxChanged( void )
- {
- CallNvmCtxCallback( LORAMAC_NVMCTXMODULE_CLASS_B );
- }
- static void EventConfirmQueueNvmCtxChanged( void )
- {
- CallNvmCtxCallback( LORAMAC_NVMCTXMODULE_CONFIRM_QUEUE );
- }
- static uint8_t IsRequestPending( void )
- {
- if( ( MacCtx.MacFlags.Bits.MlmeReq == 1 ) ||
- ( MacCtx.MacFlags.Bits.McpsReq == 1 ) )
- {
- return 1;
- }
- return 0;
- }
- LoRaMacStatus_t LoRaMacInitialization( LoRaMacPrimitives_t* primitives, LoRaMacCallback_t* callbacks, LoRaMacRegion_t region )
- {
- GetPhyParams_t getPhy;
- PhyParam_t phyParam;
- LoRaMacClassBCallback_t classBCallbacks;
- LoRaMacClassBParams_t classBParams;
- if( ( primitives == NULL ) ||
- ( callbacks == NULL ) )
- {
- return LORAMAC_STATUS_PARAMETER_INVALID;
- }
- if( ( primitives->MacMcpsConfirm == NULL ) ||
- ( primitives->MacMcpsIndication == NULL ) ||
- ( primitives->MacMlmeConfirm == NULL ) ||
- ( primitives->MacMlmeIndication == NULL ) )
- {
- return LORAMAC_STATUS_PARAMETER_INVALID;
- }
- // Verify if the region is supported
- if( RegionIsActive( region ) == false )
- {
- return LORAMAC_STATUS_REGION_NOT_SUPPORTED;
- }
- // Confirm queue reset
- LoRaMacConfirmQueueInit( primitives, EventConfirmQueueNvmCtxChanged );
- // Initialize the module context with zeros
- memset1( ( uint8_t* ) &NvmMacCtx, 0x00, sizeof( LoRaMacNvmCtx_t ) );
- memset1( ( uint8_t* ) &MacCtx, 0x00, sizeof( LoRaMacCtx_t ) );
- MacCtx.NvmCtx = &NvmMacCtx;
- // Set non zero variables to its default value
- MacCtx.AckTimeoutRetriesCounter = 1;
- MacCtx.AckTimeoutRetries = 1;
- MacCtx.NvmCtx->Region = region;
- MacCtx.NvmCtx->DeviceClass = CLASS_A;
- MacCtx.NvmCtx->RepeaterSupport = false;
- Version_t lrWanVersion;
- lrWanVersion.Fields.Major = 1;
- lrWanVersion.Fields.Minor = 0;
- lrWanVersion.Fields.Revision = 3;
- lrWanVersion.Fields.Rfu = 0;
- MacCtx.NvmCtx->Version = lrWanVersion;
- // Reset to defaults
- getPhy.Attribute = PHY_DUTY_CYCLE;
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- MacCtx.NvmCtx->DutyCycleOn = ( bool ) phyParam.Value;
- getPhy.Attribute = PHY_DEF_TX_POWER;
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- MacCtx.NvmCtx->MacParamsDefaults.ChannelsTxPower = phyParam.Value;
- getPhy.Attribute = PHY_DEF_TX_DR;
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- MacCtx.NvmCtx->MacParamsDefaults.ChannelsDatarate = phyParam.Value;
- getPhy.Attribute = PHY_MAX_RX_WINDOW;
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- MacCtx.NvmCtx->MacParamsDefaults.MaxRxWindow = phyParam.Value;
- getPhy.Attribute = PHY_RECEIVE_DELAY1;
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- MacCtx.NvmCtx->MacParamsDefaults.ReceiveDelay1 = phyParam.Value;
- getPhy.Attribute = PHY_RECEIVE_DELAY2;
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- MacCtx.NvmCtx->MacParamsDefaults.ReceiveDelay2 = phyParam.Value;
- getPhy.Attribute = PHY_JOIN_ACCEPT_DELAY1;
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- MacCtx.NvmCtx->MacParamsDefaults.JoinAcceptDelay1 = phyParam.Value;
- getPhy.Attribute = PHY_JOIN_ACCEPT_DELAY2;
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- MacCtx.NvmCtx->MacParamsDefaults.JoinAcceptDelay2 = phyParam.Value;
- getPhy.Attribute = PHY_DEF_DR1_OFFSET;
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- MacCtx.NvmCtx->MacParamsDefaults.Rx1DrOffset = phyParam.Value;
- getPhy.Attribute = PHY_DEF_RX2_FREQUENCY;
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- MacCtx.NvmCtx->MacParamsDefaults.Rx2Channel.Frequency = phyParam.Value;
- MacCtx.NvmCtx->MacParamsDefaults.RxCChannel.Frequency = phyParam.Value;
- getPhy.Attribute = PHY_DEF_RX2_DR;
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- MacCtx.NvmCtx->MacParamsDefaults.Rx2Channel.Datarate = phyParam.Value;
- MacCtx.NvmCtx->MacParamsDefaults.RxCChannel.Datarate = phyParam.Value;
- getPhy.Attribute = PHY_DEF_UPLINK_DWELL_TIME;
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- MacCtx.NvmCtx->MacParamsDefaults.UplinkDwellTime = phyParam.Value;
- getPhy.Attribute = PHY_DEF_DOWNLINK_DWELL_TIME;
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- MacCtx.NvmCtx->MacParamsDefaults.DownlinkDwellTime = phyParam.Value;
- getPhy.Attribute = PHY_DEF_MAX_EIRP;
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- MacCtx.NvmCtx->MacParamsDefaults.MaxEirp = phyParam.fValue;
- getPhy.Attribute = PHY_DEF_ANTENNA_GAIN;
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- MacCtx.NvmCtx->MacParamsDefaults.AntennaGain = phyParam.fValue;
- getPhy.Attribute = PHY_DEF_ADR_ACK_LIMIT;
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- MacCtx.AdrAckLimit = phyParam.Value;
- getPhy.Attribute = PHY_DEF_ADR_ACK_DELAY;
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- MacCtx.AdrAckDelay = phyParam.Value;
- // Init parameters which are not set in function ResetMacParameters
- MacCtx.NvmCtx->MacParamsDefaults.ChannelsNbTrans = 1;
- MacCtx.NvmCtx->MacParamsDefaults.SystemMaxRxError = 10;
- MacCtx.NvmCtx->MacParamsDefaults.MinRxSymbols = 6;
- MacCtx.NvmCtx->MacParams.SystemMaxRxError = MacCtx.NvmCtx->MacParamsDefaults.SystemMaxRxError;
- MacCtx.NvmCtx->MacParams.MinRxSymbols = MacCtx.NvmCtx->MacParamsDefaults.MinRxSymbols;
- MacCtx.NvmCtx->MacParams.MaxRxWindow = MacCtx.NvmCtx->MacParamsDefaults.MaxRxWindow;
- MacCtx.NvmCtx->MacParams.ReceiveDelay1 = MacCtx.NvmCtx->MacParamsDefaults.ReceiveDelay1;
- MacCtx.NvmCtx->MacParams.ReceiveDelay2 = MacCtx.NvmCtx->MacParamsDefaults.ReceiveDelay2;
- MacCtx.NvmCtx->MacParams.JoinAcceptDelay1 = MacCtx.NvmCtx->MacParamsDefaults.JoinAcceptDelay1;
- MacCtx.NvmCtx->MacParams.JoinAcceptDelay2 = MacCtx.NvmCtx->MacParamsDefaults.JoinAcceptDelay2;
- MacCtx.NvmCtx->MacParams.ChannelsNbTrans = MacCtx.NvmCtx->MacParamsDefaults.ChannelsNbTrans;
- ResetMacParameters( );
- MacCtx.NvmCtx->PublicNetwork = true;
- MacCtx.MacPrimitives = primitives;
- MacCtx.MacCallbacks = callbacks;
- MacCtx.MacFlags.Value = 0;
- MacCtx.MacState = LORAMAC_STOPPED;
- // Reset duty cycle times
- MacCtx.NvmCtx->LastTxDoneTime = 0;
- MacCtx.NvmCtx->AggregatedTimeOff = 0;
- // Initialize timers
- TimerInit( &MacCtx.TxDelayedTimer, OnTxDelayedTimerEvent );
- TimerInit( &MacCtx.RxWindowTimer1, OnRxWindow1TimerEvent );
- TimerInit( &MacCtx.RxWindowTimer2, OnRxWindow2TimerEvent );
- TimerInit( &MacCtx.AckTimeoutTimer,OnAckTimeoutTimerEvent );
- // Store the current initialization time
- //MacCtx.NvmCtx->InitializationTime = SysTimeGetMcuTime( );
- // Initialize Radio driver
- MacCtx.RadioEvents.TxDone = OnRadioTxDone;
- MacCtx.RadioEvents.RxDone = OnRadioRxDone;
- MacCtx.RadioEvents.RxError = OnRadioRxError;
- MacCtx.RadioEvents.TxTimeout = OnRadioTxTimeout;
- MacCtx.RadioEvents.RxTimeout = OnRadioRxTimeout;
- Radio.Init( &MacCtx.RadioEvents );
- InitDefaultsParams_t params;
- params.Type = INIT_TYPE_INIT;
- params.NvmCtx = NULL;
- RegionInitDefaults( MacCtx.NvmCtx->Region, ¶ms );
- // Initialize the Secure Element driver
- if( SecureElementInit( EventSecureElementNvmCtxChanged ) != SECURE_ELEMENT_SUCCESS )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- // Initialize Crypto module
- if( LoRaMacCryptoInit( EventCryptoNvmCtxChanged ) != LORAMAC_CRYPTO_SUCCESS )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- // Initialize MAC commands module
- if( LoRaMacCommandsInit( EventCommandsNvmCtxChanged ) != LORAMAC_COMMANDS_SUCCESS )
- {
- return LORAMAC_STATUS_MAC_COMMAD_ERROR;
- }
- // Set multicast downlink counter reference
- if( LoRaMacCryptoSetMulticastReference( MacCtx.NvmCtx->MulticastChannelList ) != LORAMAC_CRYPTO_SUCCESS )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- // Random seed initialization
- srand1( Radio.Random( ) );
- Radio.SetPublicNetwork( MacCtx.NvmCtx->PublicNetwork );
- Radio.Sleep( );
- // Initialize class b
- // Apply callback
- classBCallbacks.GetTemperatureLevel = NULL;
- classBCallbacks.MacProcessNotify = NULL;
- if( callbacks != NULL )
- {
- classBCallbacks.GetTemperatureLevel = callbacks->GetTemperatureLevel;
- classBCallbacks.MacProcessNotify = callbacks->MacProcessNotify;
- }
- // Must all be static. Don't use local references.
- classBParams.MlmeIndication = &MacCtx.MlmeIndication;
- classBParams.McpsIndication = &MacCtx.McpsIndication;
- classBParams.MlmeConfirm = &MacCtx.MlmeConfirm;
- classBParams.LoRaMacFlags = &MacCtx.MacFlags;
- classBParams.LoRaMacDevAddr = &MacCtx.NvmCtx->DevAddr;
- classBParams.LoRaMacRegion = &MacCtx.NvmCtx->Region;
- classBParams.LoRaMacParams = &MacCtx.NvmCtx->MacParams;
- classBParams.MulticastChannels = &MacCtx.NvmCtx->MulticastChannelList[0];
- LoRaMacClassBInit( &classBParams, &classBCallbacks, &EventClassBNvmCtxChanged );
- LoRaMacEnableRequests( LORAMAC_REQUEST_HANDLING_ON );
- return LORAMAC_STATUS_OK;
- }
- LoRaMacStatus_t LoRaMacStart( void )
- {
- MacCtx.MacState = LORAMAC_IDLE;
- return LORAMAC_STATUS_OK;
- }
- LoRaMacStatus_t LoRaMacStop( void )
- {
- if( LoRaMacIsBusy( ) == false )
- {
- MacCtx.MacState = LORAMAC_STOPPED;
- return LORAMAC_STATUS_OK;
- }
- else if( MacCtx.MacState == LORAMAC_STOPPED )
- {
- return LORAMAC_STATUS_OK;
- }
- return LORAMAC_STATUS_BUSY;
- }
- LoRaMacStatus_t LoRaMacQueryTxPossible( uint8_t size, LoRaMacTxInfo_t* txInfo )
- {
- CalcNextAdrParams_t adrNext;
- uint32_t adrAckCounter = MacCtx.NvmCtx->AdrAckCounter;
- int8_t datarate = MacCtx.NvmCtx->MacParamsDefaults.ChannelsDatarate;
- int8_t txPower = MacCtx.NvmCtx->MacParamsDefaults.ChannelsTxPower;
- size_t macCmdsSize = 0;
- if( txInfo == NULL )
- {
- return LORAMAC_STATUS_PARAMETER_INVALID;
- }
- // Setup ADR request
- adrNext.Version = MacCtx.NvmCtx->Version;
- adrNext.UpdateChanMask = false;
- adrNext.AdrEnabled = MacCtx.NvmCtx->AdrCtrlOn;
- adrNext.AdrAckCounter = MacCtx.NvmCtx->AdrAckCounter;
- adrNext.AdrAckLimit = MacCtx.AdrAckLimit;
- adrNext.AdrAckDelay = MacCtx.AdrAckDelay;
- adrNext.Datarate = MacCtx.NvmCtx->MacParams.ChannelsDatarate;
- adrNext.TxPower = MacCtx.NvmCtx->MacParams.ChannelsTxPower;
- adrNext.UplinkDwellTime = MacCtx.NvmCtx->MacParams.UplinkDwellTime;
- adrNext.Region = MacCtx.NvmCtx->Region;
- // We call the function for information purposes only. We don't want to
- // apply the datarate, the tx power and the ADR ack counter.
- LoRaMacAdrCalcNext( &adrNext, &datarate, &txPower, &adrAckCounter );
- txInfo->CurrentPossiblePayloadSize = GetMaxAppPayloadWithoutFOptsLength( datarate );
- if( LoRaMacCommandsGetSizeSerializedCmds( &macCmdsSize ) != LORAMAC_COMMANDS_SUCCESS )
- {
- return LORAMAC_STATUS_MAC_COMMAD_ERROR;
- }
- // Verify if the MAC commands fit into the FOpts and into the maximum payload.
- if( ( LORA_MAC_COMMAND_MAX_FOPTS_LENGTH >= macCmdsSize ) && ( txInfo->CurrentPossiblePayloadSize >= macCmdsSize ) )
- {
- txInfo->MaxPossibleApplicationDataSize = txInfo->CurrentPossiblePayloadSize - macCmdsSize;
- // Verify if the application data together with MAC command fit into the maximum payload.
- if( txInfo->CurrentPossiblePayloadSize >= ( macCmdsSize + size ) )
- {
- return LORAMAC_STATUS_OK;
- }
- else
- {
- return LORAMAC_STATUS_LENGTH_ERROR;
- }
- }
- else
- {
- txInfo->MaxPossibleApplicationDataSize = 0;
- return LORAMAC_STATUS_LENGTH_ERROR;
- }
- }
- LoRaMacStatus_t LoRaMacMibGetRequestConfirm( MibRequestConfirm_t* mibGet )
- {
- LoRaMacStatus_t status = LORAMAC_STATUS_OK;
- GetPhyParams_t getPhy;
- PhyParam_t phyParam;
- if( mibGet == NULL )
- {
- return LORAMAC_STATUS_PARAMETER_INVALID;
- }
- switch( mibGet->Type )
- {
- case MIB_DEVICE_CLASS:
- {
- mibGet->Param.Class = MacCtx.NvmCtx->DeviceClass;
- break;
- }
- case MIB_NETWORK_ACTIVATION:
- {
- mibGet->Param.NetworkActivation = MacCtx.NvmCtx->NetworkActivation;
- break;
- }
- case MIB_DEV_EUI:
- {
- mibGet->Param.DevEui = SecureElementGetDevEui( );
- break;
- }
- case MIB_JOIN_EUI:
- {
- mibGet->Param.JoinEui = SecureElementGetJoinEui( );
- break;
- }
- case MIB_ADR:
- {
- mibGet->Param.AdrEnable = MacCtx.NvmCtx->AdrCtrlOn;
- break;
- }
- case MIB_NET_ID:
- {
- mibGet->Param.NetID = MacCtx.NvmCtx->NetID;
- break;
- }
- case MIB_DEV_ADDR:
- {
- mibGet->Param.DevAddr = MacCtx.NvmCtx->DevAddr;
- break;
- }
- case MIB_PUBLIC_NETWORK:
- {
- mibGet->Param.EnablePublicNetwork = MacCtx.NvmCtx->PublicNetwork;
- break;
- }
- case MIB_REPEATER_SUPPORT:
- {
- mibGet->Param.EnableRepeaterSupport = MacCtx.NvmCtx->RepeaterSupport;
- break;
- }
- case MIB_CHANNELS:
- {
- getPhy.Attribute = PHY_CHANNELS;
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- mibGet->Param.ChannelList = phyParam.Channels;
- break;
- }
- case MIB_RX2_CHANNEL:
- {
- mibGet->Param.Rx2Channel = MacCtx.NvmCtx->MacParams.Rx2Channel;
- break;
- }
- case MIB_RX2_DEFAULT_CHANNEL:
- {
- mibGet->Param.Rx2Channel = MacCtx.NvmCtx->MacParamsDefaults.Rx2Channel;
- break;
- }
- case MIB_RXC_CHANNEL:
- {
- mibGet->Param.RxCChannel = MacCtx.NvmCtx->MacParams.RxCChannel;
- break;
- }
- case MIB_RXC_DEFAULT_CHANNEL:
- {
- mibGet->Param.RxCChannel = MacCtx.NvmCtx->MacParamsDefaults.RxCChannel;
- break;
- }
- case MIB_CHANNELS_DEFAULT_MASK:
- {
- getPhy.Attribute = PHY_CHANNELS_DEFAULT_MASK;
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- mibGet->Param.ChannelsDefaultMask = phyParam.ChannelsMask;
- break;
- }
- case MIB_CHANNELS_MASK:
- {
- getPhy.Attribute = PHY_CHANNELS_MASK;
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- mibGet->Param.ChannelsMask = phyParam.ChannelsMask;
- break;
- }
- case MIB_CHANNELS_NB_TRANS:
- {
- mibGet->Param.ChannelsNbTrans = MacCtx.NvmCtx->MacParams.ChannelsNbTrans;
- break;
- }
- case MIB_MAX_RX_WINDOW_DURATION:
- {
- mibGet->Param.MaxRxWindow = MacCtx.NvmCtx->MacParams.MaxRxWindow;
- break;
- }
- case MIB_RECEIVE_DELAY_1:
- {
- mibGet->Param.ReceiveDelay1 = MacCtx.NvmCtx->MacParams.ReceiveDelay1;
- break;
- }
- case MIB_RECEIVE_DELAY_2:
- {
- mibGet->Param.ReceiveDelay2 = MacCtx.NvmCtx->MacParams.ReceiveDelay2;
- break;
- }
- case MIB_JOIN_ACCEPT_DELAY_1:
- {
- mibGet->Param.JoinAcceptDelay1 = MacCtx.NvmCtx->MacParams.JoinAcceptDelay1;
- break;
- }
- case MIB_JOIN_ACCEPT_DELAY_2:
- {
- mibGet->Param.JoinAcceptDelay2 = MacCtx.NvmCtx->MacParams.JoinAcceptDelay2;
- break;
- }
- case MIB_CHANNELS_DEFAULT_DATARATE:
- {
- mibGet->Param.ChannelsDefaultDatarate = MacCtx.NvmCtx->MacParamsDefaults.ChannelsDatarate;
- break;
- }
- case MIB_CHANNELS_DATARATE:
- {
- mibGet->Param.ChannelsDatarate = MacCtx.NvmCtx->MacParams.ChannelsDatarate;
- break;
- }
- case MIB_CHANNELS_DEFAULT_TX_POWER:
- {
- mibGet->Param.ChannelsDefaultTxPower = MacCtx.NvmCtx->MacParamsDefaults.ChannelsTxPower;
- break;
- }
- case MIB_CHANNELS_TX_POWER:
- {
- mibGet->Param.ChannelsTxPower = MacCtx.NvmCtx->MacParams.ChannelsTxPower;
- break;
- }
- case MIB_SYSTEM_MAX_RX_ERROR:
- {
- mibGet->Param.SystemMaxRxError = MacCtx.NvmCtx->MacParams.SystemMaxRxError;
- break;
- }
- case MIB_MIN_RX_SYMBOLS:
- {
- mibGet->Param.MinRxSymbols = MacCtx.NvmCtx->MacParams.MinRxSymbols;
- break;
- }
- case MIB_ANTENNA_GAIN:
- {
- mibGet->Param.AntennaGain = MacCtx.NvmCtx->MacParams.AntennaGain;
- break;
- }
- case MIB_NVM_CTXS:
- {
- mibGet->Param.Contexts = GetCtxs( );
- break;
- }
- case MIB_DEFAULT_ANTENNA_GAIN:
- {
- mibGet->Param.DefaultAntennaGain = MacCtx.NvmCtx->MacParamsDefaults.AntennaGain;
- break;
- }
- default:
- {
- status = LoRaMacClassBMibGetRequestConfirm( mibGet );
- break;
- }
- }
- return status;
- }
- LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t* mibSet )
- {
- LoRaMacStatus_t status = LORAMAC_STATUS_OK;
- ChanMaskSetParams_t chanMaskSet;
- VerifyParams_t verify;
- if( mibSet == NULL )
- {
- return LORAMAC_STATUS_PARAMETER_INVALID;
- }
- if( ( MacCtx.MacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
- {
- return LORAMAC_STATUS_BUSY;
- }
- switch( mibSet->Type )
- {
- case MIB_DEVICE_CLASS:
- {
- status = SwitchClass( mibSet->Param.Class );
- break;
- }
- case MIB_NETWORK_ACTIVATION:
- {
- if( mibSet->Param.NetworkActivation != ACTIVATION_TYPE_OTAA )
- {
- MacCtx.NvmCtx->NetworkActivation = mibSet->Param.NetworkActivation;
- }
- else
- { // Do not allow to set ACTIVATION_TYPE_OTAA since the MAC will set it automatically after a successful join process.
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_DEV_EUI:
- {
- if( SecureElementSetDevEui( mibSet->Param.DevEui ) != SECURE_ELEMENT_SUCCESS )
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_JOIN_EUI:
- {
- if( SecureElementSetJoinEui( mibSet->Param.JoinEui ) != SECURE_ELEMENT_SUCCESS )
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_ADR:
- {
- MacCtx.NvmCtx->AdrCtrlOn = mibSet->Param.AdrEnable;
- break;
- }
- case MIB_NET_ID:
- {
- MacCtx.NvmCtx->NetID = mibSet->Param.NetID;
- break;
- }
- case MIB_DEV_ADDR:
- {
- MacCtx.NvmCtx->DevAddr = mibSet->Param.DevAddr;
- break;
- }
- case MIB_GEN_APP_KEY:
- {
- if( mibSet->Param.GenAppKey != NULL )
- {
- if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( GEN_APP_KEY, mibSet->Param.GenAppKey ) )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_APP_KEY:
- {
- if( mibSet->Param.AppKey != NULL )
- {
- if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( APP_KEY, mibSet->Param.AppKey ) )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_NWK_KEY:
- {
- if( mibSet->Param.NwkKey != NULL )
- {
- if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( NWK_KEY, mibSet->Param.NwkKey ) )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_J_S_INT_KEY:
- {
- if( mibSet->Param.JSIntKey != NULL )
- {
- if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( J_S_INT_KEY, mibSet->Param.JSIntKey ) )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_J_S_ENC_KEY:
- {
- if( mibSet->Param.JSEncKey != NULL )
- {
- if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( J_S_ENC_KEY, mibSet->Param.JSEncKey ) )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_F_NWK_S_INT_KEY:
- {
- if( mibSet->Param.FNwkSIntKey != NULL )
- {
- if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( F_NWK_S_INT_KEY, mibSet->Param.FNwkSIntKey ) )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_S_NWK_S_INT_KEY:
- {
- if( mibSet->Param.SNwkSIntKey != NULL )
- {
- if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( S_NWK_S_INT_KEY, mibSet->Param.SNwkSIntKey ) )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_NWK_S_ENC_KEY:
- {
- if( mibSet->Param.NwkSEncKey != NULL )
- {
- if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( NWK_S_ENC_KEY, mibSet->Param.NwkSEncKey ) )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_APP_S_KEY:
- {
- if( mibSet->Param.AppSKey != NULL )
- {
- if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( APP_S_KEY, mibSet->Param.AppSKey ) )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_MC_KE_KEY:
- {
- if( mibSet->Param.McKEKey != NULL )
- {
- if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_KE_KEY, mibSet->Param.McKEKey ) )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_MC_KEY_0:
- {
- if( mibSet->Param.McKey0 != NULL )
- {
- if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_KEY_0, mibSet->Param.McKey0 ) )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_MC_APP_S_KEY_0:
- {
- if( mibSet->Param.McAppSKey0 != NULL )
- {
- if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_APP_S_KEY_0, mibSet->Param.McAppSKey0 ) )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_MC_NWK_S_KEY_0:
- {
- if( mibSet->Param.McNwkSKey0 != NULL )
- {
- if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_NWK_S_KEY_0, mibSet->Param.McNwkSKey0 ) )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_MC_KEY_1:
- {
- if( mibSet->Param.McKey1 != NULL )
- {
- if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_KEY_1, mibSet->Param.McKey1 ) )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_MC_APP_S_KEY_1:
- {
- if( mibSet->Param.McAppSKey1 != NULL )
- {
- if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_APP_S_KEY_1, mibSet->Param.McAppSKey1 ) )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_MC_NWK_S_KEY_1:
- {
- if( mibSet->Param.McNwkSKey1 != NULL )
- {
- if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_NWK_S_KEY_1, mibSet->Param.McNwkSKey1 ) )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_MC_KEY_2:
- {
- if( mibSet->Param.McKey2 != NULL )
- {
- if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_KEY_2, mibSet->Param.McKey2 ) )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_MC_APP_S_KEY_2:
- {
- if( mibSet->Param.McAppSKey2 != NULL )
- {
- if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_APP_S_KEY_2, mibSet->Param.McAppSKey2 ) )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_MC_NWK_S_KEY_2:
- {
- if( mibSet->Param.McNwkSKey2 != NULL )
- {
- if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_NWK_S_KEY_2, mibSet->Param.McNwkSKey2 ) )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_MC_KEY_3:
- {
- if( mibSet->Param.McKey3 != NULL )
- {
- if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_KEY_3, mibSet->Param.McKey3 ) )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_MC_APP_S_KEY_3:
- {
- if( mibSet->Param.McAppSKey3 != NULL )
- {
- if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_APP_S_KEY_3, mibSet->Param.McAppSKey3 ) )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_MC_NWK_S_KEY_3:
- {
- if( mibSet->Param.McNwkSKey3 != NULL )
- {
- if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_NWK_S_KEY_3, mibSet->Param.McNwkSKey3 ) )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_PUBLIC_NETWORK:
- {
- MacCtx.NvmCtx->PublicNetwork = mibSet->Param.EnablePublicNetwork;
- Radio.SetPublicNetwork( MacCtx.NvmCtx->PublicNetwork );
- break;
- }
- case MIB_REPEATER_SUPPORT:
- {
- MacCtx.NvmCtx->RepeaterSupport = mibSet->Param.EnableRepeaterSupport;
- break;
- }
- case MIB_RX2_CHANNEL:
- {
- verify.DatarateParams.Datarate = mibSet->Param.Rx2Channel.Datarate;
- verify.DatarateParams.DownlinkDwellTime = MacCtx.NvmCtx->MacParams.DownlinkDwellTime;
- if( RegionVerify( MacCtx.NvmCtx->Region, &verify, PHY_RX_DR ) == true )
- {
- MacCtx.NvmCtx->MacParams.Rx2Channel = mibSet->Param.Rx2Channel;
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_RX2_DEFAULT_CHANNEL:
- {
- verify.DatarateParams.Datarate = mibSet->Param.Rx2Channel.Datarate;
- verify.DatarateParams.DownlinkDwellTime = MacCtx.NvmCtx->MacParams.DownlinkDwellTime;
- if( RegionVerify( MacCtx.NvmCtx->Region, &verify, PHY_RX_DR ) == true )
- {
- MacCtx.NvmCtx->MacParamsDefaults.Rx2Channel = mibSet->Param.Rx2DefaultChannel;
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_RXC_CHANNEL:
- {
- verify.DatarateParams.Datarate = mibSet->Param.RxCChannel.Datarate;
- verify.DatarateParams.DownlinkDwellTime = MacCtx.NvmCtx->MacParams.DownlinkDwellTime;
- if( RegionVerify( MacCtx.NvmCtx->Region, &verify, PHY_RX_DR ) == true )
- {
- MacCtx.NvmCtx->MacParams.RxCChannel = mibSet->Param.RxCChannel;
- if( ( MacCtx.NvmCtx->DeviceClass == CLASS_C ) && ( MacCtx.NvmCtx->NetworkActivation != ACTIVATION_TYPE_NONE ) )
- {
- // We can only compute the RX window parameters directly, if we are already
- // in class c mode and joined. We cannot setup an RX window in case of any other
- // class type.
- // Set the radio into sleep mode in case we are still in RX mode
- Radio.Sleep( );
- OpenContinuousRxCWindow( );
- }
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_RXC_DEFAULT_CHANNEL:
- {
- verify.DatarateParams.Datarate = mibSet->Param.RxCChannel.Datarate;
- verify.DatarateParams.DownlinkDwellTime = MacCtx.NvmCtx->MacParams.DownlinkDwellTime;
- if( RegionVerify( MacCtx.NvmCtx->Region, &verify, PHY_RX_DR ) == true )
- {
- MacCtx.NvmCtx->MacParamsDefaults.RxCChannel = mibSet->Param.RxCDefaultChannel;
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_CHANNELS_DEFAULT_MASK:
- {
- chanMaskSet.ChannelsMaskIn = mibSet->Param.ChannelsDefaultMask;
- chanMaskSet.ChannelsMaskType = CHANNELS_DEFAULT_MASK;
- if( RegionChanMaskSet( MacCtx.NvmCtx->Region, &chanMaskSet ) == false )
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_CHANNELS_MASK:
- {
- chanMaskSet.ChannelsMaskIn = mibSet->Param.ChannelsMask;
- chanMaskSet.ChannelsMaskType = CHANNELS_MASK;
- if( RegionChanMaskSet( MacCtx.NvmCtx->Region, &chanMaskSet ) == false )
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_CHANNELS_NB_TRANS:
- {
- if( ( mibSet->Param.ChannelsNbTrans >= 1 ) &&
- ( mibSet->Param.ChannelsNbTrans <= 15 ) )
- {
- MacCtx.NvmCtx->MacParams.ChannelsNbTrans = mibSet->Param.ChannelsNbTrans;
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_MAX_RX_WINDOW_DURATION:
- {
- MacCtx.NvmCtx->MacParams.MaxRxWindow = mibSet->Param.MaxRxWindow;
- break;
- }
- case MIB_RECEIVE_DELAY_1:
- {
- MacCtx.NvmCtx->MacParams.ReceiveDelay1 = mibSet->Param.ReceiveDelay1;
- break;
- }
- case MIB_RECEIVE_DELAY_2:
- {
- MacCtx.NvmCtx->MacParams.ReceiveDelay2 = mibSet->Param.ReceiveDelay2;
- break;
- }
- case MIB_JOIN_ACCEPT_DELAY_1:
- {
- MacCtx.NvmCtx->MacParams.JoinAcceptDelay1 = mibSet->Param.JoinAcceptDelay1;
- break;
- }
- case MIB_JOIN_ACCEPT_DELAY_2:
- {
- MacCtx.NvmCtx->MacParams.JoinAcceptDelay2 = mibSet->Param.JoinAcceptDelay2;
- break;
- }
- case MIB_CHANNELS_DEFAULT_DATARATE:
- {
- verify.DatarateParams.Datarate = mibSet->Param.ChannelsDefaultDatarate;
- if( RegionVerify( MacCtx.NvmCtx->Region, &verify, PHY_DEF_TX_DR ) == true )
- {
- MacCtx.NvmCtx->MacParamsDefaults.ChannelsDatarate = verify.DatarateParams.Datarate;
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_CHANNELS_DATARATE:
- {
- verify.DatarateParams.Datarate = mibSet->Param.ChannelsDatarate;
- verify.DatarateParams.UplinkDwellTime = MacCtx.NvmCtx->MacParams.UplinkDwellTime;
- if( RegionVerify( MacCtx.NvmCtx->Region, &verify, PHY_TX_DR ) == true )
- {
- MacCtx.NvmCtx->MacParams.ChannelsDatarate = verify.DatarateParams.Datarate;
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_CHANNELS_DEFAULT_TX_POWER:
- {
- verify.TxPower = mibSet->Param.ChannelsDefaultTxPower;
- if( RegionVerify( MacCtx.NvmCtx->Region, &verify, PHY_DEF_TX_POWER ) == true )
- {
- MacCtx.NvmCtx->MacParamsDefaults.ChannelsTxPower = verify.TxPower;
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_CHANNELS_TX_POWER:
- {
- verify.TxPower = mibSet->Param.ChannelsTxPower;
- if( RegionVerify( MacCtx.NvmCtx->Region, &verify, PHY_TX_POWER ) == true )
- {
- MacCtx.NvmCtx->MacParams.ChannelsTxPower = verify.TxPower;
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_SYSTEM_MAX_RX_ERROR:
- {
- MacCtx.NvmCtx->MacParams.SystemMaxRxError = MacCtx.NvmCtx->MacParamsDefaults.SystemMaxRxError = mibSet->Param.SystemMaxRxError;
- break;
- }
- case MIB_MIN_RX_SYMBOLS:
- {
- MacCtx.NvmCtx->MacParams.MinRxSymbols = MacCtx.NvmCtx->MacParamsDefaults.MinRxSymbols = mibSet->Param.MinRxSymbols;
- break;
- }
- case MIB_ANTENNA_GAIN:
- {
- MacCtx.NvmCtx->MacParams.AntennaGain = mibSet->Param.AntennaGain;
- break;
- }
- case MIB_DEFAULT_ANTENNA_GAIN:
- {
- MacCtx.NvmCtx->MacParamsDefaults.AntennaGain = mibSet->Param.DefaultAntennaGain;
- break;
- }
- case MIB_NVM_CTXS:
- {
- if( mibSet->Param.Contexts != 0 )
- {
- status = RestoreCtxs( mibSet->Param.Contexts );
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- case MIB_ABP_LORAWAN_VERSION:
- {
- if( mibSet->Param.AbpLrWanVersion.Fields.Minor <= 1 )
- {
- MacCtx.NvmCtx->Version = mibSet->Param.AbpLrWanVersion;
- if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetLrWanVersion( mibSet->Param.AbpLrWanVersion ) )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
- break;
- }
- default:
- {
- status = LoRaMacMibClassBSetRequestConfirm( mibSet );
- break;
- }
- }
- EventRegionNvmCtxChanged( );
- EventMacNvmCtxChanged( );
- return status;
- }
- LoRaMacStatus_t LoRaMacChannelAdd( uint8_t id, ChannelParams_t params )
- {
- ChannelAddParams_t channelAdd;
- // Validate if the MAC is in a correct state
- if( ( MacCtx.MacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
- {
- if( ( MacCtx.MacState & LORAMAC_TX_CONFIG ) != LORAMAC_TX_CONFIG )
- {
- return LORAMAC_STATUS_BUSY;
- }
- }
- channelAdd.NewChannel = ¶ms;
- channelAdd.ChannelId = id;
- EventRegionNvmCtxChanged( );
- return RegionChannelAdd( MacCtx.NvmCtx->Region, &channelAdd );
- }
- LoRaMacStatus_t LoRaMacChannelRemove( uint8_t id )
- {
- ChannelRemoveParams_t channelRemove;
- if( ( MacCtx.MacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
- {
- if( ( MacCtx.MacState & LORAMAC_TX_CONFIG ) != LORAMAC_TX_CONFIG )
- {
- return LORAMAC_STATUS_BUSY;
- }
- }
- channelRemove.ChannelId = id;
- if( RegionChannelsRemove( MacCtx.NvmCtx->Region, &channelRemove ) == false )
- {
- return LORAMAC_STATUS_PARAMETER_INVALID;
- }
- EventRegionNvmCtxChanged( );
- return LORAMAC_STATUS_OK;
- }
- LoRaMacStatus_t LoRaMacMcChannelSetup( McChannelParams_t *channel )
- {
- if( ( MacCtx.MacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
- {
- return LORAMAC_STATUS_BUSY;
- }
- if( channel->GroupID >= LORAMAC_MAX_MC_CTX )
- {
- return LORAMAC_STATUS_MC_GROUP_UNDEFINED;
- }
- MacCtx.NvmCtx->MulticastChannelList[channel->GroupID].ChannelParams = *channel;
- const KeyIdentifier_t mcKeys[LORAMAC_MAX_MC_CTX] = { MC_KEY_0, MC_KEY_1, MC_KEY_2, MC_KEY_3 };
- if( LoRaMacCryptoSetKey( mcKeys[channel->GroupID], channel->McKeyE ) != LORAMAC_CRYPTO_SUCCESS )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- if( LoRaMacCryptoDeriveMcSessionKeyPair( channel->GroupID, channel->Address ) != LORAMAC_CRYPTO_SUCCESS )
- {
- return LORAMAC_STATUS_CRYPTO_ERROR;
- }
- if( channel->Class == CLASS_B )
- {
- // Calculate class b parameters
- LoRaMacClassBSetMulticastPeriodicity( &MacCtx.NvmCtx->MulticastChannelList[channel->GroupID] );
- }
- // Reset multicast channel downlink counter to initial value.
- *MacCtx.NvmCtx->MulticastChannelList[channel->GroupID].DownLinkCounter = FCNT_DOWN_INITAL_VALUE;
- EventMacNvmCtxChanged( );
- EventRegionNvmCtxChanged( );
- return LORAMAC_STATUS_OK;
- }
- LoRaMacStatus_t LoRaMacMcChannelDelete( AddressIdentifier_t groupID )
- {
- if( ( MacCtx.MacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
- {
- return LORAMAC_STATUS_BUSY;
- }
- if( ( groupID >= LORAMAC_MAX_MC_CTX ) ||
- ( MacCtx.NvmCtx->MulticastChannelList[groupID].ChannelParams.IsEnabled == false ) )
- {
- return LORAMAC_STATUS_MC_GROUP_UNDEFINED;
- }
- McChannelParams_t channel;
- // Set all channel fields with 0
- memset1( ( uint8_t* )&channel, 0, sizeof( McChannelParams_t ) );
- MacCtx.NvmCtx->MulticastChannelList[groupID].ChannelParams = channel;
- EventMacNvmCtxChanged( );
- EventRegionNvmCtxChanged( );
- return LORAMAC_STATUS_OK;
- }
- uint8_t LoRaMacMcChannelGetGroupId( uint32_t mcAddress )
- {
- for( uint8_t i = 0; i < LORAMAC_MAX_MC_CTX; i++ )
- {
- if( mcAddress == MacCtx.NvmCtx->MulticastChannelList[i].ChannelParams.Address )
- {
- return i;
- }
- }
- return 0xFF;
- }
- LoRaMacStatus_t LoRaMacMcChannelSetupRxParams( AddressIdentifier_t groupID, McRxParams_t *rxParams, uint8_t *status )
- {
- *status = 0x1C + ( groupID & 0x03 );
- if( ( MacCtx.MacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
- {
- return LORAMAC_STATUS_BUSY;
- }
- DeviceClass_t devClass = MacCtx.NvmCtx->MulticastChannelList[groupID].ChannelParams.Class;
- if( ( devClass == CLASS_A ) || ( devClass > CLASS_C ) )
- {
- return LORAMAC_STATUS_PARAMETER_INVALID;
- }
- if( ( groupID >= LORAMAC_MAX_MC_CTX ) ||
- ( MacCtx.NvmCtx->MulticastChannelList[groupID].ChannelParams.IsEnabled == false ) )
- {
- return LORAMAC_STATUS_MC_GROUP_UNDEFINED;
- }
- *status &= 0x0F; // groupID OK
- VerifyParams_t verify;
- // Check datarate
- if( devClass == CLASS_B )
- {
- verify.DatarateParams.Datarate = rxParams->ClassB.Datarate;
- }
- else
- {
- verify.DatarateParams.Datarate = rxParams->ClassC.Datarate;
- }
- verify.DatarateParams.DownlinkDwellTime = MacCtx.NvmCtx->MacParams.DownlinkDwellTime;
- if( RegionVerify( MacCtx.NvmCtx->Region, &verify, PHY_RX_DR ) == true )
- {
- *status &= 0xFB; // datarate OK
- }
- // Check frequency
- if( devClass == CLASS_B )
- {
- verify.Frequency = rxParams->ClassB.Frequency;
- }
- else
- {
- verify.Frequency = rxParams->ClassC.Frequency;
- }
- if( RegionVerify( MacCtx.NvmCtx->Region, &verify, PHY_FREQUENCY ) == true )
- {
- *status &= 0xF7; // frequency OK
- }
- if( *status == ( groupID & 0x03 ) )
- {
- // Apply parameters
- MacCtx.NvmCtx->MulticastChannelList[groupID].ChannelParams.RxParams = *rxParams;
- }
- EventMacNvmCtxChanged( );
- EventRegionNvmCtxChanged( );
- return LORAMAC_STATUS_OK;
- }
- LoRaMacStatus_t LoRaMacMlmeRequest( MlmeReq_t* mlmeRequest )
- {
- LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN;
- MlmeConfirmQueue_t queueElement;
- uint8_t macCmdPayload[2] = { 0x00, 0x00 };
- if( mlmeRequest == NULL )
- {
- return LORAMAC_STATUS_PARAMETER_INVALID;
- }
- if( LoRaMacIsBusy( ) == true )
- {
- return LORAMAC_STATUS_BUSY;
- }
- if( LoRaMacConfirmQueueIsFull( ) == true )
- {
- return LORAMAC_STATUS_BUSY;
- }
- if( LoRaMacConfirmQueueGetCnt( ) == 0 )
- {
- memset1( ( uint8_t* ) &MacCtx.MlmeConfirm, 0, sizeof( MacCtx.MlmeConfirm ) );
- }
- MacCtx.MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
- MacCtx.MacFlags.Bits.MlmeReq = 1;
- queueElement.Request = mlmeRequest->Type;
- queueElement.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
- queueElement.RestrictCommonReadyToHandle = false;
- switch( mlmeRequest->Type )
- {
- case MLME_JOIN:
- {
- if( ( MacCtx.MacState & LORAMAC_TX_DELAYED ) == LORAMAC_TX_DELAYED )
- {
- return LORAMAC_STATUS_BUSY;
- }
- ResetMacParameters( );
- MacCtx.NvmCtx->MacParams.ChannelsDatarate = RegionAlternateDr( MacCtx.NvmCtx->Region, mlmeRequest->Req.Join.Datarate, ALTERNATE_DR );
- queueElement.Status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL;
- status = SendReJoinReq( JOIN_REQ );
- if( status != LORAMAC_STATUS_OK )
- {
- // Revert back the previous datarate ( mainly used for US915 like regions )
- MacCtx.NvmCtx->MacParams.ChannelsDatarate = RegionAlternateDr( MacCtx.NvmCtx->Region, mlmeRequest->Req.Join.Datarate, ALTERNATE_DR_RESTORE );
- }
- break;
- }
- case MLME_LINK_CHECK:
- {
- // LoRaMac will send this command piggy-pack
- status = LORAMAC_STATUS_OK;
- if( LoRaMacCommandsAddCmd( MOTE_MAC_LINK_CHECK_REQ, macCmdPayload, 0 ) != LORAMAC_COMMANDS_SUCCESS )
- {
- status = LORAMAC_STATUS_MAC_COMMAD_ERROR;
- }
- break;
- }
- case MLME_TXCW:
- {
- status = SetTxContinuousWave( mlmeRequest->Req.TxCw.Timeout );
- break;
- }
- case MLME_TXCW_1:
- {
- status = SetTxContinuousWave1( mlmeRequest->Req.TxCw.Timeout, mlmeRequest->Req.TxCw.Frequency, mlmeRequest->Req.TxCw.Power );
- break;
- }
- case MLME_DEVICE_TIME:
- {
- // LoRaMac will send this command piggy-pack
- status = LORAMAC_STATUS_OK;
- if( LoRaMacCommandsAddCmd( MOTE_MAC_DEVICE_TIME_REQ, macCmdPayload, 0 ) != LORAMAC_COMMANDS_SUCCESS )
- {
- status = LORAMAC_STATUS_MAC_COMMAD_ERROR;
- }
- break;
- }
- case MLME_PING_SLOT_INFO:
- {
- if( MacCtx.NvmCtx->DeviceClass == CLASS_A )
- {
- uint8_t value = mlmeRequest->Req.PingSlotInfo.PingSlot.Value;
- // LoRaMac will send this command piggy-pack
- LoRaMacClassBSetPingSlotInfo( mlmeRequest->Req.PingSlotInfo.PingSlot.Fields.Periodicity );
- macCmdPayload[0] = value;
- status = LORAMAC_STATUS_OK;
- if( LoRaMacCommandsAddCmd( MOTE_MAC_PING_SLOT_INFO_REQ, macCmdPayload, 1 ) != LORAMAC_COMMANDS_SUCCESS )
- {
- status = LORAMAC_STATUS_MAC_COMMAD_ERROR;
- }
- }
- break;
- }
- case MLME_BEACON_TIMING:
- {
- // LoRaMac will send this command piggy-pack
- status = LORAMAC_STATUS_OK;
- if( LoRaMacCommandsAddCmd( MOTE_MAC_BEACON_TIMING_REQ, macCmdPayload, 0 ) != LORAMAC_COMMANDS_SUCCESS )
- {
- status = LORAMAC_STATUS_MAC_COMMAD_ERROR;
- }
- break;
- }
- case MLME_BEACON_ACQUISITION:
- {
- // Apply the request
- queueElement.RestrictCommonReadyToHandle = true;
- if( LoRaMacClassBIsAcquisitionInProgress( ) == false )
- {
- // Start class B algorithm
- LoRaMacClassBSetBeaconState( BEACON_STATE_ACQUISITION );
- LoRaMacClassBBeaconTimerEvent( NULL );
- status = LORAMAC_STATUS_OK;
- }
- else
- {
- status = LORAMAC_STATUS_BUSY;
- }
- break;
- }
- default:
- break;
- }
- if( status != LORAMAC_STATUS_OK )
- {
- if( LoRaMacConfirmQueueGetCnt( ) == 0 )
- {
- MacCtx.NodeAckRequested = false;
- MacCtx.MacFlags.Bits.MlmeReq = 0;
- }
- }
- else
- {
- LoRaMacConfirmQueueAdd( &queueElement );
- EventMacNvmCtxChanged( );
- }
- return status;
- }
- LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t* mcpsRequest )
- {
- GetPhyParams_t getPhy;
- PhyParam_t phyParam;
- LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN;
- LoRaMacHeader_t macHdr;
- VerifyParams_t verify;
- uint8_t fPort = 0;
- void* fBuffer;
- uint16_t fBufferSize;
- int8_t datarate = DR_0;
- bool readyToSend = false;
- if( mcpsRequest == NULL )
- {
- return LORAMAC_STATUS_PARAMETER_INVALID;
- }
- if( LoRaMacIsBusy( ) == true )
- {
- return LORAMAC_STATUS_BUSY;
- }
- macHdr.Value = 0;
- memset1( ( uint8_t* ) &MacCtx.McpsConfirm, 0, sizeof( MacCtx.McpsConfirm ) );
- MacCtx.McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
- // AckTimeoutRetriesCounter must be reset every time a new request (unconfirmed or confirmed) is performed.
- MacCtx.AckTimeoutRetriesCounter = 1;
- switch( mcpsRequest->Type )
- {
- case MCPS_UNCONFIRMED:
- {
- readyToSend = true;
- MacCtx.AckTimeoutRetries = 1;
- macHdr.Bits.MType = FRAME_TYPE_DATA_UNCONFIRMED_UP;
- fPort = mcpsRequest->Req.Unconfirmed.fPort;
- fBuffer = mcpsRequest->Req.Unconfirmed.fBuffer;
- fBufferSize = mcpsRequest->Req.Unconfirmed.fBufferSize;
- datarate = mcpsRequest->Req.Unconfirmed.Datarate;
- break;
- }
- case MCPS_CONFIRMED:
- {
- readyToSend = true;
- MacCtx.AckTimeoutRetries = MIN( mcpsRequest->Req.Confirmed.NbTrials, MAX_ACK_RETRIES );
- macHdr.Bits.MType = FRAME_TYPE_DATA_CONFIRMED_UP;
- fPort = mcpsRequest->Req.Confirmed.fPort;
- fBuffer = mcpsRequest->Req.Confirmed.fBuffer;
- fBufferSize = mcpsRequest->Req.Confirmed.fBufferSize;
- datarate = mcpsRequest->Req.Confirmed.Datarate;
- break;
- }
- case MCPS_PROPRIETARY:
- {
- readyToSend = true;
- MacCtx.AckTimeoutRetries = 1;
- macHdr.Bits.MType = FRAME_TYPE_PROPRIETARY;
- fBuffer = mcpsRequest->Req.Proprietary.fBuffer;
- fBufferSize = mcpsRequest->Req.Proprietary.fBufferSize;
- datarate = mcpsRequest->Req.Proprietary.Datarate;
- break;
- }
- default:
- break;
- }
- // Get the minimum possible datarate
- getPhy.Attribute = PHY_MIN_TX_DR;
- getPhy.UplinkDwellTime = MacCtx.NvmCtx->MacParams.UplinkDwellTime;
- phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- // Apply the minimum possible datarate.
- // Some regions have limitations for the minimum datarate.
- datarate = MAX( datarate, ( int8_t )phyParam.Value );
- if( readyToSend == true )
- {
- if( MacCtx.NvmCtx->AdrCtrlOn == false )
- {
- verify.DatarateParams.Datarate = datarate;
- verify.DatarateParams.UplinkDwellTime = MacCtx.NvmCtx->MacParams.UplinkDwellTime;
- if( RegionVerify( MacCtx.NvmCtx->Region, &verify, PHY_TX_DR ) == true )
- {
- MacCtx.NvmCtx->MacParams.ChannelsDatarate = verify.DatarateParams.Datarate;
- }
- else
- {
- return LORAMAC_STATUS_PARAMETER_INVALID;
- }
- }
- status = Send( &macHdr, fPort, fBuffer, fBufferSize );
- if( status == LORAMAC_STATUS_OK )
- {
- MacCtx.McpsConfirm.McpsRequest = mcpsRequest->Type;
- MacCtx.MacFlags.Bits.McpsReq = 1;
- }
- else
- {
- MacCtx.NodeAckRequested = false;
- }
- }
- EventMacNvmCtxChanged( );
- return status;
- }
- void LoRaMacTestSetDutyCycleOn( bool enable )
- {
- VerifyParams_t verify;
- verify.DutyCycle = enable;
- if( RegionVerify( MacCtx.NvmCtx->Region, &verify, PHY_DUTY_CYCLE ) == true )
- {
- MacCtx.NvmCtx->DutyCycleOn = enable;
- }
- }
|