deca_device.c 125 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862
  1. /*! ------------------------------------------------------------------------------------------------------------------
  2. * @file deca_device.c
  3. * @brief DecaWave device configuration and control functions
  4. *
  5. * @attention
  6. *
  7. * Copyright 2015 (c) DecaWave Ltd, Dublin, Ireland.
  8. *
  9. * All rights reserved.
  10. *
  11. */
  12. #include "deca_types.h"
  13. #include "deca_param_types.h"
  14. #include "deca_regs.h"
  15. #include "deca_device_api.h"
  16. #include "port.h"
  17. // Defines for enable_clocks function
  18. #define FORCE_SYS_XTI 0
  19. #define ENABLE_ALL_SEQ 1
  20. #define FORCE_SYS_PLL 2
  21. #define READ_ACC_ON 7
  22. #define READ_ACC_OFF 8
  23. #define FORCE_OTP_ON 11
  24. #define FORCE_OTP_OFF 12
  25. #define FORCE_TX_PLL 13
  26. // #define DWT_API_ERROR_CHECK // define so API checks config input parameters
  27. // -------------------------------------------------------------------------------------------------------------------
  28. //
  29. // Internal functions for controlling and configuring the device
  30. //
  31. // -------------------------------------------------------------------------------------------------------------------
  32. // Enable and Configure specified clocks
  33. void _dwt_enableclocks(int clocks) ;
  34. // Configure the ucode (FP algorithm) parameters
  35. void _dwt_configlde(int prf);
  36. // load ucode from OTP/ROM
  37. int _dwt_loaducodefromrom(void);
  38. //read non-volatile memory
  39. uint32_t _dwt_otpread(uint32_t address);
  40. //program the non-volatile memory
  41. uint32_t _dwt_otpprogword32(uint32_t data, uint16_t address);
  42. //upload the device configuration into always on memory
  43. void _dwt_aonarrayupload(void);
  44. uint32_t _dwt_otpsetmrregs(int mode);
  45. void _dwt_aonconfigupload(void);
  46. void _dwt_disablesequencing(void);
  47. // -------------------------------------------------------------------------------------------------------------------
  48. /*!
  49. * Static data for DW1000 DecaWave Transceiver control
  50. */
  51. // -------------------------------------------------------------------------------------------------------------------
  52. // structure to hold device data
  53. #pragma pack(4)
  54. typedef struct
  55. {
  56. uint32_t deviceID ;
  57. uint32_t partID ;
  58. uint32_t lotID ;
  59. uint8_t chan; // added chan here - used in the reading of acc
  60. uint8_t longFrames ; // flag in non-standard long frame mode
  61. uint8_t otprev ; // OTP revision number (read during initialisation)
  62. uint32_t txFCTRL ; // keep TX_FCTRL register config
  63. uint16_t rfrxDly; // rf delay (delay though the RF blocks before the signal comes out of the antenna i.e. "antenna delay")
  64. uint16_t rftxDly; // rf delay (delay though the RF blocks before the signal comes out of the antenna i.e. "antenna delay")
  65. uint32_t antennaDly; // antenna delay read from OTP 64 PRF value is in high 16 bits and 16M PRF in low 16 bits
  66. uint32_t antennaCals[4]; // antenna delays for the TREKs (Anchor high 16-bits, Tag low 16-bits)
  67. uint8_t xtrim; // xtrim value read from OTP
  68. uint8_t dblbuffon; // double rx buffer mode flag
  69. uint32_t sysCFGreg ; // local copy of system config register
  70. uint32_t txPowCfg[12]; // stores the Tx power configuration read from OTP (6 channels consecutively with PRF16 then 64, e.g. Ch 1 PRF16 is index 0 and 64 index 1)
  71. dwt_callback_data_t cdata; // callback data structure
  72. uint32_t states[3] ; //MP workaround debug states register
  73. uint8_t statescount ;
  74. uint8_t wait4resp ; //wait 4 response was set with last TX start command
  75. int prfIndex ;
  76. uint32_t ldoTune ; //low 32 bits of LDO tune value
  77. //void (*dwt_txcallback)(const dwt_callback_data_t *txd);
  78. //void (*dwt_rxcallback)(const dwt_callback_data_t *rxd);
  79. dwt_rxtxhandler dwt_txcallback;
  80. dwt_rxtxhandler dwt_rxcallback;
  81. } dwt_local_data_t ;
  82. #pragma pack()
  83. static volatile dwt_local_data_t dw1000local ; // Static local device data
  84. /*! ------------------------------------------------------------------------------------------------------------------
  85. * @fn dwt_initialise()
  86. *
  87. * @brief This function initiates communications with the DW1000 transceiver
  88. * and reads its DEV_ID register (address 0x00) to verify the IC is one supported
  89. * by this software (e.g. DW1000 32-bit device ID value is 0xDECA0130). Then it
  90. * does any initial once only device configurations needed for use and initialises
  91. * as necessary any static data items belonging to this low-level driver.
  92. *
  93. * NOTES:
  94. * 1.this function needs to be run before dwt_configuresleep, also the SPI freq has to be < 3MHz
  95. * 2.it also reads any calibration data from OTP memory as specified by the input paramter
  96. *
  97. * input parameters
  98. * @param config - specifies what configuration to load form OTP memory
  99. * DWT_LOADUCODE 0x800 - load the LDE micro-code from ROM - enabled accurate RX timestamp
  100. * DWT_LOADTXCONFIG 0x4 - load the TX power values
  101. * DWT_LOADANTDLY 0x2 - load the antenna delay values
  102. * DWT_LOADXTALTRIM 0x1 - load XTAL trim values
  103. * DWT_LOADNONE 0x0 - do not load any values from OTP memory
  104. *
  105. * output parameters
  106. *
  107. * returns DWT_DECA_SUCCESS for success, or DWT_DECA_ERROR for error
  108. */
  109. //OTP addresses definitions
  110. #define LDOTUNE_ADDRESS (0x04)
  111. #define PARTID_ADDRESS (0x06)
  112. #define LOTID_ADDRESS (0x07)
  113. #define VBAT_ADDRESS (0x08)
  114. #define VTEMP_ADDRESS (0x09)
  115. #define TXCFG_ADDRESS (0x10)
  116. #define ANTDLY_ADDRESS (0x1C)
  117. #define XTRIM_ADDRESS (0x1E)
  118. #define TREK_ANTDLY_1 (0xD)
  119. #define TREK_ANTDLY_2 (0xE)
  120. #define TREK_ANTDLY_3 (0xF)
  121. #define TREK_ANTDLY_4 (0x1D)
  122. int dwt_initialise(uint16_t config)
  123. {
  124. int i = 0;
  125. uint8_t plllockdetect = EC_CTRL_PLLLCK;
  126. uint16_t otp_addr = 0;
  127. dw1000local.statescount = 0;
  128. dw1000local.dblbuffon = 0; //double mode off by default
  129. dw1000local.prfIndex = 0; //16M
  130. dw1000local.cdata.aatset = 0;
  131. dw1000local.ldoTune = 0;
  132. dw1000local.wait4resp = 0;
  133. dw1000local.dwt_txcallback = NULL ;
  134. dw1000local.dwt_rxcallback = NULL ;
  135. dw1000local.deviceID = dwt_readdevid() ;
  136. // read and validate device ID return -1 if not recognized
  137. if (DWT_DEVICE_ID != dw1000local.deviceID) // MP IC ONLY (i.e. DW1000) FOR THIS CODE
  138. {
  139. return DWT_ERROR ;
  140. }
  141. _dwt_enableclocks(FORCE_SYS_XTI); //NOTE: set system clock to XTI - this is necessary to make sure the values read by _dwt_otpread are reliable
  142. //configure the CPLL lock detect
  143. dwt_writetodevice(EXT_SYNC_ID, EC_CTRL_OFFSET, 1, &plllockdetect); //
  144. //read OTP revision number
  145. otp_addr = _dwt_otpread(XTRIM_ADDRESS) & 0xffff; // Read 32 bit value, XTAL trim val is in low octet-0 (5 bits)
  146. dw1000local.otprev = (otp_addr >> 8) & 0xff; // OTP revision is next byte
  147. if(config & DWT_LOADLDOTUNE)
  148. {
  149. dw1000local.ldoTune = _dwt_otpread(LDOTUNE_ADDRESS);
  150. }
  151. if((dw1000local.ldoTune & 0xFF) != 0) //LDO tune values are stored in the OTP
  152. {
  153. uint8_t ldok = OTP_SF_LDO_KICK;
  154. //kick LDO tune
  155. dwt_writetodevice(OTP_IF_ID, OTP_SF, 1, &ldok); // set load LDE kick bit
  156. }
  157. else
  158. {
  159. dw1000local.ldoTune = 0;
  160. }
  161. dw1000local.partID = _dwt_otpread(PARTID_ADDRESS);
  162. dw1000local.lotID = _dwt_otpread(LOTID_ADDRESS);
  163. // Zero all antenna delay calibration values
  164. dw1000local.antennaDly = 0;
  165. for(i=0; i<4; i++)
  166. {
  167. dw1000local.antennaCals[i] = 0 ;
  168. }
  169. if(config & DWT_LOADANTDLY) // if we are loading antenna delays from OTP
  170. {
  171. if( dw1000local.otprev <= 1) // in revision 0, 1 of EVB1000/EVK1000
  172. {
  173. dw1000local.antennaDly = _dwt_otpread(ANTDLY_ADDRESS);
  174. }
  175. else if(dw1000local.otprev <= 3) // i.e. OTP version is 2 or 3 it is calibrated for TREK use cases
  176. {
  177. //read antenna delays
  178. dw1000local.antennaCals[0] = _dwt_otpread(TREK_ANTDLY_1);
  179. dw1000local.antennaCals[1] = _dwt_otpread(TREK_ANTDLY_2);
  180. dw1000local.antennaCals[2] = _dwt_otpread(TREK_ANTDLY_3);
  181. dw1000local.antennaCals[3] = _dwt_otpread(TREK_ANTDLY_4);
  182. }
  183. }
  184. if(config & DWT_LOADXTALTRIM)
  185. {
  186. dw1000local.xtrim = otp_addr & 0x1F;
  187. if ( !dw1000local.xtrim )
  188. {
  189. dw1000local.xtrim = pll2calcfg & 0x1F ; // set to mid-range if no calibration value inside
  190. }
  191. }
  192. else
  193. {
  194. dw1000local.xtrim = pll2calcfg & 0x1F ; // set to mid-range default as described in UM 8.1.1 Calibration Method
  195. }
  196. if(config & DWT_LOADTXCONFIG)
  197. {
  198. for(i=0; i<12; i++)
  199. {
  200. dw1000local.txPowCfg[i] = _dwt_otpread(TXCFG_ADDRESS+i);
  201. }
  202. }
  203. else
  204. {
  205. for(i=0; i<12; i++)
  206. {
  207. dw1000local.txPowCfg[i] = 0;
  208. }
  209. }
  210. // load leading edge detect code
  211. if(config & DWT_LOADUCODE)
  212. {
  213. _dwt_loaducodefromrom();
  214. }
  215. else //should disable the LDERUN enable bit in 0x36, 0x4
  216. {
  217. uint16_t rega = dwt_read16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET+1) ;
  218. rega &= 0xFDFF ; //clear LDERUN bit
  219. dwt_write16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET+1, rega) ;
  220. }
  221. _dwt_enableclocks(ENABLE_ALL_SEQ); //enable clocks for sequencing
  222. //read system register / store local copy
  223. dw1000local.sysCFGreg = dwt_read32bitreg(SYS_CFG_ID) ; // read sysconfig register
  224. {
  225. uint32_t reg;
  226. // Set up MFIO
  227. reg = dwt_read32bitreg(GPIO_CTRL_ID);
  228. reg |= 0x00014000 ; //7 and 8 to mode - to be used with PA
  229. reg |= 0x00050000 ; //8 and 9 to mode - RX/TX testing
  230. dwt_write32bitreg(GPIO_CTRL_ID,reg);
  231. //disable fine grain sequencing - this is needed when using PA on the TX
  232. dwt_write16bitoffsetreg(PMSC_ID,PMSC_TXFINESEQ_OFFSET,PMSC_TXFINESEQ_DIS_MASK);
  233. }
  234. return DWT_SUCCESS ;
  235. } // end dwt_initialise()
  236. /*! ------------------------------------------------------------------------------------------------------------------
  237. * @fn dwt_getTREKOTPantennadelay()
  238. *
  239. * @brief This API function returns the antenna delay read from the OTP memory as part of device initialisation
  240. * Note: the antenna delay will only be read if dwt_initialise is called with DWT_LOADANTDLY bit set in the config parameter
  241. * The values of antenna delay are only valid for TREK use case modes.
  242. *
  243. * input parameters:
  244. * @param anchor - this is the mode (Tag or Anchor) if Tag set to 0, if Anchor set to 1
  245. * @param chan - this is the channel (1, 2, 3, 4, 5, 7)
  246. * @param datarate - this is the datarate DWT_BR_6M8, DWT_BR_110K or DWT_BR_850K
  247. *
  248. */
  249. uint16_t dwt_getTREKOTPantennadelay(uint8_t anchor, uint8_t chan, uint8_t datarate)
  250. {
  251. uint32_t dly = 0;
  252. // 32-bit antenna delay value previously read from OTP, high 16 bits is value for Anchor mode, low 16-bits for Tag mode
  253. switch(chan)
  254. {
  255. case 2:
  256. if(datarate == DWT_BR_6M8)
  257. dly = dw1000local.antennaCals[0];
  258. else if(datarate == DWT_BR_110K)
  259. dly = dw1000local.antennaCals[1];
  260. break;
  261. case 5:
  262. if(datarate == DWT_BR_6M8)
  263. dly = dw1000local.antennaCals[2];
  264. else if(datarate == DWT_BR_110K)
  265. dly = dw1000local.antennaCals[3];
  266. break;
  267. default:
  268. dly = 0;
  269. break;
  270. }
  271. return (dly >> (16*(anchor & 0x1))) & 0xFFFF;
  272. }
  273. /*! ------------------------------------------------------------------------------------------------------------------
  274. * Function: dwt_otprevision()
  275. *
  276. * Description: This is used to return the read OTP revision
  277. *
  278. * input parameters:
  279. *
  280. * output parameters:
  281. *
  282. * returns the read OTP revision value
  283. */
  284. uint8_t dwt_otprevision(void)
  285. {
  286. return dw1000local.otprev ;
  287. }
  288. /*! ------------------------------------------------------------------------------------------------------------------
  289. * @fn dwt_setGPIOforEXTTRX()
  290. *
  291. * @brief This is used to enable GPIO for external LNA or PA functionality - HW dependent, consult the DW1000 User Manual
  292. *
  293. * input parameters
  294. *
  295. * output parameters
  296. *
  297. * no return value
  298. */
  299. void dwt_setGPIOforEXTTRX(void)
  300. {
  301. uint8_t buf[GPIO_MODE_LEN];
  302. // Set the GPIO to control external PA/LNA
  303. dwt_readfromdevice(GPIO_CTRL_ID, GPIO_MODE_OFFSET, GPIO_MODE_LEN, buf);
  304. buf[GPIO_LNA_byte_no] |= (GPIO_PIN5_EXTTXE_8 + GPIO_PIN6_EXTRXE_8);
  305. dwt_writetodevice(GPIO_CTRL_ID, GPIO_MODE_OFFSET, GPIO_MODE_LEN, buf);
  306. }
  307. void dwt_setGPIOforEXTPA(void)
  308. {
  309. uint8_t buf[GPIO_MODE_LEN];
  310. // Set the GPIO to control external PA/LNA
  311. dwt_readfromdevice(GPIO_CTRL_ID, GPIO_MODE_OFFSET, GPIO_MODE_LEN, buf);
  312. buf[GPIO_PA_byte_no] |= (GPIO_PIN4_EXTPA_8);
  313. buf[GPIO_LNA_byte_no] |= (GPIO_PIN5_EXTTXE_8);
  314. dwt_writetodevice(GPIO_CTRL_ID, GPIO_MODE_OFFSET, GPIO_MODE_LEN, buf);
  315. }
  316. /*! ------------------------------------------------------------------------------------------------------------------
  317. * @fn dwt_setGPIOdirection()
  318. *
  319. * @brief This is used to set GPIO direction as an input (1) or output (0)
  320. *
  321. * input parameters
  322. * @param gpioNum - this is the GPIO to configure - see GxM0... GxM8 in the deca_regs.h file
  323. * @param direction - this sets the GPIO direction - see GxP0... GxP8 in the deca_regs.h file
  324. *
  325. * output parameters
  326. *
  327. * no return value
  328. */
  329. void dwt_setGPIOdirection(uint32_t gpioNum, uint32_t direction)
  330. {
  331. uint8_t buf[GPIO_DIR_LEN];
  332. uint32_t command = direction | gpioNum;
  333. buf[0] = command & 0xff;
  334. buf[1] = (command >> 8) & 0xff;
  335. buf[2] = (command >> 16) & 0xff;
  336. dwt_writetodevice(GPIO_CTRL_ID, GPIO_DIR_OFFSET, GPIO_DIR_LEN, buf);
  337. }
  338. /*! ------------------------------------------------------------------------------------------------------------------
  339. * @fn dwt_setGPIOvalue()
  340. *
  341. * @brief This is used to set GPIO value as (1) or (0) only applies if the GPIO is configured as output
  342. *
  343. * input parameters
  344. * @param gpioNum - this is the GPIO to configure - see GxM0... GxM8 in the deca_regs.h file
  345. * @param value - this sets the GPIO value - see GDP0... GDP8 in the deca_regs.h file
  346. *
  347. * output parameters
  348. *
  349. * no return value
  350. */
  351. void dwt_setGPIOvalue(uint32_t gpioNum, uint32_t value)
  352. {
  353. uint8_t buf[GPIO_DOUT_LEN];
  354. uint32_t command = value | gpioNum;
  355. buf[0] = command & 0xff;
  356. buf[1] = (command >> 8) & 0xff;
  357. buf[2] = (command >> 16) & 0xff;
  358. dwt_writetodevice(GPIO_CTRL_ID, GPIO_DOUT_OFFSET, GPIO_DOUT_LEN, buf);
  359. }
  360. /*! ------------------------------------------------------------------------------------------------------------------
  361. * @fn dwt_getldotune()
  362. *
  363. * @brief This is used to return the low 32 bits of the programmed LDO tune value of the device
  364. *
  365. * input parameters
  366. *
  367. * output parameters
  368. *
  369. * returns the 32 bit LDO tune value of the device as programmed in the factory
  370. */
  371. uint32_t dwt_getldotune(void)
  372. {
  373. return dw1000local.ldoTune;
  374. }
  375. /*! ------------------------------------------------------------------------------------------------------------------
  376. * @fn dwt_getpartid()
  377. *
  378. * @brief This is used to return the read part ID of the device
  379. *
  380. * input parameters
  381. *
  382. * output parameters
  383. *
  384. * returns the 32 bit part ID value as programmed in the factory
  385. */
  386. uint32_t dwt_getpartid(void)
  387. {
  388. return dw1000local.partID;
  389. }
  390. /*! ------------------------------------------------------------------------------------------------------------------
  391. * @fn dwt_getlotid()
  392. *
  393. * @brief This is used to return the read lot ID of the device
  394. *
  395. * input parameters
  396. *
  397. * output parameters
  398. *
  399. * returns the 32 bit lot ID value as programmed in the factory
  400. */
  401. uint32_t dwt_getlotid(void)
  402. {
  403. return dw1000local.lotID;
  404. }
  405. /*! ------------------------------------------------------------------------------------------------------------------
  406. * @fn dwt_readdevid()
  407. *
  408. * @brief This is used to return the read device tyoe and revision information of the DW1000 device (MP part is 0xDECA0130)
  409. *
  410. * input parameters:
  411. *
  412. * output parameters:
  413. *
  414. * returns the read value which for DW1000 is 0xDECA0130
  415. */
  416. uint32_t dwt_readdevid(void)
  417. {
  418. return dwt_read32bitoffsetreg(DEV_ID_ID,0);
  419. }
  420. /*! ------------------------------------------------------------------------------------------------------------------
  421. * @fn dwt_configuretxrf()
  422. *
  423. * @brief This function provides the API for the configuration of the TX spectrum
  424. * including the power and pulse generator delay. The input is a pointer to the data structure
  425. * of type dwt_txconfig_t that holds all the configurable items.
  426. *
  427. * input parameters
  428. * @param config - pointer to the txrf configuration structure, which contains the tx rf config data
  429. *
  430. * output parameters
  431. *
  432. * no return value
  433. *
  434. */
  435. void dwt_configuretxrf(dwt_txconfig_t *config)
  436. {
  437. //Config RF TX PG_DELAY
  438. dwt_writetodevice(TX_CAL_ID, TC_PGDELAY_OFFSET, 1, &config->PGdly);
  439. //Configure TX power
  440. dwt_write32bitreg(TX_POWER_ID, config->power);
  441. }
  442. /*! ------------------------------------------------------------------------------------------------------------------
  443. * @fn dwt_getotptxpower()
  444. *
  445. * @brief This API function returns the tx power value read from OTP memory as part of initialisation
  446. *
  447. * input parameters
  448. * @param prf - this is the PRF e.g. DWT_PRF_16M or DWT_PRF_64M
  449. * @param chan - this is the channel e.g. 1 to 7
  450. *
  451. * output parameters
  452. *
  453. * returns tx power value for a given PRF and channel
  454. */
  455. uint32_t dwt_getotptxpower(uint8_t prf, uint8_t chan)
  456. {
  457. return dw1000local.txPowCfg[(prf - DWT_PRF_16M) + (chan_idx[chan] * 2)];
  458. }
  459. /*! ------------------------------------------------------------------------------------------------------------------
  460. * @fn dwt_configure()
  461. *
  462. * @brief This function provides the main API for the configuration of the
  463. * DW1000 and this low-level driver. The input is a pointer to the data structure
  464. * of type dwt_config_t that holds all the configurable items.
  465. * The dwt_config_t structure shows which ones are supported
  466. *
  467. * input parameters
  468. * @param config - pointer to the configuration structure, which contains the device configuration data.
  469. * @param useotp - specifies what configuration (read form OTP memory as part of initialisation) to configure
  470. * DWT_LOADANTDLY 0x2 - load the antenna delay values
  471. * DWT_LOADXTALTRIM 0x1 - load XTAL trim values
  472. * DWT_LOADNONE 0x0 - do not load any values from OTP memory
  473. *
  474. * output parameters
  475. *
  476. * returns DWT_DECA_SUCCESS for success, or DWT_DECA_ERROR for error
  477. */
  478. int dwt_configure(dwt_config_t *config, uint8_t use_otpconfigvalues)
  479. {
  480. uint8_t nsSfd_result = 0;
  481. uint8_t useDWnsSFD = 0;
  482. uint8_t chan = config->chan ;
  483. uint32_t regval ;
  484. uint16_t reg16 = lde_replicaCoeff[config->rxCode];
  485. uint8_t prfIndex = dw1000local.prfIndex = config->prf - DWT_PRF_16M;
  486. uint8_t bw = ((chan == 4) || (chan == 7)) ? 1 : 0 ; //select wide or narrow band
  487. dw1000local.chan = config->chan ;
  488. #ifdef DWT_API_ERROR_CHECK
  489. if (config->dataRate > DWT_BR_6M8)
  490. {
  491. return DWT_ERROR ;
  492. }// validate datarate parameter
  493. if ((config->prf > DWT_PRF_64M) || (config->prf < DWT_PRF_16M))
  494. {
  495. return DWT_ERROR ; // validate Pulse Repetition Frequency
  496. }
  497. if (config->rxPAC > DWT_PAC64)
  498. {
  499. return DWT_ERROR ; // validate PAC size
  500. }
  501. if ((chan < 1) || (chan > 7) || (6 == chan))
  502. {
  503. return DWT_ERROR ; // validate channel number parameter
  504. }
  505. // validate TX and TX pre-amble codes selections
  506. if (config->prf == DWT_PRF_64M)
  507. {
  508. // at 64M PRF, codes should be 9 to 27 only
  509. // config->txCode
  510. // config->rxCode
  511. }
  512. else
  513. {
  514. // at 16M PRF, codes should be 0 to 8 only
  515. }
  516. switch (config->txPreambLength)
  517. {
  518. case DWT_PLEN_4096 :
  519. case DWT_PLEN_2048 :
  520. case DWT_PLEN_1536 :
  521. case DWT_PLEN_1024 :
  522. case DWT_PLEN_512 :
  523. case DWT_PLEN_256 :
  524. case DWT_PLEN_128 :
  525. case DWT_PLEN_64 : break ; // all okay
  526. default : return DWT_ERROR ; // not a good preamble length parameter
  527. }
  528. if(config->phrMode > DWT_PHRMODE_EXT)
  529. {
  530. return DWT_ERROR ;
  531. }
  532. #endif
  533. // for 110 kbps we need to special setup
  534. if(DWT_BR_110K == config->dataRate)
  535. {
  536. dw1000local.sysCFGreg |= SYS_CFG_RXM110K ;
  537. reg16 >>= 3; //div by 8
  538. }
  539. else
  540. {
  541. dw1000local.sysCFGreg &= (~SYS_CFG_RXM110K) ;
  542. }
  543. dw1000local.longFrames = config->phrMode ;
  544. dw1000local.sysCFGreg |= (SYS_CFG_PHR_MODE_11 & (config->phrMode << 16)) ;
  545. dwt_write32bitreg(SYS_CFG_ID,dw1000local.sysCFGreg) ;
  546. //write/set the lde_replicaCoeff
  547. dwt_write16bitoffsetreg(LDE_IF_ID, LDE_REPC_OFFSET, reg16 ) ;
  548. _dwt_configlde(prfIndex);
  549. // config RF pll (for a given channel)
  550. // configure PLL2/RF PLL block CFG
  551. dwt_writetodevice(FS_CTRL_ID, FS_PLLCFG_OFFSET, 5, &pll2_config[chan_idx[chan]][0]);
  552. //configure PLL2/RF PLL block CAL
  553. dwt_writetodevice(FS_CTRL_ID, FS_XTALT_OFFSET, 1, &pll2calcfg);
  554. // Configure RF RX blocks (for specified channel/badwidth)
  555. dwt_writetodevice(RF_CONF_ID, RF_RXCTRLH_OFFSET, 1, &rx_config[bw]);
  556. // Configure RF TX blocks (for specified channel and prf)
  557. //Config RF TX control
  558. dwt_write32bitoffsetreg(RF_CONF_ID, RF_TXCTRL_OFFSET, tx_config[chan_idx[chan]]);
  559. // Configure the baseband parameters (for specified prf, bit rate, pac, and SFD settings)
  560. //DTUNE0
  561. dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE0b_OFFSET, sftsh[config->dataRate][config->nsSFD]);
  562. //DTUNE1
  563. dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE1a_OFFSET, dtune1[prfIndex]);
  564. if(config->dataRate == DWT_BR_110K)
  565. {
  566. dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE1b_OFFSET, 0x64);
  567. }
  568. else
  569. {
  570. if(config->txPreambLength == DWT_PLEN_64) //if preamble length is 64
  571. {
  572. uint8_t temp = 0x10;
  573. dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE1b_OFFSET, 0x10);
  574. dwt_writetodevice(DRX_CONF_ID, 0x26, 1, &temp);
  575. }
  576. else
  577. {
  578. uint8_t temp = 0x28;
  579. dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE1b_OFFSET, 0x20);
  580. dwt_writetodevice(DRX_CONF_ID, 0x26, 1, &temp);
  581. }
  582. }
  583. //DTUNE2
  584. dwt_write32bitoffsetreg(DRX_CONF_ID, DRX_TUNE2_OFFSET, digital_bb_config[prfIndex][config->rxPAC]);
  585. //DTUNE3
  586. if(config->sfdTO != DWT_SFDTOC_DEF)
  587. { //if default value no need to program it
  588. dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_SFDTOC_OFFSET, config->sfdTO);
  589. }
  590. //don't allow 0 - SFD timeout will always be enabled
  591. if(config->sfdTO == 0)
  592. {
  593. dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_SFDTOC_OFFSET, DWT_SFDTOC_DEF);
  594. }
  595. // configure AGC parameters
  596. dwt_write32bitoffsetreg( AGC_CFG_STS_ID, 0xC, agc_config.lo32);
  597. dwt_write16bitoffsetreg( AGC_CFG_STS_ID, 0x4, agc_config.target[prfIndex]);
  598. // set (non-standard) user SFD for improved performance,
  599. if(config->nsSFD)
  600. {
  601. //Write non standard (DW) SFD length
  602. dwt_writetodevice(USR_SFD_ID,0x00,1,&dwnsSFDlen[config->dataRate]);
  603. nsSfd_result = 3 ;
  604. useDWnsSFD = 1 ;
  605. }
  606. regval = (CHAN_CTRL_TX_CHAN_MASK & (chan << CHAN_CTRL_TX_CHAN_SHIFT)) | // Transmit Channel
  607. (CHAN_CTRL_RX_CHAN_MASK & (chan << CHAN_CTRL_RX_CHAN_SHIFT)) | // Receive Channel
  608. (CHAN_CTRL_RXFPRF_MASK & (config->prf << CHAN_CTRL_RXFPRF_SHIFT)) | // RX PRF
  609. ((CHAN_CTRL_TNSSFD|CHAN_CTRL_RNSSFD) & (nsSfd_result << CHAN_CTRL_TNSSFD_SHIFT)) | // nsSFD enable RX&TX
  610. (CHAN_CTRL_DWSFD & (useDWnsSFD << CHAN_CTRL_DWSFD_SHIFT)) | // use DW nsSFD
  611. (CHAN_CTRL_TX_PCOD_MASK & (config->txCode << CHAN_CTRL_TX_PCOD_SHIFT)) | // TX Preamble Code
  612. (CHAN_CTRL_RX_PCOD_MASK & (config->rxCode << CHAN_CTRL_RX_PCOD_SHIFT)) ; // RX Preamble Code
  613. dwt_write32bitreg(CHAN_CTRL_ID,regval) ;
  614. // Set up TX Preamble Size and TX PRF
  615. // Set up TX Ranging Bit and Data Rate
  616. {
  617. uint32_t x = (config->txPreambLength | config->prf) << 16;
  618. dw1000local.txFCTRL = x | TX_FCTRL_TR | /* always set ranging bit !!! */
  619. (config->dataRate << TX_FCTRL_TXBR_SHFT) ;
  620. dwt_write32bitoffsetreg(TX_FCTRL_ID,0,dw1000local.txFCTRL) ;
  621. }
  622. if (use_otpconfigvalues & DWT_LOADXTALTRIM)
  623. {
  624. dwt_xtaltrim(dw1000local.xtrim);
  625. }
  626. if (use_otpconfigvalues & DWT_LOADANTDLY)
  627. {
  628. //put half of the antenna delay value into tx and half into rx
  629. dwt_setrxantennadelay(((dw1000local.antennaDly >> (16*prfIndex)) & 0xFFFF) >> 1);
  630. dwt_settxantennadelay(((dw1000local.antennaDly >> (16*prfIndex)) & 0xFFFF) >> 1);
  631. }
  632. return DWT_SUCCESS ;
  633. } // end dwt_configure()
  634. /*! ------------------------------------------------------------------------------------------------------------------
  635. * @fn dwt_setrxantennadelay()
  636. *
  637. * @brief This API function writes the antenna delay (in time units) to RX registers
  638. *
  639. * input parameters:
  640. * @param rxDelay - this is the total (RX) antenna delay value, which
  641. * will be programmed into the RX register
  642. *
  643. * output parameters
  644. *
  645. * no return value
  646. */
  647. void dwt_setrxantennadelay(uint16_t rxDelay)
  648. {
  649. // -------------------------------------------------------------------------------------------------------------------
  650. // set the antenna delay
  651. dw1000local.rfrxDly = rxDelay;
  652. dwt_write16bitoffsetreg(LDE_IF_ID,LDE_RXANTD_OFFSET,dw1000local.rfrxDly) ;
  653. }
  654. /*! ------------------------------------------------------------------------------------------------------------------
  655. * @fn dwt_settxantennadelay()
  656. *
  657. * @brief This API function writes the antenna delay (in time units) to TX registers
  658. *
  659. * input parameters:
  660. * @param txDelay - this is the total (TX) antenna delay value, which
  661. * will be programmed into the TX delay register
  662. *
  663. * output parameters
  664. *
  665. * no return value
  666. *
  667. */
  668. void dwt_settxantennadelay(uint16_t txDelay)
  669. {
  670. // -------------------------------------------------------------------------------------------------------------------
  671. // set the tx antenna delay for auto tx timestamp adjustment
  672. dw1000local.rftxDly = txDelay;
  673. dwt_write16bitoffsetreg(TX_ANTD_ID, 0x0, dw1000local.rftxDly) ;
  674. }
  675. /*! ------------------------------------------------------------------------------------------------------------------
  676. * @fn dwt_readantennadelay()
  677. *
  678. * @brief This API function returns the antenna delay read from the OTP memory as part of device initialisation
  679. * Note: the antenna delay will only be read if dwt_initialise is called with DWT_LOADANTDLY bit set in the config parameter
  680. *
  681. * input parameters:
  682. * @param prf - this is the PRF e.g. DWT_PRF_16M or DWT_PRF_64M
  683. *
  684. */
  685. uint16_t dwt_readantennadelay(uint8_t prf)
  686. {
  687. // 32-bit antenna delay value previously read from OTP, high 16 bits is value for 64 MHz PRF, low 16-bits for 16 MHz PRF
  688. return (dw1000local.antennaDly >> (16*(prf-DWT_PRF_16M))) & 0xFFFF;
  689. }
  690. /*! ------------------------------------------------------------------------------------------------------------------
  691. * @fn dwt_writetxdata()
  692. *
  693. * @brief This API function writes the supplied TX data into the DW1000's
  694. * TX buffer. The input parameters are the data length in bytes and a pointer
  695. * to those data bytes.
  696. *
  697. * input parameters
  698. * @param txFrameLength - This is the total frame length, including the two byte CRC.
  699. * Note: this is the length of TX message (including the 2 byte CRC) - max is 1023
  700. * standard PHR mode allows up to 127 bytes
  701. * if > 127 is programmed, DWT_PHRMODE_EXT needs to be set in the phrMode configuration
  702. * see dwt_configure function
  703. * @param txFrameBytes - Pointer to the user's buffer containing the data to send.
  704. * @param txBufferOffset - This specifies an offset in the DW1000's TX Buffer at which to start writing data.
  705. *
  706. * output parameters
  707. *
  708. * returns DWT_DECA_SUCCESS for success, or DWT_DECA_ERROR for error
  709. */
  710. #ifdef __GNUC__
  711. #pragma GCC optimize ("O3")
  712. #elif defined(__ICCARM__)
  713. #pragma optimize=speed high
  714. #endif
  715. int dwt_writetxdata(uint16_t txFrameLength, uint8_t *txFrameBytes, uint16_t txBufferOffset)
  716. {
  717. #ifdef DWT_API_ERROR_CHECK
  718. if (dw1000local.longFrames)
  719. {
  720. if (txFrameLength > 1023)
  721. {
  722. return DWT_ERROR ;
  723. }
  724. }
  725. else
  726. {
  727. if (txFrameLength > 127)
  728. {
  729. return DWT_ERROR ;
  730. }
  731. }
  732. if (txFrameLength < 2)
  733. {
  734. return DWT_ERROR ;
  735. }
  736. #endif
  737. if ((txBufferOffset + txFrameLength) > 1024)
  738. {
  739. return DWT_ERROR ;
  740. }
  741. // write the data to the IC TX buffer, (-2 bytes for auto generated CRC)
  742. dwt_writetodevice( TX_BUFFER_ID, txBufferOffset, txFrameLength-2, txFrameBytes) ;
  743. return DWT_SUCCESS ;
  744. } // end dwt_writetxdata()
  745. /*! ------------------------------------------------------------------------------------------------------------------
  746. * @fn dwt_writetxfctrl()
  747. *
  748. * @brief This API function configures the TX frame control register before the transmission of a frame
  749. *
  750. * input parameters:
  751. * @param txFrameLength - this is the length of TX message (including the 2 byte CRC) - max is 1023
  752. * NOTE: standard PHR mode allows up to 127 bytes
  753. * if > 127 is programmed, DWT_PHRMODE_EXT needs to be set in the phrMode configuration
  754. * see dwt_configure function
  755. * @param txBufferOffset - the offset in the tx buffer to start writing the data
  756. *
  757. * output parameters
  758. *
  759. * returns DWT_DECA_SUCCESS for success, or DWT_DECA_ERROR for error
  760. *
  761. */
  762. #ifdef __GNUC__
  763. #pragma GCC optimize ("O3")
  764. #elif defined(__ICCARM__)
  765. #pragma optimize=speed high
  766. #endif
  767. int dwt_writetxfctrl(uint16_t txFrameLength, uint16_t txBufferOffset)
  768. {
  769. #ifdef DWT_API_ERROR_CHECK
  770. if (dw1000local.longFrames)
  771. {
  772. if (txFrameLength > 1023)
  773. {
  774. return DWT_ERROR ;
  775. }
  776. }
  777. else
  778. {
  779. if (txFrameLength > 127)
  780. {
  781. return DWT_ERROR ;
  782. }
  783. }
  784. if (txFrameLength < 2)
  785. {
  786. return DWT_ERROR ;
  787. }
  788. #endif
  789. // write the frame length to the TX frame control register
  790. // dw1000local.txFCTRL has kept configured bit rate information
  791. uint32_t reg32 = dw1000local.txFCTRL | txFrameLength | (txBufferOffset << 22);
  792. dwt_write32bitoffsetreg(TX_FCTRL_ID,0,reg32) ;
  793. return DWT_SUCCESS ;
  794. } // end dwt_writetxfctrl()
  795. /*! ------------------------------------------------------------------------------------------------------------------
  796. * @fn dwt_readrxdata()
  797. *
  798. * @brief This is used to read the data from the RX buffer, from an offset location give by offset paramter
  799. *
  800. * input parameters
  801. * @param buffer - the buffer into which the data will be read
  802. * @param length - the length of data to read (in bytes)
  803. * @param rxBufferOffset - the offset in the rx buffer from which to read the data
  804. *
  805. * output parameters
  806. *
  807. * no return value
  808. */
  809. #ifdef __GNUC__
  810. #pragma GCC optimize ("O3")
  811. #elif defined(__ICCARM__)
  812. #pragma optimize=speed high
  813. #endif
  814. void dwt_readrxdata(uint8_t *buffer, uint16_t length, uint16_t rxBufferOffset)
  815. {
  816. dwt_readfromdevice(RX_BUFFER_ID,rxBufferOffset,length,buffer) ;
  817. }
  818. /*! ------------------------------------------------------------------------------------------------------------------
  819. * @fn dwt_readaccdata()
  820. *
  821. * @brief This is used to read the data from the Accumulator buffer, from an offset location give by offset parameter
  822. *
  823. * input parameters
  824. * @param buffer - the buffer into which the data will be read
  825. * @param length - the length of data to read (in bytes)
  826. * @param accOffset - the offset in the acc buffer from which to read the data
  827. *
  828. * output parameters
  829. *
  830. * no return value
  831. */
  832. void dwt_readaccdata(uint8_t *buffer, uint16_t len, uint16_t accOffset)
  833. {
  834. // Force on the ACC clocks if we are sequenced
  835. _dwt_enableclocks(READ_ACC_ON);
  836. dwt_readfromdevice(ACC_MEM_ID,accOffset,len,buffer) ;
  837. _dwt_enableclocks(READ_ACC_OFF); //revert clocks back
  838. }
  839. /*! ------------------------------------------------------------------------------------------------------------------
  840. * @fn dwt_readdignostics()
  841. *
  842. * @brief @brief this function reads the rx signal quality diagnostic data
  843. *
  844. * input parameters
  845. * @param diagnostics - diagnostic structure pointer, this will contain the diagnostic data read from the DW1000
  846. *
  847. * output parameters
  848. *
  849. * no return value
  850. */
  851. void dwt_readdignostics(dwt_rxdiag_t *diagnostics)
  852. {
  853. uint8_t reg[2];
  854. uint16_t fp;
  855. dwt_readfromdevice(RX_TIME_ID, 5, 2, reg) ; //read the HW FP index
  856. //LDE result 0 is in bytes 40->55
  857. // convert (and save) hardware estimate to show on graph
  858. fp = reg[0];
  859. fp = fp + (reg[1] << 8);
  860. diagnostics->firstPath = (double) fp * (1.0/64.0) ;
  861. //LDE diagnostic data
  862. diagnostics->maxNoise = dwt_read16bitoffsetreg(LDE_IF_ID, LDE_THRESH_OFFSET);
  863. //read all 8 bytes in one SPI transaction
  864. dwt_readfromdevice(RX_FQUAL_ID, 0x0, 8, (uint8_t*)&diagnostics->stdNoise);
  865. //diagnostics->stdNoise = dwt_read16bitoffsetreg(RX_FQUAL_ID, 0x0) ;
  866. //diagnostics->firstPathAmp2 = dwt_read16bitoffsetreg(RX_FQUAL_ID, 0x2) ;
  867. //diagnostics->firstPathAmp3 = dwt_read16bitoffsetreg(RX_FQUAL_ID, 0x4) ;
  868. //diagnostics->maxGrowthCIR = dwt_read16bitoffsetreg(RX_FQUAL_ID, 0x6) ;
  869. diagnostics->firstPathAmp1 = dwt_read16bitoffsetreg(RX_TIME_ID, 0x7) ;
  870. diagnostics->rxPreamCount = (dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXPACC_MASK) >> RX_FINFO_RXPACC_SHIFT ;
  871. //diagnostics->debug1 = dwt_read32bitoffsetreg(0x27, 0x28);
  872. //diagnostics->debug2 = dwt_read32bitoffsetreg(0x27, 0xc);
  873. }
  874. /*! ------------------------------------------------------------------------------------------------------------------
  875. * @fn dwt_readtxtimestamp()
  876. *
  877. * @brief This is used to read the TX timestamp (adjusted with the programmed antenna delay)
  878. *
  879. * input parameters
  880. * @param timestamp - a pointer to a 5-byte buffer which will store the read TX timestamp time
  881. *
  882. * output parameters - the timestamp buffer will contain the value after the function call
  883. *
  884. * no return value
  885. */
  886. #ifdef __GNUC__
  887. #pragma GCC optimize ("O3")
  888. #elif defined(__ICCARM__)
  889. #pragma optimize=speed high
  890. #endif
  891. void dwt_readtxtimestamp(uint8_t * timestamp)
  892. {
  893. dwt_readfromdevice(TX_TIME_ID, 0, TX_TIME_TX_STAMP_LEN, timestamp) ; // read bytes directly into buffer
  894. }
  895. /*! ------------------------------------------------------------------------------------------------------------------
  896. * @fn dwt_readtxtimestamphi32()
  897. *
  898. * @brief This is used to read the high 32-bits of the TX timestamp (adjusted with the programmed antenna delay)
  899. *
  900. * input parameters
  901. *
  902. * output parameters
  903. *
  904. * returns high 32-bits of TX timestamp
  905. */
  906. #ifdef __GNUC__
  907. #pragma GCC optimize ("O3")
  908. #elif defined(__ICCARM__)
  909. #pragma optimize=speed high
  910. #endif
  911. uint32_t dwt_readtxtimestamphi32(void)
  912. {
  913. return dwt_read32bitoffsetreg(TX_TIME_ID, 1);
  914. }
  915. /*! ------------------------------------------------------------------------------------------------------------------
  916. * @fn dwt_readtxtimestamplo32()
  917. *
  918. * @brief This is used to read the low 32-bits of the TX timestamp (adjusted with the programmed antenna delay)
  919. *
  920. * input parameters
  921. *
  922. * output parameters
  923. *
  924. * returns low 32-bits of TX timestamp
  925. */
  926. #ifdef __GNUC__
  927. #pragma GCC optimize ("O3")
  928. #elif defined(__ICCARM__)
  929. #pragma optimize=speed high
  930. #endif
  931. uint32_t dwt_readtxtimestamplo32(void)
  932. {
  933. return dwt_read32bitoffsetreg(TX_TIME_ID, 0);
  934. }
  935. /*! ------------------------------------------------------------------------------------------------------------------
  936. * @fn dwt_readrxtimestamp()
  937. *
  938. * @brief This is used to read the RX timestamp (adjusted time of arrival)
  939. *
  940. * input parameters
  941. * @param timestamp - a pointer to a 5-byte buffer which will store the read RX timestamp time
  942. *
  943. * output parameters - the timestamp buffer will contain the value after the function call
  944. *
  945. * no return value
  946. */
  947. #ifdef __GNUC__
  948. #pragma GCC optimize ("O3")
  949. #elif defined(__ICCARM__)
  950. #pragma optimize=speed high
  951. #endif
  952. void dwt_readrxtimestamp(uint8_t * timestamp)
  953. {
  954. dwt_readfromdevice(RX_TIME_ID, 0, RX_TIME_RX_STAMP_LEN, timestamp) ; //get the adjusted time of arrival
  955. }
  956. /*! ------------------------------------------------------------------------------------------------------------------
  957. * @fn dwt_readrxtimestamphi32()
  958. *
  959. * @brief This is used to read the high 32-bits of the RX timestamp (adjusted with the programmed antenna delay)
  960. *
  961. * input parameters
  962. *
  963. * output parameters
  964. * uint32_t rxtimestamp (hi 32-bits of RX timestamp)
  965. */
  966. #ifdef __GNUC__
  967. #pragma GCC optimize ("O3")
  968. #elif defined(__ICCARM__)
  969. #pragma optimize=speed high
  970. #endif
  971. uint32_t dwt_readrxtimestamphi32(void)
  972. {
  973. return dwt_read32bitoffsetreg(RX_TIME_ID, 1);
  974. }
  975. /*! ------------------------------------------------------------------------------------------------------------------
  976. * @fn dwt_readrxtimestamplo32()
  977. *
  978. * @brief This is used to read the low 32-bits of the RX timestamp (adjusted with the programmed antenna delay)
  979. *
  980. * input parameters
  981. *
  982. * output parameters
  983. * uint32_t rxtimestamp (lo 32-bits of RX timestamp)
  984. */
  985. #ifdef __GNUC__
  986. #pragma GCC optimize ("O3")
  987. #elif defined(__ICCARM__)
  988. #pragma optimize=speed high
  989. #endif
  990. uint32_t dwt_readrxtimestamplo32(void)
  991. {
  992. return dwt_read32bitoffsetreg(RX_TIME_ID, 0);
  993. }
  994. /*! ------------------------------------------------------------------------------------------------------------------
  995. * @fn dwt_readsystimestamphi32()
  996. *
  997. * @brief This is used to read the high 32-bits of the system time
  998. *
  999. * input parameters
  1000. *
  1001. * output parameters
  1002. *
  1003. * returns high 32-bits of system time timestamp
  1004. */
  1005. #ifdef __GNUC__
  1006. #pragma GCC optimize ("O3")
  1007. #elif defined(__ICCARM__)
  1008. #pragma optimize=speed high
  1009. #endif
  1010. uint32_t dwt_readsystimestamphi32(void)
  1011. {
  1012. return dwt_read32bitoffsetreg(SYS_TIME_ID, 1);
  1013. }
  1014. /*! ------------------------------------------------------------------------------------------------------------------
  1015. * @fn dwt_readsystime()
  1016. *
  1017. * @brief This is used to read the system time
  1018. *
  1019. * input parameters
  1020. * @param timestamp - a pointer to a 5-byte buffer which will store the read system time
  1021. *
  1022. * output parameters
  1023. * @param timestamp - the timestamp buffer will contain the value after the function call
  1024. *
  1025. * returns
  1026. */
  1027. #ifdef __GNUC__
  1028. #pragma GCC optimize ("O3")
  1029. #elif defined(__ICCARM__)
  1030. #pragma optimize=speed high
  1031. #endif
  1032. void dwt_readsystime(uint8_t * timestamp)
  1033. {
  1034. dwt_readfromdevice(SYS_TIME_ID, 0, SYS_TIME_LEN, timestamp) ; //get the adjusted time of arrival
  1035. }
  1036. /*! ------------------------------------------------------------------------------------------------------------------
  1037. * @fn dwt_writetodevice()
  1038. *
  1039. * @brief this function is used to write to the DW1000 device registers
  1040. * Notes:
  1041. * 1. Firstly we create a header (the first byte is a header byte)
  1042. * a. check if sub index is used, if subindexing is used - set bit-6 to 1 to signify that the sub-index address follows the register index byte
  1043. * b. set bit-7 (or with 0x80) for write operation
  1044. * c. if extended sub address index is used (i.e. if index > 127) set bit-7 of the first sub-index byte following the first header byte
  1045. *
  1046. * 2. Write the header followed by the data bytes to the DW1000 device
  1047. *
  1048. *
  1049. * input parameters:
  1050. * @param recordNumber - ID of register file or buffer being accessed
  1051. * @param index - byte index into register file or buffer being accessed
  1052. * @param length - number of bytes being written
  1053. * @param buffer - pointer to buffer containing the 'length' bytes to be written
  1054. *
  1055. * output parameters
  1056. *
  1057. * returns DWT_DECA_SUCCESS for success, or DWT_DECA_ERROR for error
  1058. */
  1059. #ifdef __GNUC__
  1060. #pragma GCC optimize ("O3")
  1061. #elif defined(__ICCARM__)
  1062. #pragma optimize=speed high
  1063. #endif
  1064. int dwt_writetodevice
  1065. (
  1066. uint16_t recordNumber,
  1067. uint16_t index,
  1068. uint32_t length,
  1069. const uint8_t *buffer
  1070. )
  1071. {
  1072. uint8_t header[3] ; // buffer to compose header in
  1073. int cnt = 0; // counter for length of header
  1074. #ifdef DWT_API_ERROR_CHECK
  1075. if (recordNumber > 0x3F)
  1076. {
  1077. return DWT_ERROR ; // record number is limited to 6-bits.
  1078. }
  1079. #endif
  1080. // Write message header selecting WRITE operation and addresses as appropriate (this is one to three bytes long)
  1081. if (index == 0) // for index of 0, no sub-index is required
  1082. {
  1083. header[cnt++] = 0x80 | recordNumber ; // bit-7 is WRITE operation, bit-6 zero=NO sub-addressing, bits 5-0 is reg file id
  1084. }
  1085. else
  1086. {
  1087. #ifdef DWT_API_ERROR_CHECK
  1088. if (index > 0x7FFF)
  1089. {
  1090. return DWT_ERROR ; // index is limited to 15-bits.
  1091. }
  1092. if ((index + length)> 0x7FFF)
  1093. {
  1094. return DWT_ERROR ; // sub-addressable area is limited to 15-bits.
  1095. }
  1096. #endif
  1097. header[cnt++] = 0xC0 | recordNumber ; // bit-7 is WRITE operation, bit-6 one=sub-address follows, bits 5-0 is reg file id
  1098. if (index <= 127) // for non-zero index < 127, just a single sub-index byte is required
  1099. {
  1100. header[cnt++] = (uint8_t)index ; // bit-7 zero means no extension, bits 6-0 is index.
  1101. }
  1102. else
  1103. {
  1104. header[cnt++] = 0x80 | (uint8_t)(index) ; // bit-7 one means extended index, bits 6-0 is low seven bits of index.
  1105. header[cnt++] = (uint8_t) (index >> 7) ; // 8-bit value = high eight bits of index.
  1106. }
  1107. }
  1108. // write it to the SPI
  1109. return writetospi(cnt,header,length,buffer);
  1110. } // end dwt_writetodevice()
  1111. /*! ------------------------------------------------------------------------------------------------------------------
  1112. * @fn dwt_readfromdevice()
  1113. *
  1114. * @brief this function is used to read from the DW1000 device registers
  1115. * Notes:
  1116. * 1. Firstly we create a header (the first byte is a header byte)
  1117. * a. check if sub index is used, if subindexing is used - set bit-6 to 1 to signify that the sub-index address follows the register index byte
  1118. * b. set bit-7 (or with 0x80) for write operation
  1119. * c. if extended sub address index is used (i.e. if index > 127) set bit-7 of the first sub-index byte following the first header byte
  1120. *
  1121. * 2. Write the header followed by the data bytes to the DW1000 device
  1122. * 3. Store the read data in the input buffer
  1123. *
  1124. * input parameters:
  1125. * @param recordNumber - ID of register file or buffer being accessed
  1126. * @param index - byte index into register file or buffer being accessed
  1127. * @param length - number of bytes being read
  1128. * @param buffer - pointer to buffer in which to return the read data.
  1129. *
  1130. * output parameters
  1131. *
  1132. * @return DWT_DECA_SUCCESS for success, or DWT_DECA_ERROR for error
  1133. */
  1134. #ifdef __GNUC__
  1135. #pragma GCC optimize ("O3")
  1136. #elif defined(__ICCARM__)
  1137. #pragma optimize=speed high
  1138. #endif
  1139. int dwt_readfromdevice
  1140. (
  1141. uint16_t recordNumber,
  1142. uint16_t index,
  1143. uint32_t length,
  1144. uint8_t *buffer
  1145. )
  1146. {
  1147. uint8_t header[4] ; // buffer to compose header in
  1148. int cnt = 0; // counter for length of header
  1149. #ifdef DWT_API_ERROR_CHECK
  1150. if (recordNumber > 0x3F)
  1151. {
  1152. return DWT_ERROR ; // record number is limited to 6-bits.
  1153. }
  1154. #endif
  1155. // Write message header selecting READ operation and addresses as appropriate (this is one to three bytes long)
  1156. if (index == 0) // for index of 0, no sub-index is required
  1157. {
  1158. header[cnt++] = (uint8_t) recordNumber ; // bit-7 zero is READ operation, bit-6 zero=NO sub-addressing, bits 5-0 is reg file id
  1159. }
  1160. else
  1161. {
  1162. #ifdef DWT_API_ERROR_CHECK
  1163. if (index > 0x7FFF)
  1164. {
  1165. return DWT_ERROR ; // index is limited to 15-bits.
  1166. }
  1167. if ((index + length)> 0x7FFF)
  1168. {
  1169. return DWT_ERROR ; // sub-addressible area is limited to 15-bits.
  1170. }
  1171. #endif
  1172. header[cnt++] = (uint8_t)(0x40 | recordNumber) ; // bit-7 zero is READ operation, bit-6 one=sub-address follows, bits 5-0 is reg file id
  1173. if (index <= 127) // for non-zero index < 127, just a single sub-index byte is required
  1174. {
  1175. header[cnt++] = (uint8_t) index ; // bit-7 zero means no extension, bits 6-0 is index.
  1176. }
  1177. else
  1178. {
  1179. header[cnt++] = 0x80 | (uint8_t)(index) ; // bit-7 one means extended index, bits 6-0 is low seven bits of index.
  1180. header[cnt++] = (uint8_t) (index >> 7) ; // 8-bit value = high eight bits of index.
  1181. }
  1182. }
  1183. // do the read from the SPI
  1184. return readfromspi(cnt, header, length, buffer); // result is stored in the buffer
  1185. } // end dwt_readfromdevice()
  1186. /*! ------------------------------------------------------------------------------------------------------------------
  1187. * @fn dwt_read32bitoffsetreg()
  1188. *
  1189. * @brief this function is used to read 32-bit value from the DW1000 device registers
  1190. *
  1191. * input parameters:
  1192. * @param regFileID - ID of register file or buffer being accessed
  1193. * @param regOffset - the index into register file or buffer being accessed
  1194. *
  1195. * output parameters
  1196. *
  1197. * returns 32 bit register value (success), or DWT_DECA_ERROR for error
  1198. */
  1199. #ifdef __GNUC__
  1200. #pragma GCC optimize ("O3")
  1201. #elif defined(__ICCARM__)
  1202. #pragma optimize=speed high
  1203. #endif
  1204. uint32_t dwt_read32bitoffsetreg(int regFileID,int regOffset)
  1205. {
  1206. uint32_t regval = DWT_ERROR ;
  1207. int j ;
  1208. uint8_t buffer[4] ;
  1209. int result = dwt_readfromdevice(regFileID,regOffset,4,buffer); // read 4 bytes (32-bits) register into buffer
  1210. if(result == DWT_SUCCESS)
  1211. {
  1212. for (j = 3 ; j >= 0 ; j --)
  1213. {
  1214. regval = (regval << 8) + buffer[j] ; // sum
  1215. }
  1216. }
  1217. return regval ;
  1218. } // end dwt_read32bitoffsetreg()
  1219. /*! ------------------------------------------------------------------------------------------------------------------
  1220. * @fn dwt_read16bitoffsetreg()
  1221. *
  1222. * @brief this function is used to read 16-bit value from the DW1000 device registers
  1223. *
  1224. * input parameters:
  1225. * @param regFileID - ID of register file or buffer being accessed
  1226. * @param regOffset - the index into register file or buffer being accessed
  1227. *
  1228. * output parameters
  1229. *
  1230. * returns 16 bit register value (success), or DWT_DECA_ERROR for error
  1231. */
  1232. #ifdef __GNUC__
  1233. #pragma GCC optimize ("O3")
  1234. #elif defined(__ICCARM__)
  1235. #pragma optimize=speed high
  1236. #endif
  1237. uint16_t dwt_read16bitoffsetreg(int regFileID,int regOffset)
  1238. {
  1239. uint16_t regval = DWT_ERROR ;
  1240. uint8_t buffer[2] ;
  1241. int result = dwt_readfromdevice(regFileID,regOffset,2,buffer); // read 2 bytes (16-bits) register into buffer
  1242. if(result == DWT_SUCCESS)
  1243. {
  1244. regval = (buffer[1] << 8) + buffer[0] ; // sum
  1245. }
  1246. return regval ;
  1247. } // end dwt_read16bitoffsetreg()
  1248. /*! ------------------------------------------------------------------------------------------------------------------
  1249. * @fn dwt_write16bitoffsetreg()
  1250. *
  1251. * @brief this function is used to write 16-bit value to the DW1000 device registers
  1252. *
  1253. * input parameters:
  1254. * @param regFileID - ID of register file or buffer being accessed
  1255. * @param regOffset - the index into register file or buffer being accessed
  1256. * @param regval - the value to write
  1257. *
  1258. * output parameters
  1259. *
  1260. * returns DWT_DECA_SUCCESS for success, or DWT_DECA_ERROR for error
  1261. */
  1262. #ifdef __GNUC__
  1263. #pragma GCC optimize ("O3")
  1264. #elif defined(__ICCARM__)
  1265. #pragma optimize=speed high
  1266. #endif
  1267. int dwt_write16bitoffsetreg(int regFileID,int regOffset,uint16_t regval)
  1268. {
  1269. int reg;
  1270. uint8_t buffer[2] ;
  1271. buffer[0] = regval & 0xFF;
  1272. buffer[1] = regval >> 8 ;
  1273. reg = dwt_writetodevice(regFileID,regOffset,2,buffer);
  1274. return reg;
  1275. } // end dwt_write16bitoffsetreg()
  1276. /*! ------------------------------------------------------------------------------------------------------------------
  1277. * @fn dwt_write32bitoffsetreg()
  1278. *
  1279. * @brief this function is used to write 32-bit value to the DW1000 device registers
  1280. *
  1281. * input parameters:
  1282. * @param regFileID - ID of register file or buffer being accessed
  1283. * @param regOffset - the index into register file or buffer being accessed
  1284. * @param regval - the value to write
  1285. *
  1286. * output parameters
  1287. *
  1288. * returns DWT_DECA_SUCCESS for success, or DWT_DECA_ERROR for error
  1289. */
  1290. #ifdef __GNUC__
  1291. #pragma GCC optimize ("O3")
  1292. #elif defined(__ICCARM__)
  1293. #pragma optimize=speed high
  1294. #endif
  1295. int dwt_write32bitoffsetreg(int regFileID,int regOffset,uint32_t regval)
  1296. {
  1297. int j ;
  1298. int reg;
  1299. uint8_t buffer[4] ;
  1300. for ( j = 0 ; j < 4 ; j++ )
  1301. {
  1302. buffer[j] = regval & 0xff ;
  1303. regval >>= 8 ;
  1304. }
  1305. reg = dwt_writetodevice(regFileID,regOffset,4,buffer);
  1306. return reg;
  1307. } // end dwt_write32bitoffsetreg()
  1308. /*! ------------------------------------------------------------------------------------------------------------------
  1309. * @fn dwt_enableframefilter()
  1310. *
  1311. * @brief This is used to enable the frame filtering - (the default option is to
  1312. * accept any data and ack frames with correct destination address
  1313. *
  1314. * input parameters
  1315. * @param - bitmask - enables/disables the frame filtering options according to
  1316. * DWT_FF_NOTYPE_EN 0x000 no frame types allowed
  1317. * DWT_FF_COORD_EN 0x002 behave as coordinator (can receive frames with no destination address (PAN ID has to match))
  1318. * DWT_FF_BEACON_EN 0x004 beacon frames allowed
  1319. * DWT_FF_DATA_EN 0x008 data frames allowed
  1320. * DWT_FF_ACK_EN 0x010 ack frames allowed
  1321. * DWT_FF_MAC_EN 0x020 mac control frames allowed
  1322. * DWT_FF_RSVD_EN 0x040 reserved frame types allowed
  1323. *
  1324. * output parameters
  1325. *
  1326. * no return value
  1327. */
  1328. void dwt_enableframefilter(uint16_t enable)
  1329. {
  1330. uint32_t sysconfig = SYS_CFG_MASK & dwt_read32bitreg(SYS_CFG_ID) ; // read sysconfig register
  1331. if(enable)
  1332. {
  1333. //enable frame filtering and configure frame types
  1334. sysconfig &= ~(SYS_CFG_FF_ALL_EN); //clear all
  1335. sysconfig |= (enable & SYS_CFG_FF_ALL_EN) | SYS_CFG_FFE;
  1336. }
  1337. else
  1338. {
  1339. sysconfig &= ~(SYS_CFG_FFE);
  1340. }
  1341. dw1000local.sysCFGreg = sysconfig ;
  1342. dwt_write32bitreg(SYS_CFG_ID,sysconfig) ;
  1343. }
  1344. /*! ------------------------------------------------------------------------------------------------------------------
  1345. * @fn dwt_setpanid()
  1346. *
  1347. * @brief This is used to set the PAN ID
  1348. *
  1349. *
  1350. * input parameters
  1351. * @param panID - this is the PAN ID
  1352. *
  1353. * output parameters
  1354. *
  1355. * no return value
  1356. */
  1357. void dwt_setpanid(uint16_t panID)
  1358. {
  1359. // PAN ID is high 16 bits of register
  1360. dwt_write16bitoffsetreg(PANADR_ID, 2, panID) ; // set the value
  1361. }
  1362. /*! ------------------------------------------------------------------------------------------------------------------
  1363. * @fn dwt_setaddress16()
  1364. *
  1365. * @brief This is used to set 16-bit (short) address
  1366. *
  1367. *
  1368. * input parameters
  1369. * @param shortAddress - this sets the 16 bit short address
  1370. *
  1371. * output parameters
  1372. *
  1373. * no return value
  1374. */
  1375. void dwt_setaddress16(uint16_t shortAddress)
  1376. {
  1377. // short address into low 16 bits
  1378. dwt_write16bitoffsetreg(PANADR_ID, 0, shortAddress) ; // set the value
  1379. }
  1380. /*! ------------------------------------------------------------------------------------------------------------------
  1381. * @fn dwt_seteui()
  1382. *
  1383. * @brief This is used to set the EUI 64-bit (long) address
  1384. *
  1385. * input parameters
  1386. * @param eui64 - this is the pointer to a buffer that contains the 64bit address
  1387. *
  1388. * output parameters
  1389. *
  1390. * no return value
  1391. */
  1392. void dwt_seteui(uint8_t *eui64)
  1393. {
  1394. dwt_writetodevice(EUI_64_ID, 0x0, 8, eui64);
  1395. }
  1396. /*! ------------------------------------------------------------------------------------------------------------------
  1397. * @fn dwt_geteui()
  1398. *
  1399. * @brief This is used to get the EUI 64-bit from the DW1000
  1400. *
  1401. * input parameters
  1402. * @param eui64 - this is the pointer to a buffer that will contain the read 64-bit EUI value
  1403. *
  1404. * output parameters
  1405. *
  1406. * no return value
  1407. */
  1408. void dwt_geteui(uint8_t *eui64)
  1409. {
  1410. dwt_readfromdevice(EUI_64_ID, 0x0, 8, eui64);
  1411. }
  1412. //
  1413. // _dwt_otpread - function to read the OTP memory. Ensure that MR,MRa,MRb are reset to 0.
  1414. //
  1415. uint32_t _dwt_otpread(uint32_t address)
  1416. {
  1417. uint8_t buf[4];
  1418. uint32_t ret_data;
  1419. buf[1] = (address>>8) & 0xff;
  1420. buf[0] = address & 0xff;
  1421. // Write the address
  1422. dwt_writetodevice(OTP_IF_ID,OTP_ADDR,2,buf);
  1423. // Assert OTP Read (self clearing)
  1424. buf[0] = 0x03; // 0x03 for manual drive of OTP_READ
  1425. dwt_writetodevice(OTP_IF_ID,OTP_CTRL,1,buf);
  1426. buf[0] = 0x00; // Bit0 is not autoclearing, so clear it (Bit 1 is but we clear it anyway).
  1427. dwt_writetodevice(OTP_IF_ID,OTP_CTRL,1,buf);
  1428. // Read read data, available 40ns after rising edge of OTP_READ
  1429. ret_data=dwt_read32bitoffsetreg(OTP_IF_ID,OTP_RDAT);
  1430. // Return the 32bit of read data
  1431. return (ret_data);
  1432. }
  1433. // Configure the MR registers for initial programming (enable charge pump).
  1434. // Read margin is used to stress the read back from the
  1435. // programmed bit. In normal operation this is relaxed.
  1436. uint32_t _dwt_otpsetmrregs(int mode)
  1437. {
  1438. uint8_t rd_buf[4];
  1439. uint8_t wr_buf[4];
  1440. uint32_t mra=0,mrb=0,mr=0;
  1441. //printf("OTP SET MR: Setting MR,MRa,MRb for mode %2x\n",mode);
  1442. // For mode we will set the following:
  1443. // "0" : Reset all to 0x0: MRA=0x0000, MRB=0x0000, MR=0x0000
  1444. // "1" : Set for inital programming: MRA=0x9220, MRB=0x000E, MR=0x1024
  1445. // "2" : Set for soak programming: MRA=0x9220, MRB=0x0003, MR=0x1824
  1446. // "3" : High Vpp: MRA=0x9220, MRB=0x004E, MR=0x1824
  1447. // "4" : Low Read Margin: MRA=0x0000, MRB=0x000E, MR=0x0000
  1448. // "5" : Array Clean: MRA=0x0049, MRB=0x0003, MR=0x0024
  1449. // "4" : Very Low Read Margin: MRA=0x0000, MRB=0x000E, MR=0x0000
  1450. ///////////////////////////////////////////
  1451. // PROGRAMME MRA
  1452. // Set MRA, MODE_SEL
  1453. wr_buf[0] = 0x03;
  1454. dwt_writetodevice(OTP_IF_ID, OTP_CTRL+1,1,wr_buf);
  1455. // Load data
  1456. switch(mode&0x0f) {
  1457. case 0x0 :
  1458. mr =0x0000;
  1459. mra=0x0000;
  1460. mrb=0x0000;
  1461. break;
  1462. case 0x1 :
  1463. mr =0x1024;
  1464. mra=0x9220; // Enable CPP mon
  1465. mrb=0x000e;
  1466. break;
  1467. case 0x2 :
  1468. mr =0x1824;
  1469. mra=0x9220;
  1470. mrb=0x0003;
  1471. break;
  1472. case 0x3 :
  1473. mr =0x1824;
  1474. mra=0x9220;
  1475. mrb=0x004e;
  1476. break;
  1477. case 0x4 :
  1478. mr =0x0000;
  1479. mra=0x0000;
  1480. mrb=0x0003;
  1481. break;
  1482. case 0x5 :
  1483. mr =0x0024;
  1484. mra=0x0000;
  1485. mrb=0x0003;
  1486. break;
  1487. default :
  1488. // printf("OTP SET MR: ERROR : Invalid mode selected\n",mode);
  1489. break;
  1490. }
  1491. wr_buf[0] = mra & 0x00ff;
  1492. wr_buf[1] = (mra & 0xff00)>>8;
  1493. dwt_writetodevice(OTP_IF_ID, OTP_WDAT,2,wr_buf);
  1494. // Set WRITE_MR
  1495. wr_buf[0] = 0x08;
  1496. dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
  1497. // Wait?
  1498. // Set Clear Mode sel
  1499. wr_buf[0] = 0x02;
  1500. dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
  1501. // Set AUX update, write MR
  1502. wr_buf[0] = 0x88;
  1503. dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
  1504. // Clear write MR
  1505. wr_buf[0] = 0x80;
  1506. dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
  1507. // Clear AUX update
  1508. wr_buf[0] = 0x00;
  1509. dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
  1510. ///////////////////////////////////////////
  1511. // PROGRAM MRB
  1512. // Set SLOW, MRB, MODE_SEL
  1513. wr_buf[0] = 0x05;
  1514. dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
  1515. wr_buf[0] = mrb & 0x00ff;
  1516. wr_buf[1] = (mrb & 0xff00)>>8;
  1517. dwt_writetodevice(OTP_IF_ID, OTP_WDAT,2,wr_buf);
  1518. // Set WRITE_MR
  1519. wr_buf[0] = 0x08;
  1520. dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
  1521. // Wait?
  1522. // Set Clear Mode sel
  1523. wr_buf[0] = 0x04;
  1524. dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
  1525. // Set AUX update, write MR
  1526. wr_buf[0] = 0x88;
  1527. dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
  1528. // Clear write MR
  1529. wr_buf[0] = 0x80;
  1530. dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
  1531. // Clear AUX update
  1532. wr_buf[0] = 0x00;
  1533. dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
  1534. ///////////////////////////////////////////
  1535. // PROGRAM MR
  1536. // Set SLOW, MODE_SEL
  1537. wr_buf[0] = 0x01;
  1538. dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
  1539. // Load data
  1540. wr_buf[0] = mr & 0x00ff;
  1541. wr_buf[1] = (mr & 0xff00)>>8;
  1542. dwt_writetodevice(OTP_IF_ID, OTP_WDAT,2,wr_buf);
  1543. // Set WRITE_MR
  1544. wr_buf[0] = 0x08;
  1545. dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
  1546. // Wait?
  1547. Sleep(10);
  1548. // Set Clear Mode sel
  1549. wr_buf[0] = 0x00;
  1550. dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
  1551. // Read confirm mode writes.
  1552. //Set man override, MRA_SEL
  1553. wr_buf[0] = OTP_CTRL_OTPRDEN;
  1554. dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
  1555. wr_buf[0] = 0x02;
  1556. dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
  1557. //MRB_SEL
  1558. wr_buf[0] = 0x04;
  1559. dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
  1560. Sleep(100);
  1561. // Clear mode sel
  1562. wr_buf[0] = 0x00;
  1563. dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
  1564. // Clear MAN_OVERRIDE
  1565. wr_buf[0] = 0x00;
  1566. dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
  1567. Sleep(10);
  1568. if (((mode&0x0f) == 0x1)||((mode&0x0f) == 0x2))
  1569. {
  1570. // Read status register
  1571. dwt_readfromdevice(OTP_IF_ID, OTP_STAT,1,rd_buf);
  1572. }
  1573. return DWT_SUCCESS;
  1574. }
  1575. //
  1576. // _dwt_otpprogword32 - function to program the OTP memory. Ensure that MR,MRa,MRb are reset to 0.
  1577. // VNM Charge pump needs to be enabled(see _dwt_otpsetmrregs)
  1578. // Note the address is only 11 bits long.
  1579. uint32_t _dwt_otpprogword32(uint32_t data, uint16_t address)
  1580. {
  1581. uint8_t rd_buf[1];
  1582. uint8_t wr_buf[4];
  1583. uint8_t otp_done;
  1584. // Read status register
  1585. dwt_readfromdevice(OTP_IF_ID, OTP_STAT, 1, rd_buf);
  1586. if((rd_buf[0] & 0x02) != 0x02)
  1587. {
  1588. printf("OTP PROG 32: ERROR VPP NOT OK, programming will fail. Are MR/MRA/MRB set?\n");
  1589. return DWT_ERROR;
  1590. }
  1591. // Write the data
  1592. wr_buf[3] = (data>>24) & 0xff;
  1593. wr_buf[2] = (data>>16) & 0xff;
  1594. wr_buf[1] = (data>>8) & 0xff;
  1595. wr_buf[0] = data & 0xff;
  1596. dwt_writetodevice(OTP_IF_ID, OTP_WDAT, 4, wr_buf);
  1597. // Write the address [10:0]
  1598. wr_buf[1] = (address>>8) & 0x07;
  1599. wr_buf[0] = address & 0xff;
  1600. dwt_writetodevice(OTP_IF_ID, OTP_ADDR, 2, wr_buf);
  1601. // Enable Sequenced programming
  1602. wr_buf[0] = OTP_CTRL_OTPPROG;
  1603. dwt_writetodevice(OTP_IF_ID, OTP_CTRL, 1, wr_buf);
  1604. wr_buf[0] = 0x00; // And clear
  1605. dwt_writetodevice(OTP_IF_ID, OTP_CTRL, 1, wr_buf);
  1606. // WAIT for status to flag PRGM OK..
  1607. otp_done = 0;
  1608. while(otp_done == 0)
  1609. {
  1610. Sleep(1);
  1611. dwt_readfromdevice(OTP_IF_ID, OTP_STAT, 1, rd_buf);
  1612. if((rd_buf[0] & 0x01) == 0x01)
  1613. {
  1614. otp_done = 1;
  1615. }
  1616. }
  1617. return DWT_SUCCESS;
  1618. }
  1619. /*! ------------------------------------------------------------------------------------------------------------------
  1620. * @fn dwt_otpwriteandverify()
  1621. *
  1622. * @brief This is used to program 32-bit value into the DW1000 OTP memory.
  1623. *
  1624. * input parameters
  1625. * @param value - this is the 32-bit value to be progarmmed into OTP
  1626. * @param address - this is the 16-bit OTP address into which the 32-bit value is programmed
  1627. *
  1628. * output parameters
  1629. *
  1630. * returns DWT_DECA_SUCCESS for success, or DWT_DECA_ERROR for error
  1631. */
  1632. uint32_t dwt_otpwriteandverify(uint32_t value, uint16_t address)
  1633. {
  1634. int prog_ok = 0;
  1635. int retry = 0;
  1636. //firstly set the system clock to crystal
  1637. _dwt_enableclocks(FORCE_SYS_XTI); //set system clock to XTI
  1638. //
  1639. //!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!
  1640. //Set the supply to 3.7V
  1641. //
  1642. _dwt_otpsetmrregs(1); //set mode for programming
  1643. //for each value to program - the readback/chack is done couple of times to verify it has programmed successfully
  1644. while(prog_ok==0)
  1645. {
  1646. _dwt_otpprogword32(value, address);
  1647. if(_dwt_otpread(address) == value)
  1648. {
  1649. prog_ok = 1;
  1650. }
  1651. retry++;
  1652. if(retry==5)
  1653. {
  1654. prog_ok = 2;
  1655. }
  1656. }
  1657. //even if the above does not exit before retry reaches 5, the programming has probably been sucessful
  1658. _dwt_otpsetmrregs(4); //set mode for reading
  1659. if(_dwt_otpread(address) == value) //if this does not pass please check voltage supply on VDDIO
  1660. {
  1661. prog_ok = DWT_SUCCESS;
  1662. }
  1663. else
  1664. {
  1665. prog_ok = DWT_ERROR;
  1666. }
  1667. _dwt_otpsetmrregs(0); //setting OTP mode register for low RM read - resetting the device would be alternative
  1668. return prog_ok;
  1669. }
  1670. // upload always on array configuration
  1671. void _dwt_aonconfigupload(void)
  1672. {
  1673. uint8_t buf[1];
  1674. // Upload array
  1675. buf[0] = 0x04;
  1676. dwt_writetodevice(AON_ID,AON_CTRL_OFFSET,1,buf);
  1677. buf[0] = 0x00;
  1678. dwt_writetodevice(AON_ID,AON_CTRL_OFFSET,1,buf);
  1679. }
  1680. // upload always on array configuration and go to sleep
  1681. void _dwt_aonarrayupload(void)
  1682. {
  1683. uint8_t buf[1];
  1684. // Upload array
  1685. buf[0] = 0x00;
  1686. dwt_writetodevice(AON_ID,AON_CTRL_OFFSET,1,buf);
  1687. buf[0] = 0x02;
  1688. dwt_writetodevice(AON_ID,AON_CTRL_OFFSET,1,buf);
  1689. }
  1690. /*! ------------------------------------------------------------------------------------------------------------------
  1691. * @fn dwt_entersleep()
  1692. *
  1693. * @brief This function puts the device into deep sleep or sleep. dwt_configuredeepsleep should be called first
  1694. * to configure the sleep and on-wake/wakeup parameters
  1695. *
  1696. * input parameters
  1697. *
  1698. * output parameters
  1699. *
  1700. * no return value
  1701. */
  1702. void dwt_entersleep(void)
  1703. {
  1704. //copy config to AON - upload the new configuration
  1705. _dwt_aonarrayupload();
  1706. }
  1707. /*! ------------------------------------------------------------------------------------------------------------------
  1708. * @fn dwt_configuresleepcnt()
  1709. *
  1710. * @brief sets the sleep counter to new value, this function programs the high 16-bits of the 28-bit counter
  1711. *
  1712. * NOTE: this function needs to be run before dwt_configuresleep, also the SPI freq has to be < 3MHz
  1713. *
  1714. * input parameters
  1715. * @param sleepcnt - this it value of the sleep counter to program
  1716. *
  1717. * output parameters
  1718. *
  1719. * no return value
  1720. */
  1721. void dwt_configuresleepcnt(uint16_t sleepcnt)
  1722. {
  1723. uint8_t buf[2];
  1724. buf[0] = 0x01;
  1725. dwt_writetodevice(PMSC_ID,PMSC_CTRL0_OFFSET,1,buf);
  1726. buf[0] = 0;
  1727. dwt_writetodevice(AON_ID, AON_CFG0_OFFSET, 1, buf); //to make sure we don't accidentaly go to sleep
  1728. buf[0] = 0;
  1729. dwt_writetodevice(AON_ID, AON_CFG1_OFFSET, 1, buf);
  1730. //disable the sleep counter
  1731. _dwt_aonconfigupload();
  1732. //set new value
  1733. buf[0] = sleepcnt & 0xFF;
  1734. buf[1] = (sleepcnt >> 8) & 0xFF;
  1735. dwt_writetodevice(AON_ID, (AON_CFG0_OFFSET+2) , 2, buf);
  1736. _dwt_aonconfigupload();
  1737. //enable the sleep counter
  1738. buf[0] = 1;
  1739. dwt_writetodevice(AON_ID, AON_CFG1_OFFSET, 1, buf);
  1740. _dwt_aonconfigupload();
  1741. buf[0] = 0x00;
  1742. dwt_writetodevice(PMSC_ID,PMSC_CTRL0_OFFSET,1,buf);
  1743. }
  1744. /*! ------------------------------------------------------------------------------------------------------------------
  1745. * @fn dwt_calibratesleepcnt()
  1746. *
  1747. * @brief calibrates the local oscillator as its frequency can vary between 7 and 13kHz depending on temp and voltage
  1748. *
  1749. * NOTE: this function needs to be run before dwt_configuresleepcnt, so that we know what the counter units are
  1750. * returns the number of XTAL/2 cycles per low-power oscillator cycle
  1751. *
  1752. * To get LP OSC freq = (XTAL/2)/result = 19.2MHz/result
  1753. *
  1754. * input parameters
  1755. *
  1756. * output parameters
  1757. *
  1758. * no return value
  1759. */
  1760. uint16_t dwt_calibratesleepcnt(void)
  1761. {
  1762. uint8_t buf[2];
  1763. uint16_t result;
  1764. //enable cal of the sleep counter
  1765. buf[0] = 4;
  1766. dwt_writetodevice(AON_ID, AON_CFG1_OFFSET, 1, buf);
  1767. _dwt_aonconfigupload();
  1768. //disables the cal of the sleep counter
  1769. buf[0] = 0;
  1770. dwt_writetodevice(AON_ID, AON_CFG1_OFFSET, 1, buf);
  1771. _dwt_aonconfigupload();
  1772. buf[0] = 0x01;
  1773. dwt_writetodevice(PMSC_ID,PMSC_CTRL0_OFFSET,1,buf);
  1774. Sleep(1);
  1775. //read the number of XTAL/2 cycles one lposc cycle took.
  1776. // Set up address
  1777. buf[0] = 118;
  1778. dwt_writetodevice(AON_ID, AON_ADDR_OFFSET, 1,buf);
  1779. // Enable manual override
  1780. buf[0] = 0x80; // OVR EN
  1781. dwt_writetodevice(AON_ID, AON_CTRL_OFFSET, 1,buf);
  1782. // Read confirm data that was written
  1783. buf[0] = 0x88; // OVR EN, OVR_RD
  1784. dwt_writetodevice(AON_ID, AON_CTRL_OFFSET, 1,buf);
  1785. // Read back byte from AON
  1786. dwt_readfromdevice(AON_ID, AON_RDAT_OFFSET, 1,buf);
  1787. result = buf[0];
  1788. result = result << 8;
  1789. // Set up address
  1790. buf[0] = 117;
  1791. dwt_writetodevice(AON_ID, AON_ADDR_OFFSET, 1,buf);
  1792. // Enable manual override
  1793. buf[0] = 0x80; // OVR EN
  1794. dwt_writetodevice(AON_ID, AON_CTRL_OFFSET, 1,buf);
  1795. // Read confirm data that was written
  1796. buf[0] = 0x88; // OVR EN, OVR_RD
  1797. dwt_writetodevice(AON_ID, AON_CTRL_OFFSET, 1,buf);
  1798. // Read back byte from AON
  1799. dwt_readfromdevice(AON_ID, AON_RDAT_OFFSET, 1,buf);
  1800. result |= buf[0];
  1801. buf[0] = 0x00; // Disable OVR EN
  1802. dwt_writetodevice(AON_ID,AON_CTRL_OFFSET,1,buf);
  1803. buf[0] = 0x00;
  1804. dwt_writetodevice(PMSC_ID,PMSC_CTRL0_OFFSET,1,buf);
  1805. //returns the number of XTAL/2 cycles per one LP OSC cycle
  1806. //this can be converted into LP OSC freq by 19.2MHz/result
  1807. return result;
  1808. }
  1809. /*! ------------------------------------------------------------------------------------------------------------------
  1810. * @fn dwt_configuresleep()
  1811. *
  1812. * @brief configures the device for both DEEP_SLEEP and SLEEP modes, and on-wake mode
  1813. * I.e. before entering the sleep, the device should be programmed for TX or RX, then upon "waking up" the TX/RX settings
  1814. * will be preserved and the device can immediately perform the desired action TX/RX
  1815. *
  1816. * NOTE: e.g. Tag operation - after deep sleep, the device needs to just load the TX buffer and send the frame
  1817. *
  1818. *
  1819. * mode: the array and LDE code (OTP/ROM) and LDO tune, and set sleep persist
  1820. * DWT_LOADLDO 0x1000 - load LDO tune value from OTP
  1821. * DWT_LOADUCODE 0x0800 - load ucode from OTP
  1822. * DWT_PRESRV_SLEEP 0x0100 - preserve sleep
  1823. * DWT_LOADOPSET 0x0080 - load operating parameter set on wakeup
  1824. * DWT_CONFIG 0x0040 - download the AON array into the HIF (configuration download)
  1825. * DWT_LOADEUI 0x0008
  1826. * DWT_GOTORX 0x0002
  1827. * DWT_TANDV 0x0001
  1828. *
  1829. * wake: wake up parameters
  1830. * DWT_XTAL_EN 0x10 - keep XTAL running during sleep
  1831. * DWT_WAKE_SLPCNT 0x8 - wake up after sleep count
  1832. * DWT_WAKE_CS 0x4 - wake up on chip select
  1833. * DWT_WAKE_WK 0x2 - wake up on WAKEUP PIN
  1834. * DWT_SLP_EN 0x1 - enable sleep/deep sleep functionality
  1835. *
  1836. * input parameters
  1837. * @param mode - config on-wake parameters
  1838. * @param wake - config wake up parameters
  1839. *
  1840. * output parameters
  1841. *
  1842. * no return value
  1843. */
  1844. void dwt_configuresleep(uint16_t mode, uint8_t wake)
  1845. {
  1846. uint8_t buf[1];
  1847. dwt_write16bitoffsetreg(AON_ID, AON_WCFG_OFFSET, mode);
  1848. buf[0] = wake;
  1849. dwt_writetodevice(AON_ID, AON_CFG0_OFFSET, 1, buf);
  1850. }
  1851. void dwt_getsleepconfig(uint16_t* mode, uint8_t* wake)
  1852. {
  1853. *mode = dwt_read16bitoffsetreg(AON_ID, AON_WCFG_OFFSET);
  1854. dwt_readfromdevice(AON_ID, AON_CFG0_OFFSET, 1, wake);
  1855. }
  1856. /*! ------------------------------------------------------------------------------------------------------------------
  1857. * @fn dwt_entersleepaftertx(int enable)
  1858. *
  1859. * @brief sets the auto TX to sleep bit. This means that after a frame
  1860. * transmission the device will enter deep sleep mode. The dwt_setdeepsleep() function
  1861. * needs to be called before this to configure the on-wake settings
  1862. *
  1863. * NOTE: the IRQ line has to be low/inactive (i.e. no pending events)
  1864. *
  1865. * input parameters
  1866. * @param enable - 1 to configure the device to enter deep sleep after TX, 0 - disables the configuration
  1867. *
  1868. * output parameters
  1869. *
  1870. * no return value
  1871. */
  1872. void dwt_entersleepaftertx(int enable)
  1873. {
  1874. uint32_t reg = dwt_read32bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET);
  1875. //set the auto TX -> sleep bit
  1876. if(enable)
  1877. {
  1878. reg |= PMSC_CTRL1_ATXSLP;
  1879. }
  1880. else
  1881. {
  1882. reg &= ~(PMSC_CTRL1_ATXSLP);
  1883. }
  1884. dwt_write32bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET, reg);
  1885. }
  1886. /*! ------------------------------------------------------------------------------------------------------------------
  1887. * @fn dwt_spicswakeup()
  1888. *
  1889. * @brief wake up the device from sleep mode using the SPI read,
  1890. * the device will wake up on chip slect line going low if the line is held low for at least 600us
  1891. * NOTE: Alternatively the device can be woken up with WaKE_UP pin if configured for that operation
  1892. *
  1893. * input parameters
  1894. * @param buff - this is a pointer to the dummy buffer which will be used in the SPI read transaction used for the WAKE UP of the device
  1895. * @param length - this is the length of the dummy buffer
  1896. *
  1897. * output parameters
  1898. *
  1899. * returns DWT_DECA_SUCCESS for success, or DWT_DECA_ERROR for error
  1900. */
  1901. int dwt_spicswakeup(uint8_t *buff, uint16_t length)
  1902. {
  1903. if(dwt_readdevid() != DWT_DEVICE_ID) //device was in deep sleep (the first read fails)
  1904. {
  1905. //need to keep chip select line low for at least 600us
  1906. dwt_readfromdevice(0x0, 0x0, length, buff); //do a long read to wake up the chip (hold the chip select low) (@3M, 100 ~= 272us, 200 ~= 540us)
  1907. //need 5ms for XTAL to start and stabilise (could wait for PLL lock IRQ status bit !!!)
  1908. //NOTE: Polling of the STATUS register is not possible unless freq is < 3MHz
  1909. Sleep(5);
  1910. }
  1911. else
  1912. {
  1913. return DWT_SUCCESS;
  1914. }
  1915. //DEBUG - check if still in sleep mode
  1916. if(dwt_readdevid() != DWT_DEVICE_ID)
  1917. {
  1918. return DWT_ERROR;
  1919. }
  1920. return DWT_SUCCESS;
  1921. }
  1922. /*! ------------------------------------------------------------------------------------------------------------------
  1923. * @fn _dwt_configlde()
  1924. *
  1925. * @brief configure LDE algorithm parameters
  1926. *
  1927. * input parameters
  1928. * @param prf - this is the PRF index (0 or 1) 0 correcpods to 16 and 1 to 64 PRF
  1929. *
  1930. * output parameters
  1931. *
  1932. * no return value
  1933. */
  1934. void _dwt_configlde(int prfIndex)
  1935. {
  1936. uint8_t x = LDE_PARAM1;
  1937. dwt_writetodevice( LDE_IF_ID, LDE_CFG1_OFFSET, 1, &x ); /*8-bit configuration register*/
  1938. if(prfIndex)
  1939. {
  1940. dwt_write16bitoffsetreg( LDE_IF_ID, LDE_CFG2_OFFSET, (uint16_t) LDE_PARAM3_64); /* 16-bit LDE configuration tuning register */
  1941. }
  1942. else
  1943. {
  1944. dwt_write16bitoffsetreg( LDE_IF_ID, LDE_CFG2_OFFSET, (uint16_t) LDE_PARAM3_16);
  1945. }
  1946. }
  1947. /*! ------------------------------------------------------------------------------------------------------------------
  1948. * @fn _dwt_loaducodefromrom()
  1949. *
  1950. * @brief load ucode from OTP MEMORY or ROM
  1951. *
  1952. * input parameters
  1953. *
  1954. * output parameters
  1955. *
  1956. * no return value
  1957. */
  1958. int _dwt_loaducodefromrom(void)
  1959. {
  1960. uint8_t wr_buf[2];
  1961. //set up clocks
  1962. wr_buf[1] = 0x03;
  1963. wr_buf[0] = 0x01;
  1964. dwt_writetodevice(PMSC_ID, PMSC_CTRL0_OFFSET, 2, wr_buf);
  1965. //kick off the LDE load
  1966. dwt_write16bitoffsetreg(OTP_IF_ID, OTP_CTRL, OTP_CTRL_LDELOAD); // set load LDE kick bit
  1967. Sleep(1); // Allow time for code to upload (should take up to 120 us)
  1968. //default clocks (ENABLE_ALL_SEQ)
  1969. _dwt_enableclocks(ENABLE_ALL_SEQ); //enable clocks for sequencing
  1970. return DWT_SUCCESS ;
  1971. }
  1972. /*! ------------------------------------------------------------------------------------------------------------------
  1973. * @fn dwt_loadopsettabfromotp()
  1974. *
  1975. * @brief This is used to select which Operational Parameter Set table to load from OTP memory
  1976. *
  1977. * input parameters
  1978. * @param - opset table selection
  1979. * DWT_OPSET_64LEN = 0x0 - load the operational parameter set table for 64 length preamble configuration
  1980. * DWT_OPSET_TIGHT = 0x1 - load the operational parameter set table for tight xtal offsets (<1ppm)
  1981. * DWT_OPSET_DEFLT = 0x2 - load the default operational parameter set table (this is loaded from reset)
  1982. *
  1983. * output parameters
  1984. *
  1985. * no return value
  1986. */
  1987. void dwt_loadopsettabfromotp(uint8_t gtab_sel)
  1988. {
  1989. uint8_t wr_buf[2];
  1990. uint16_t reg = (((gtab_sel & 0x3) << 5) | 0x1);
  1991. //set up clocks
  1992. wr_buf[1] = 0x03;
  1993. wr_buf[0] = 0x01;
  1994. dwt_writetodevice(PMSC_ID, PMSC_CTRL0_OFFSET, 2, wr_buf);
  1995. dwt_write16bitoffsetreg(OTP_IF_ID, OTP_SF, reg); // set load gtab kick bit (bit0) and gtab selection bit
  1996. //default clocks (ENABLE_ALL_SEQ)
  1997. _dwt_enableclocks(ENABLE_ALL_SEQ); //enable clocks for sequencing
  1998. }
  1999. /*! ------------------------------------------------------------------------------------------------------------------
  2000. * @fn dwt_setsmarttxpower()
  2001. *
  2002. * @brief This call enables or disables the smart TX power feature.
  2003. *
  2004. * input parameters
  2005. * @param enable - this enables or disables the TX smart power (1 = enable, 0 = disable)
  2006. *
  2007. * output parameters
  2008. *
  2009. * no return value
  2010. */
  2011. void dwt_setsmarttxpower(int enable)
  2012. {
  2013. //config system register
  2014. dw1000local.sysCFGreg = dwt_read32bitreg(SYS_CFG_ID) ; // read sysconfig register
  2015. //disable smart power configuration
  2016. if(enable)
  2017. {
  2018. dw1000local.sysCFGreg &= ~(SYS_CFG_DIS_STXP) ;
  2019. }
  2020. else
  2021. {
  2022. dw1000local.sysCFGreg |= SYS_CFG_DIS_STXP ;
  2023. }
  2024. dwt_write32bitreg(SYS_CFG_ID,dw1000local.sysCFGreg) ;
  2025. }
  2026. /*! ------------------------------------------------------------------------------------------------------------------
  2027. * @fn dwt_enableautoack()
  2028. *
  2029. * @brief This call enables the auto-ACK feature. If the responseDelayTime (paramter) is 0, the ACK will be sent a.s.a.p.
  2030. * otherwise it will be sent with a programmed delay (in symbols), max is 255.
  2031. *
  2032. * input parameters
  2033. * @param responseDelayTime - if non-zero the ACK is sent after this delay, max is 255.
  2034. *
  2035. * output parameters
  2036. *
  2037. * no return value
  2038. */
  2039. void dwt_enableautoack(uint8_t responseDelayTime)
  2040. {
  2041. //enable auto ACK - needs to have frame filtering enabled as well
  2042. dw1000local.sysCFGreg |= SYS_CFG_AUTOACK;
  2043. // auto ACK reply delay
  2044. dwt_write16bitoffsetreg(ACK_RESP_T_ID, 0x2, (responseDelayTime << 8) ) ; //in symbols
  2045. dwt_write32bitreg(SYS_CFG_ID,dw1000local.sysCFGreg) ;
  2046. }
  2047. /*! ------------------------------------------------------------------------------------------------------------------
  2048. * @fn dwt_setdblrxbuffmode()
  2049. *
  2050. * @brief This call enables the double receive buffer mode
  2051. *
  2052. * input parameters
  2053. * @param enable - 1 to enable, 0 to disable the double buffer mode
  2054. *
  2055. * output parameters
  2056. *
  2057. * no return value
  2058. */
  2059. void dwt_setdblrxbuffmode(int enable)
  2060. {
  2061. if(enable)
  2062. {
  2063. //enable double rx buffer mode
  2064. dw1000local.sysCFGreg &= ~SYS_CFG_DIS_DRXB;
  2065. dw1000local.dblbuffon = 1;
  2066. }
  2067. else
  2068. {
  2069. //disable double rx buffer mode
  2070. dw1000local.sysCFGreg |= SYS_CFG_DIS_DRXB;
  2071. dw1000local.dblbuffon = 0;
  2072. }
  2073. dwt_write32bitreg(SYS_CFG_ID,dw1000local.sysCFGreg) ;
  2074. }
  2075. /*! ------------------------------------------------------------------------------------------------------------------
  2076. * @fn dwt_setautorxreenable()
  2077. *
  2078. * @brief This call enables the auto rx re-enable feature
  2079. *
  2080. * input parameters
  2081. * @param enable - 1 to enable, 0 to disable the feature
  2082. *
  2083. * output parameters
  2084. *
  2085. * no return value
  2086. */
  2087. void dwt_setautorxreenable(int enable)
  2088. {
  2089. uint8_t byte = 0;
  2090. if(enable)
  2091. {
  2092. //enable auto re-enable of the receiver
  2093. dw1000local.sysCFGreg |= SYS_CFG_RXAUTR;
  2094. }
  2095. else
  2096. {
  2097. //disable auto re-enable of the receiver
  2098. dw1000local.sysCFGreg &= ~SYS_CFG_RXAUTR;
  2099. }
  2100. byte = dw1000local.sysCFGreg >> 24;
  2101. dwt_writetodevice(SYS_CFG_ID, 3, 1, &byte) ;
  2102. }
  2103. /*! ------------------------------------------------------------------------------------------------------------------
  2104. * @fn dwt_setrxaftertxdelay()
  2105. *
  2106. * @brief This sets the receiver turnon delay time after a transmission of a frame
  2107. *
  2108. * input parameters
  2109. * @param rxDelayTime - (20 bits) - the delay is in micro seconds
  2110. *
  2111. * output parameters
  2112. *
  2113. * no return value
  2114. */
  2115. void dwt_setrxaftertxdelay(uint32_t rxDelayTime)
  2116. {
  2117. uint32_t val = dwt_read32bitreg(ACK_RESP_T_ID) ; // read ACK_RESP_T_ID register
  2118. val &= ~(ACK_RESP_T_W4R_TIM_MASK) ; //clear the timer (19:0)
  2119. val |= (rxDelayTime & ACK_RESP_T_W4R_TIM_MASK) ; //in usec (e.g. turn the receiver 20us after TX)
  2120. dwt_write32bitreg(ACK_RESP_T_ID, val) ;
  2121. }
  2122. /*! ------------------------------------------------------------------------------------------------------------------
  2123. * @fn dwt_setcallbacks()
  2124. *
  2125. * @brief This is the devices interrupt handler function, it will process/report status events
  2126. *
  2127. * input parameters
  2128. * @param txcallback - the pointer to the TX callback function
  2129. * @param rxcallback - the pointer to the RX callback function
  2130. *
  2131. * output parameters
  2132. *
  2133. * no return value
  2134. */
  2135. //void dwt_setcallbacks(void (*txcallback)(const dwt_callback_data_t *), void (*rxcallback)(const dwt_callback_data_t *))
  2136. void dwt_setcallbacks(dwt_rxtxhandler txcallback, dwt_rxtxhandler rxcallback){
  2137. dw1000local.dwt_txcallback = txcallback;
  2138. dw1000local.dwt_rxcallback = rxcallback;
  2139. }
  2140. /*! ------------------------------------------------------------------------------------------------------------------
  2141. * @fn dwt_checkIRQ()
  2142. *
  2143. * @brief This function checks if the IRQ line is active - this is used instead of interrupt handler
  2144. *
  2145. * input parameters
  2146. *
  2147. * output parameters
  2148. *
  2149. * return value is 1 if the IRQS bit is set and 0 otherwise
  2150. */
  2151. uint8_t dwt_checkIRQ(void)
  2152. {
  2153. uint8_t temp;
  2154. dwt_readfromdevice(SYS_STATUS_ID, 0, 1, &temp);
  2155. return (temp & 0x1) ;
  2156. }
  2157. /*! ------------------------------------------------------------------------------------------------------------------
  2158. * @fn dwt_isr()
  2159. *
  2160. * @brief This is the devices interrupt handler function, it will process/report status events
  2161. * Notes: In PC based system using (Cheetah or ARM) USB to SPI converter there can be no interrupts, however we still need something
  2162. * to take the place of it and operate in a polled way.
  2163. * In an embedded system this function should be configured to launch on an interrupt, then it will process the interrupt trigger event and
  2164. * call a tx or rx callback function depending on whether the event is a TX or RX event.
  2165. * the tx call-back will be called when a frame has been sent and the rx call-back when a frame has been received.
  2166. *
  2167. * input parameters
  2168. *
  2169. * output parameters
  2170. *
  2171. * no return value
  2172. */
  2173. #define DEBUGx 0
  2174. #if (DEBUGx==1)
  2175. volatile uint32_t last_status[16]={0};
  2176. volatile uint32_t status_idx = 0;
  2177. #endif
  2178. stDeviceErrorCount errorCount={0};
  2179. void dwt_isr(void) // assume interrupt can supply context
  2180. {
  2181. uint32_t status = 0;
  2182. uint32_t clear = 0; // will clear any events seen
  2183. #if (DEBUGx==1)
  2184. uint32_t status1 = 0;
  2185. uint32_t states = 0;
  2186. uint32_t states1 = 0;
  2187. uint8_t buffer[2] = {0, 0};
  2188. #endif
  2189. dw1000local.cdata.event = 0;
  2190. dw1000local.cdata.dblbuff = dw1000local.dblbuffon ;
  2191. //last_status[status_idx++] = status = dw1000local.cdata.status = dwt_read32bitreg(SYS_STATUS_ID) ; // read status register low 32bits
  2192. //status_idx &= 0x0f;
  2193. status = dw1000local.cdata.status = dwt_read32bitreg(SYS_STATUS_ID) ; // read status register low 32bits
  2194. #if (DEBUGx==1)
  2195. last_status[status_idx++] = status ;
  2196. status_idx &= 0x0f;
  2197. /*if(status_idx >= 10)
  2198. {
  2199. status_idx = 0;
  2200. }*/
  2201. #endif
  2202. //NOTES:
  2203. //1. TX Event - if DWT_INT_TFRS is enabled, then when the frame has completed transmission the interrupt will be triggered.
  2204. // The status register will have the TXFRS bit set. This function will clear the tx event and call the dwt_txcallback function.
  2205. //
  2206. //2. RX Event - if DWT_INT_RFCG is enabled, then when a frame with good CRC has been received the interrupt will be triggered.
  2207. // The status register will have the RXFCG bit set. This function will clear the rx event and call the dwt_rxcallback function.
  2208. //
  2209. //2.a. RX Event - This is same as 2. above except this time the received frame has ACK request bit set in the header (AAT bit will be set).
  2210. // This function will clear the rx event and call the dwt_rxcallback function, notifying the application that ACK req is set.
  2211. // If using auto-ACK, the AAT indicates that ACK frame transmission is in progress. Once the ACK has been sent the TXFRS bit will be set and TX event triggered.
  2212. // If the auto-ACK is not enabled, the application can format/configure and start transmission of its own ACK frame.
  2213. //
  2214. #if (DEBUGx==1)
  2215. //DEBUG ----- DEBUG ----- DEBUG -----
  2216. status1 = dwt_read32bitoffsetreg(SYS_STATUS_ID, 1) ; // read status register
  2217. dwt_readfromdevice(RX_BUFFER_ID,0,2,buffer) ;
  2218. printf("status %02X%08X, byte 0 %02X%02X\n", status1>>24, status, buffer[0], buffer[1]);
  2219. states = dwt_read32bitreg(0x19) ; // read status register
  2220. states1 = dwt_read32bitoffsetreg(0x19, 1) ; // read status register
  2221. printf("states %02X%08X\n", states1>>24, states);
  2222. #endif
  2223. if(status == 0x00800003)
  2224. {
  2225. //uint32_t status1 = 0;
  2226. //uint32_t states1 = 0;
  2227. //status1 = dwt_read32bitoffsetreg(SYS_STATUS_ID, 1) ;
  2228. //states1 = dwt_read32bitoffsetreg(0x19, 0) ;
  2229. //states1 = dwt_read32bitoffsetreg(0x19, 1) ;
  2230. dwt_forcetrxoff();
  2231. dwt_rxreset();
  2232. }
  2233. //fix for bug 622 - LDE done flag gets latched on a bad frame
  2234. if((status & SYS_STATUS_LDEDONE) && (dw1000local.dblbuffon == 0))
  2235. {
  2236. if((status & (SYS_STATUS_LDEDONE | SYS_STATUS_RXPHD | SYS_STATUS_RXSFDD)) != (SYS_STATUS_LDEDONE | SYS_STATUS_RXPHD | SYS_STATUS_RXSFDD))
  2237. {
  2238. //got LDE done but other flags SFD and PHR are clear - this is a bad frame - reset the transceiver
  2239. dwt_forcetrxoff(); //this will clear all events
  2240. dwt_rxreset();
  2241. //leave any TX events for processing (e.g. if we TX a frame, and then enable rx,
  2242. //we can get into here before the TX frame done has been processed, when we are polling (i.e. slow to process the TX)
  2243. status &= CLEAR_ALLTX_EVENTS;
  2244. //re-enable the receiver - if auto rx re-enable set
  2245. if(dw1000local.sysCFGreg & SYS_CFG_RXAUTR)
  2246. {
  2247. dwt_write16bitoffsetreg(SYS_CTRL_ID,0,(uint16_t)SYS_CTRL_RXENAB) ;
  2248. }
  2249. else
  2250. {
  2251. dw1000local.cdata.event = DWT_SIG_RX_ERROR;//
  2252. if(dw1000local.dwt_rxcallback != NULL)
  2253. {
  2254. dw1000local.dwt_rxcallback((const dwt_callback_data_t *)&dw1000local.cdata);
  2255. }
  2256. }
  2257. }
  2258. }
  2259. //
  2260. // 1st check for RX frame received or RX timeout and if so call the rx callback function
  2261. //
  2262. if(status & SYS_STATUS_RXFCG) // Receiver FCS Good
  2263. {
  2264. if(status & SYS_STATUS_LDEDONE) // LDE done/finished
  2265. {
  2266. // bug 634 - overrun overwrites the frame info data... so both frames should be discarded
  2267. // read frame info and other registers and check for overflow again
  2268. // if overflow set then discard both frames...
  2269. uint16_t len = 0;
  2270. if (status & SYS_STATUS_RXOVRR) //NOTE when overrun both HS and RS pointers point to the same buffer
  2271. {
  2272. //when the overrun happens the frame info data of the buffer A (which contains the older frame e.g. seq. num = x)
  2273. //will be corrupted with the latest frame (seq. num = x + 2) data, both the host and IC are pointing to buffer A
  2274. //we are going to discard this frame - turn off transceiver and reset receiver
  2275. dwt_forcetrxoff();
  2276. dwt_rxreset();
  2277. if(dw1000local.sysCFGreg & SYS_CFG_RXAUTR) //re-enable of RX is ON, then re-enable here (ignore error)
  2278. {
  2279. dwt_write16bitoffsetreg(SYS_CTRL_ID,0,(uint16_t)SYS_CTRL_RXENAB) ;
  2280. }
  2281. else //the RX will be re-enabled by the application, report an error
  2282. {
  2283. dw1000local.cdata.event = DWT_SIG_RX_ERROR;//RX_OVERRUN
  2284. if(dw1000local.dwt_rxcallback != NULL)
  2285. {
  2286. dw1000local.dwt_rxcallback((const dwt_callback_data_t *)&dw1000local.cdata);
  2287. }
  2288. }
  2289. errorCount.overRunCount++;
  2290. return;
  2291. }
  2292. else //no overrun condition - proceed to process the frame
  2293. {
  2294. len = dwt_read16bitoffsetreg(RX_FINFO_ID, 0) & 0x3FF;
  2295. dwt_readfromdevice(RX_BUFFER_ID,0,2,(uint8_t*)dw1000local.cdata.fctrl) ;
  2296. if (dw1000local.longFrames==0)
  2297. {
  2298. len &= 0x7F ;
  2299. }
  2300. // Standard frame length up to 127, extended frame length up to 1023 bytes
  2301. dw1000local.cdata.datalength = len ;
  2302. //bug 627 workaround - clear the AAT bit if the ACK request bit in the FC is not set
  2303. if((status & SYS_STATUS_AAT) //AAT bit is set (ACK has been requested)
  2304. && (((dw1000local.cdata.fctrl[0] & 0x20) == 0) || (dw1000local.cdata.fctrl[0] == 0x02)) //but the data frame has it clear or it is an ACK frame
  2305. )
  2306. {
  2307. clear |= SYS_STATUS_AAT ;
  2308. dw1000local.cdata.aatset = 0 ; //ACK request is not set
  2309. dw1000local.wait4resp = 0;
  2310. }
  2311. else //the AAT is correctly set for a frame that requested the ACK
  2312. {
  2313. dw1000local.cdata.aatset = (status & SYS_STATUS_AAT) ; //check if ACK request is set
  2314. }
  2315. dw1000local.cdata.event = DWT_SIG_RX_OKAY ;
  2316. if(dw1000local.dblbuffon == 0) //if no double buffering
  2317. {
  2318. //clear all receive status bits (as we are finished with this receive event)
  2319. clear |= status & CLEAR_ALLRXGOOD_EVENTS ;
  2320. dwt_write32bitreg(SYS_STATUS_ID,clear) ; // write status register to clear event bits we have seen
  2321. //NOTE: clear the event which caused interrupt means once the rx is enabled or tx is started
  2322. //new events can trigger and give rise to new interrupts
  2323. //call the RX call-back function to process the RX event
  2324. if(dw1000local.dwt_rxcallback != NULL)
  2325. {
  2326. dw1000local.dwt_rxcallback((const dwt_callback_data_t *)&dw1000local.cdata);
  2327. }
  2328. }
  2329. else //double buffer
  2330. {
  2331. uint8_t buff ;
  2332. uint8_t hsrb = 0x01 ;
  2333. //need to make sure that the host/IC buffer pointers are aligned before starting RX
  2334. //read again because the status could have changed since the interrupt was triggered
  2335. dwt_readfromdevice(SYS_STATUS_ID, 3, 1, &buff);
  2336. //if ICRBP is equal to HSRBP this means we've received another frame (both buffers have frames)
  2337. if((buff & (SYS_STATUS_ICRBP>>24) ) == /* IC side Receive Buffer Pointer */
  2338. ((buff & (SYS_STATUS_HSRBP>>24) ) << 1) ) /* Host Side Receive Buffer Pointer */
  2339. {
  2340. //clear all receive status bits (as we are finished with this receive event)
  2341. clear |= status & CLEAR_DBLBUFF_EVENTS ;
  2342. dwt_write32bitreg(SYS_STATUS_ID,clear) ; // write status register to clear event bits we have seen
  2343. }
  2344. //if they are not aligned then there is a new frame in the other buffer, so we just need to toggle...
  2345. if((dw1000local.sysCFGreg & SYS_CFG_RXAUTR) == 0) //double buffer is on but no auto rx re-enable RX
  2346. {
  2347. dwt_write16bitoffsetreg(SYS_CTRL_ID,0,(uint16_t)SYS_CTRL_RXENAB) ;
  2348. }
  2349. //call the RX call-back function to process the RX event
  2350. if(dw1000local.dwt_rxcallback != NULL)
  2351. {
  2352. dw1000local.dwt_rxcallback((const dwt_callback_data_t *)&dw1000local.cdata);
  2353. }
  2354. //if overrun, then reset the reciver - RX bug, when overruns cannot guarantee the last frame's data was not corrupted
  2355. //if no overrun all is good, toggle the pointer
  2356. if(dwt_checkoverrun() == 0)
  2357. {
  2358. //toggle the host side Receive Buffer Pointer by writing one to the register
  2359. dwt_writetodevice(SYS_CTRL_ID, SYS_CTRL_HRBT_OFFSET, 1, &hsrb) ; // we need to swap rx buffer status reg (write one to toggle internally)
  2360. }
  2361. else
  2362. {
  2363. //the calback has completed, but the overrun has been set, before we toggled, this means two new frames have arrived (one in the other buffer) and the 2nd's PHR good set the overrun flag
  2364. //due to a receiver bug, which cannot guarantee the last frame's data was not corrupted need to reset receiver and discard any new data
  2365. dwt_forcetrxoff();
  2366. dwt_rxreset();
  2367. if(dw1000local.sysCFGreg & SYS_CFG_RXAUTR) //re-enable of RX is ON, then re-enable here
  2368. {
  2369. dwt_write16bitoffsetreg(SYS_CTRL_ID,0,(uint16_t)SYS_CTRL_RXENAB) ;
  2370. }
  2371. }
  2372. } //end of else double buffer
  2373. }//end of no overrun
  2374. } //if LDE_DONE is set (this means we have both SYS_STATUS_RXFCG and SYS_STATUS_LDEDONE)
  2375. else //no LDE_DONE ?
  2376. {
  2377. //printf("NO LDE done or LDE error\n");
  2378. if(!(dw1000local.sysCFGreg & SYS_CFG_RXAUTR))
  2379. {
  2380. dwt_forcetrxoff();
  2381. }
  2382. dwt_rxreset(); //reset the RX
  2383. dw1000local.wait4resp = 0;
  2384. dw1000local.cdata.event = DWT_SIG_RX_ERROR;//LED_DONE is not set
  2385. if(dw1000local.dwt_rxcallback != NULL)
  2386. {
  2387. dw1000local.dwt_rxcallback((const dwt_callback_data_t *)&dw1000local.cdata);
  2388. }
  2389. }
  2390. } // end if CRC is good
  2391. else
  2392. //
  2393. // Check for TX frame sent event and signal to upper layer.
  2394. //
  2395. if (status & SYS_STATUS_TXFRS) // Transmit Frame Sent
  2396. {
  2397. clear |= CLEAR_ALLTX_EVENTS; //clear TX event bits
  2398. dwt_write32bitreg(SYS_STATUS_ID,clear) ; // write status register to clear event bits we have seen
  2399. //NOTE: clear the event which caused interrupt means once the rx is enabled or tx is started
  2400. //new events can trigger and give rise to new interrupts
  2401. if(dw1000local.cdata.aatset)
  2402. {
  2403. dw1000local.cdata.aatset = 0; //the ACK has been sent
  2404. if(dw1000local.dblbuffon == 0) //if not double buffered
  2405. {
  2406. if(dw1000local.wait4resp) //wait4response was set with the last TX start command
  2407. {
  2408. //if using wait4response and the ACK has been sent as the response requested it
  2409. //the receiver will be re-enabled, so issue a TRXOFF command to disable and prevent any
  2410. //unexpected interrupts
  2411. dwt_forcetrxoff();
  2412. }
  2413. }
  2414. }
  2415. dw1000local.cdata.event = DWT_SIG_TX_DONE ; // signal TX completed
  2416. //call the TX call-back function to process the TX event
  2417. if(dw1000local.dwt_txcallback != NULL)
  2418. {
  2419. dw1000local.dwt_txcallback((const dwt_callback_data_t *)&dw1000local.cdata);
  2420. }
  2421. }
  2422. else if (status & SYS_STATUS_RXRFTO) // Receiver Frame Wait timeout:
  2423. {
  2424. clear |= status & SYS_STATUS_RXRFTO ;
  2425. dwt_write32bitreg(SYS_STATUS_ID,clear) ; // write status register to clear event bits we have seen
  2426. dw1000local.cdata.event = DWT_SIG_RX_TIMEOUT ;
  2427. if(dw1000local.dwt_rxcallback != NULL)
  2428. {
  2429. dw1000local.dwt_rxcallback((const dwt_callback_data_t *)&dw1000local.cdata);
  2430. }
  2431. dw1000local.wait4resp = 0;
  2432. }
  2433. else if(status & CLEAR_ALLRXERROR_EVENTS)//catches all other error events
  2434. {
  2435. clear |= status & CLEAR_ALLRXERROR_EVENTS;
  2436. dwt_write32bitreg(SYS_STATUS_ID,clear) ; // write status register to clear event bits we have seen
  2437. dw1000local.wait4resp = 0;
  2438. //NOTE: clear the event which caused interrupt means once the rx is enabled or tx is started
  2439. //new events can trigger and give rise to new interrupts
  2440. //fix for bug 622 - LDE done flag gets latched on a bad frame / reset receiver
  2441. if(!(dw1000local.sysCFGreg & SYS_CFG_RXAUTR))
  2442. {
  2443. dwt_forcetrxoff(); //this will clear all events
  2444. }
  2445. dwt_rxreset(); //reset the RX
  2446. //end of fix for bug 622 - LDE done flag gets latched on a bad frame
  2447. if(status & SYS_STATUS_RXPHE)
  2448. {
  2449. dw1000local.cdata.event = DWT_SIG_RX_PHR_ERROR ;
  2450. errorCount.rxPHECount++;
  2451. }
  2452. else if(status & SYS_STATUS_RXFCE)
  2453. {
  2454. dw1000local.cdata.event = DWT_SIG_RX_ERROR ;//FCS error
  2455. errorCount.rxFCECount++;
  2456. }
  2457. else if(status & SYS_STATUS_RXRFSL)
  2458. {
  2459. dw1000local.cdata.event = DWT_SIG_RX_SYNCLOSS ;
  2460. }
  2461. else if(status & SYS_STATUS_RXSFDTO)
  2462. {
  2463. dw1000local.cdata.event = DWT_SIG_RX_SFDTIMEOUT ;
  2464. errorCount.rxSFDTOCount++;
  2465. }
  2466. else if(status & SYS_STATUS_RXPTO)
  2467. {
  2468. dw1000local.cdata.event = DWT_SIG_RX_PTOTIMEOUT ;
  2469. errorCount.rxPTOCount++;
  2470. }
  2471. else
  2472. {
  2473. dw1000local.cdata.event = DWT_SIG_RX_ERROR;//Unknown error
  2474. errorCount.rxOtherCount++;
  2475. }
  2476. if(dw1000local.dwt_rxcallback != NULL)
  2477. {
  2478. dw1000local.dwt_rxcallback((const dwt_callback_data_t *)&dw1000local.cdata);
  2479. }
  2480. status &= CLEAR_ALLTX_EVENTS;
  2481. }
  2482. } // end dwt_isr()
  2483. /*! ------------------------------------------------------------------------------------------------------------------
  2484. * @fn dwt_setleds()
  2485. *
  2486. * @brief This is used to set up Tx/Rx GPIOs which could be used to control LEDs
  2487. * Note: not completely IC dependent, also needs board with LEDS fitted on right I/O lines
  2488. * this function enables GPIOs 2 and 3 which are connected to LED3 and LED4 on EVB1000
  2489. *
  2490. * input parameters
  2491. * @param test - if 1 the LEDs will be enabled, if 0 the LED control is disabled.
  2492. * - if value is 2 the LEDs will flash once after enable.
  2493. *
  2494. * output parameters
  2495. *
  2496. * no return value
  2497. */
  2498. void dwt_setleds(uint8_t test)
  2499. {
  2500. uint8_t buf[2];
  2501. if(test & 0x1)
  2502. {
  2503. // Set up MFIO for LED output
  2504. dwt_readfromdevice(GPIO_CTRL_ID,0x00,2,buf);
  2505. buf[1] &= ~0x3C; //clear the bits
  2506. buf[1] |= 0x14;
  2507. dwt_writetodevice(GPIO_CTRL_ID,0x01,1,&buf[1]);
  2508. // Enable LP Oscillator to run from counter, turn on debounce clock
  2509. dwt_readfromdevice(PMSC_ID,0x02,1,buf);
  2510. buf[0] |= 0x84; //
  2511. dwt_writetodevice(PMSC_ID,0x02,1,buf);
  2512. // Enable LEDs to blink
  2513. buf[0] = 0x10; // Blink period.
  2514. buf[1] = 0x01; // Enable blink counter
  2515. dwt_writetodevice(PMSC_ID,PMSC_LEDC_OFFSET,2,buf);
  2516. }
  2517. else if ((test & 0x1)== 0)
  2518. {
  2519. // Clear the GPIO bits that are used for LED control
  2520. dwt_readfromdevice(GPIO_CTRL_ID,0x00,2,buf);
  2521. buf[1] &= ~(0x14);
  2522. dwt_writetodevice(GPIO_CTRL_ID,0x00,2,buf);
  2523. }
  2524. // Test LEDs
  2525. if(test & 0x2)
  2526. {
  2527. buf[0] = 0x0f; // Fire a LED blink trigger
  2528. dwt_writetodevice(PMSC_ID,0x2a,1,buf);
  2529. buf[0] = 0x00; // Clear forced trigger bits
  2530. dwt_writetodevice(PMSC_ID,0x2a,1,buf);
  2531. }
  2532. } // end _dwt_enableleds()
  2533. // -------------------------------------------------------------------------------------------------------------------
  2534. // function to enable/disable clocks to particular digital blocks/system
  2535. //
  2536. void _dwt_enableclocks(int clocks)
  2537. {
  2538. uint8_t reg[2];
  2539. dwt_readfromdevice(PMSC_ID, PMSC_CTRL0_OFFSET, 2, reg);
  2540. switch(clocks)
  2541. {
  2542. case ENABLE_ALL_SEQ:
  2543. {
  2544. reg[0] = 0x00 ;
  2545. reg[1] = reg[1] & 0xfe;
  2546. }
  2547. break;
  2548. case FORCE_SYS_XTI:
  2549. {
  2550. //system and rx
  2551. reg[0] = 0x01 | (reg[0] & 0xfc);
  2552. }
  2553. break;
  2554. case FORCE_SYS_PLL:
  2555. {
  2556. //system
  2557. reg[0] = 0x02 | (reg[0] & 0xfc);
  2558. }
  2559. break;
  2560. case READ_ACC_ON:
  2561. {
  2562. reg[0] = 0x48 | (reg[0] & 0xb3);
  2563. reg[1] = 0x80 | reg[1];
  2564. }
  2565. break;
  2566. case READ_ACC_OFF:
  2567. {
  2568. reg[0] = reg[0] & 0xb3;
  2569. reg[1] = 0x7f & reg[1];
  2570. }
  2571. break;
  2572. case FORCE_OTP_ON:
  2573. {
  2574. reg[1] = 0x02 | reg[1];
  2575. }
  2576. break;
  2577. case FORCE_OTP_OFF:
  2578. {
  2579. reg[1] = reg[1] & 0xfd;
  2580. }
  2581. break;
  2582. case FORCE_TX_PLL:
  2583. {
  2584. reg[0] = 0x20| (reg[0] & 0xcf);
  2585. }
  2586. break;
  2587. default:
  2588. break;
  2589. }
  2590. // Need to write lower byte separately before setting the higher byte(s)
  2591. dwt_writetodevice(PMSC_ID, PMSC_CTRL0_OFFSET, 1, &reg[0]);
  2592. dwt_writetodevice(PMSC_ID, 0x1, 1, &reg[1]);
  2593. } // end _dwt_enableclocks()
  2594. /*! ------------------------------------------------------------------------------------------------------------------
  2595. * @fn _dwt_disablesequencing()
  2596. *
  2597. * @brief This function disables the TX blocks sequencing, it disables PMSC control of RF blocks, system clock is also set to XTAL
  2598. *
  2599. * input parameters none
  2600. *
  2601. * output parameters none
  2602. *
  2603. * no return value
  2604. */
  2605. void _dwt_disablesequencing(void) //disable sequencing and go to state "INIT"
  2606. {
  2607. _dwt_enableclocks(FORCE_SYS_XTI); //set system clock to XTI
  2608. dwt_write16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET, PMSC_CTRL1_PKTSEQ_DISABLE); //disable PMSC ctrl of RF and RX clk blocks
  2609. }
  2610. /*! ------------------------------------------------------------------------------------------------------------------
  2611. * @fn dwt_setdelayedtrxtime()
  2612. *
  2613. * @brief This API function configures the delayed transmit time or the delayed rx on time
  2614. *
  2615. * input parameters
  2616. * @param starttime - the tx/rx start time (the 32 bits should be the high 32 bits of the system time at which to send the message,
  2617. * or at which to turn on the receiver)
  2618. *
  2619. * output parameters none
  2620. *
  2621. * no return value
  2622. */
  2623. #ifdef __GNUC__
  2624. #pragma GCC optimize ("O3")
  2625. #elif defined(__ICCARM__)
  2626. #pragma optimize=speed high
  2627. #endif
  2628. void dwt_setdelayedtrxtime(uint32_t starttime)
  2629. {
  2630. dwt_write32bitoffsetreg(DX_TIME_ID, 1, starttime) ;
  2631. } // end dwt_setdelayedtrxtime()
  2632. /*! ------------------------------------------------------------------------------------------------------------------
  2633. * @fn dwt_starttx()
  2634. *
  2635. * @brief This call initiates the transmission, input parameter indicates which TX mode is used see below
  2636. *
  2637. * input parameters:
  2638. * @param mode - if 0 immediate TX (no response expected)
  2639. * if 1 delayed TX (no response expected)
  2640. * if 2 immediate TX (response expected - so the receiver will be automatically turned on after TX is done)
  2641. * if 3 delayed TX (response expected - so the receiver will be automatically turned on after TX is done)
  2642. *
  2643. * output parameters
  2644. *
  2645. * returns DWT_DECA_SUCCESS for success, or DWT_DECA_ERROR for error (e.g. a delayed transmission will fail if the delayed time has passed)
  2646. */
  2647. #ifdef __GNUC__
  2648. #pragma GCC optimize ("O3")
  2649. #elif defined(__ICCARM__)
  2650. #pragma optimize=speed high
  2651. #endif
  2652. int dwt_starttx(uint8_t mode)
  2653. {
  2654. int retval = DWT_SUCCESS ;
  2655. uint8_t temp = 0x00;
  2656. uint16_t checkTxOK = 0 ;
  2657. if(mode & DWT_RESPONSE_EXPECTED)
  2658. {
  2659. temp = (uint8_t)SYS_CTRL_WAIT4RESP ; //set wait4response bit
  2660. dwt_writetodevice(SYS_CTRL_ID,0,1,&temp) ;
  2661. dw1000local.wait4resp = 1;
  2662. }
  2663. if (mode & DWT_START_TX_DELAYED)
  2664. {
  2665. // both SYS_CTRL_TXSTRT and SYS_CTRL_TXDLYS to correctly enable TX
  2666. temp |= (uint8_t)(SYS_CTRL_TXDLYS | SYS_CTRL_TXSTRT) ;
  2667. dwt_writetodevice(SYS_CTRL_ID,0,1,&temp) ;
  2668. checkTxOK = dwt_read16bitoffsetreg(SYS_STATUS_ID,3) ;
  2669. if ((checkTxOK & SYS_STATUS_TXERR) == 0) // Transmit Delayed Send set over Half a Period away or Power Up error (there is enough time to send but not to power up individual blocks).
  2670. {
  2671. //printf("tx delayed \n");
  2672. retval = DWT_SUCCESS ; // All okay
  2673. }
  2674. else
  2675. {
  2676. // I am taking DSHP set to Indicate that the TXDLYS was set too late for the specified DX_TIME.
  2677. // Remedial Action - (a) cancel delayed send
  2678. temp = (uint8_t)SYS_CTRL_TRXOFF; // this assumes the bit is in the lowest byte
  2679. dwt_writetodevice(SYS_CTRL_ID,0,1,&temp) ;
  2680. // note event Delayed TX Time too Late
  2681. // could fall through to start a normal send (below) just sending late.....
  2682. // ... instead return and assume return value of 1 will be used to detect and recover from the issue.
  2683. // clear the "auto TX to sleep" bit
  2684. dwt_entersleepaftertx(0);
  2685. dw1000local.wait4resp = 0;
  2686. retval = DWT_ERROR ; // Failed !
  2687. }
  2688. }
  2689. else
  2690. {
  2691. temp |= (uint8_t)SYS_CTRL_TXSTRT ;
  2692. dwt_writetodevice(SYS_CTRL_ID,0,1,&temp) ;
  2693. }
  2694. return retval;
  2695. } // end dwt_starttx()
  2696. // -------------------------------------------------------------------------------------------------------------------
  2697. //
  2698. // Clear overrun condition
  2699. //
  2700. int dwt_checkoverrun(void)
  2701. {
  2702. return (dwt_read16bitoffsetreg(SYS_STATUS_ID, 2) & (SYS_STATUS_RXOVRR >> 16));
  2703. }
  2704. // -------------------------------------------------------------------------------------------------------------------
  2705. //
  2706. // Force Transceiver OFF
  2707. //
  2708. #ifdef __GNUC__
  2709. #pragma GCC optimize ("O3")
  2710. #elif defined(__ICCARM__)
  2711. #pragma optimize=speed high
  2712. #endif
  2713. void dwt_forcetrxoff(void)
  2714. {
  2715. decaIrqStatus_t stat ;
  2716. uint8_t temp ;
  2717. uint32_t mask;
  2718. temp = (uint8_t)SYS_CTRL_TRXOFF ; // this assumes the bit is in the lowest byte
  2719. mask = dwt_read32bitreg(SYS_MASK_ID) ; //read set interrupt mask
  2720. // need to beware of interrupts occurring in the middle of following read modify write cycle
  2721. // we can disable the radio, but before the status is cleared an interrupt can be set (e.g. the
  2722. // event has just happened before the radio was disabled)
  2723. // thus we need to disable interrupt during this operation
  2724. stat = decamutexon() ;
  2725. dwt_write32bitreg(SYS_MASK_ID, 0) ; //clear interrupt mask - so we don't get any unwanted events
  2726. dwt_writetodevice(SYS_CTRL_ID,0,1,&temp) ; //disable the radio
  2727. // Forcing Transceiver off - so we do not want to see any new events that may have happened
  2728. dwt_write32bitreg(SYS_STATUS_ID,(CLEAR_ALLTX_EVENTS | CLEAR_ALLRXERROR_EVENTS | CLEAR_ALLRXGOOD_EVENTS)) ;
  2729. dwt_syncrxbufptrs();
  2730. dwt_write32bitreg(SYS_MASK_ID, mask) ; //set interrupt mask to what it was
  2731. //enable/restore interrupts again...
  2732. decamutexoff(stat) ;
  2733. dw1000local.wait4resp = 0;
  2734. } // end deviceforcetrxoff()
  2735. /*! ------------------------------------------------------------------------------------------------------------------
  2736. * @fn dwt_syncrxbufptrs()
  2737. *
  2738. * @brief this function synchronizes rx buffer pointers
  2739. * need to make sure that the host/IC buffer pointers are aligned before starting RX
  2740. *
  2741. * input parameters:
  2742. *
  2743. * output parameters
  2744. *
  2745. * no return value
  2746. */
  2747. void dwt_syncrxbufptrs(void)
  2748. {
  2749. uint8_t buff ;
  2750. //need to make sure that the host/IC buffer pointers are aligned before starting RX
  2751. dwt_readfromdevice(SYS_STATUS_ID, 3, 1, &buff);
  2752. if((buff & (SYS_STATUS_ICRBP>>24) ) != /* IC side Receive Buffer Pointer */
  2753. ((buff & (SYS_STATUS_HSRBP>>24) ) << 1) ) /* Host Side Receive Buffer Pointer */
  2754. {
  2755. uint8_t hsrb = 0x01;
  2756. dwt_writetodevice(SYS_CTRL_ID, SYS_CTRL_HRBT_OFFSET , 1, &hsrb) ; // we need to swap rx buffer status reg (write one to toggle internally)
  2757. }
  2758. }
  2759. /*! ------------------------------------------------------------------------------------------------------------------
  2760. * @fn dwt_setrxmode()
  2761. *
  2762. * @brief enable different rx modes, e.g.:
  2763. * a) "snooze" mode, the receiver only listens periodically for preamble
  2764. * b) the rx PPDM "sniff" mode - receiver cycles through ON/OFF periods
  2765. *
  2766. * input parameters:
  2767. * @param mode - DWT_RX_NORMAL = 0x0
  2768. * DWT_RX_SNIFF = 0x1 enable the rx PPDM "sniff" mode
  2769. * @param rxON - SNIFF mode ON period in PACs
  2770. * @param rxOFF - SNIFF mode OFF period in us (actually in 1.0256 micro second intervals)
  2771. * output parameters
  2772. *
  2773. * no return value
  2774. */
  2775. void dwt_setrxmode(int mode, uint8_t rxON, uint8_t rxOFF)
  2776. {
  2777. uint16_t reg16 = RX_SNIFF_MASK & ((rxOFF << 8) | rxON);
  2778. if(mode & DWT_RX_SNIFF)
  2779. {
  2780. // PPM_OFF 15:8, PPM_ON 3:0
  2781. dwt_write16bitoffsetreg(RX_SNIFF_ID, 0x00, reg16) ; //enable
  2782. }
  2783. else
  2784. {
  2785. dwt_write16bitoffsetreg(RX_SNIFF_ID, 0x00, 0x0000) ; //disable
  2786. }
  2787. }
  2788. /*! ------------------------------------------------------------------------------------------------------------------
  2789. * @fn dwt_rxenable(int delayed)
  2790. *
  2791. * @brief This call turns on the receiver, can be immediate or delayed.
  2792. * The receiver will stay turned on, listening to any messages until
  2793. * it either receives a good frame, an error (CRC, PHY header, Reed Solomon) or it times out (SFD, Preamble or Frame).
  2794. *
  2795. * input parameters
  2796. * @param mode - if 0 immediate RX
  2797. * if 1 delayed RX the receiver is turned on after some delay (as programmed with dwt_setdelayedtime())
  2798. * if 2 RX on if delay error so the receiver will be automatically turned on if "late" error detected
  2799. *
  2800. * @return DWT_DECA_SUCCESS for success, or DWT_DECA_ERROR for error (e.g. a delayed receive enable will be too far in the future if delayed time has passed (if delayed time is > 8s from now))
  2801. */
  2802. #ifdef __GNUC__
  2803. #pragma GCC optimize ("O3")
  2804. #elif defined(__ICCARM__)
  2805. #pragma optimize=speed high
  2806. #endif
  2807. int dwt_rxenable(uint8_t mode)
  2808. {
  2809. uint16_t temp ;
  2810. uint16_t checkRxOK = 0;
  2811. dwt_syncrxbufptrs();
  2812. temp = (uint16_t)SYS_CTRL_RXENAB ;
  2813. if (mode & DWT_START_RX_DELAYED)
  2814. {
  2815. temp |= (uint16_t)SYS_CTRL_RXDLYE ;
  2816. }
  2817. dwt_write16bitoffsetreg(SYS_CTRL_ID,0,temp) ;
  2818. if (mode & DWT_START_RX_DELAYED) //check for errors
  2819. {
  2820. checkRxOK = dwt_read16bitoffsetreg(SYS_STATUS_ID,3) ;
  2821. if ((checkRxOK & SYS_STATUS_TXERR) != 0) //if delay has not passed do delayed else immediate RX on
  2822. {
  2823. dwt_forcetrxoff(); //turn the delayed receive off, and do immediate receive, return warning indication
  2824. if(mode & DWT_REENABLE_ON_DLY_ERR)
  2825. {
  2826. dwt_write16bitoffsetreg(SYS_CTRL_ID,0,SYS_CTRL_RXENAB) ;
  2827. }
  2828. return DWT_ERROR;
  2829. }
  2830. }
  2831. return DWT_SUCCESS;
  2832. } // end dwt_rxenable()
  2833. /*! ------------------------------------------------------------------------------------------------------------------
  2834. * @fn dwt_setrxtimeout()
  2835. *
  2836. * @brief This call enables RX timeout (SY_STAT_RFTO event)
  2837. *
  2838. * input parameters
  2839. * @param time - how long the receiver remains on from the RX enable command
  2840. * The time parameter used here is in 1.0256 us (512/499.2MHz) units
  2841. * If set to 0 the timeout is disabled.
  2842. *
  2843. * output parameters
  2844. *
  2845. * no return value
  2846. */
  2847. void dwt_setrxtimeout(uint16_t time)
  2848. {
  2849. uint8_t temp ;
  2850. dwt_readfromdevice(SYS_CFG_ID,3,1,&temp) ; // read register
  2851. if(time > 0)
  2852. {
  2853. dwt_write16bitoffsetreg(RX_FWTO_ID, 0x0, time) ;
  2854. temp |= (uint8_t)(SYS_CFG_RXWTOE>>24);
  2855. // OR in 32bit value (1 bit set), I know this is in high byte.
  2856. dw1000local.sysCFGreg |= SYS_CFG_RXWTOE;
  2857. dwt_writetodevice(SYS_CFG_ID,3,1,&temp) ;
  2858. }
  2859. else
  2860. {
  2861. temp &= ~((uint8_t)(SYS_CFG_RXWTOE>>24));
  2862. // AND in inverted 32bit value (1 bit clear), I know this is in high byte.
  2863. dw1000local.sysCFGreg &= ~(SYS_CFG_RXWTOE);
  2864. dwt_writetodevice(SYS_CFG_ID,3,1,&temp) ;
  2865. //dwt_write16bitoffsetreg(RX_FWTO_ID,0,0) ; // clearing the time is not needed
  2866. }
  2867. } // end dwt_setrxtimeout()
  2868. /*! ------------------------------------------------------------------------------------------------------------------
  2869. * @fn dwt_setpreambledetecttimeout()
  2870. *
  2871. * @brief This call enables preamble timeout (SY_STAT_RXPTO event)
  2872. *
  2873. * input parameters
  2874. * @param timeout - in PACs
  2875. *
  2876. * output parameters
  2877. *
  2878. * no return value
  2879. */
  2880. void dwt_setpreambledetecttimeout(uint16_t timeout)
  2881. {
  2882. dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_PRETOC_OFFSET, timeout);
  2883. }
  2884. /*! ------------------------------------------------------------------------------------------------------------------
  2885. * @fn void dwt_setinterrupt( uint32_t bitmask, uint8_t enable)
  2886. *
  2887. * @brief This function enables the specified events to trigger an interrupt.
  2888. * The following events can be enabled:
  2889. * DWT_INT_TFRS 0x00000080 // frame sent
  2890. * DWT_INT_RFCG 0x00004000 // frame received with good CRC
  2891. * DWT_INT_RPHE 0x00001000 // receiver PHY header error
  2892. * DWT_INT_RFCE 0x00008000 // receiver CRC error
  2893. * DWT_INT_RFSL 0x00010000 // receiver sync loss error
  2894. * DWT_INT_RFTO 0x00020000 // frame wait timeout
  2895. * DWT_INT_RXPTO 0x00200000 // preamble detect timeout
  2896. * DWT_INT_SFDT 0x04000000 // SFD timeout
  2897. * DWT_INT_ARFE 0x20000000 // frame rejected (due to frame filtering configuration)
  2898. *
  2899. *
  2900. * input parameters:
  2901. * @param bitmask - sets the events which will generate interrupt
  2902. * @param enable - if set the interrupts are enabled else they are cleared
  2903. *
  2904. * output parameters
  2905. *
  2906. * no return value
  2907. */
  2908. void dwt_setinterrupt(uint32_t bitmask, uint8_t enable)
  2909. {
  2910. decaIrqStatus_t stat ;
  2911. uint32_t mask ;
  2912. // need to beware of interrupts occurring in the middle of following read modify write cycle
  2913. stat = decamutexon() ;
  2914. mask = dwt_read32bitreg(SYS_MASK_ID) ; // read register
  2915. if(enable)
  2916. {
  2917. mask |= bitmask ;
  2918. }
  2919. else
  2920. {
  2921. mask &= ~bitmask ; // clear the bit
  2922. }
  2923. dwt_write32bitreg(SYS_MASK_ID,mask) ; // new value
  2924. decamutexoff(stat) ;
  2925. }
  2926. /*! ------------------------------------------------------------------------------------------------------------------
  2927. * @fn dwt_configeventcounters()
  2928. *
  2929. * @brief This is used to enable/disable the event counter in the IC
  2930. *
  2931. * input parameters
  2932. * @param - enable - 1 enables (and reset), 0 disables the event counters
  2933. * output parameters
  2934. *
  2935. * no return value
  2936. */
  2937. void dwt_configeventcounters(int enable)
  2938. {
  2939. uint8_t temp = 0x0; //disable
  2940. //need to clear and disable, can't just clear
  2941. temp = (uint8_t)(EVC_CLR); //clear and disable
  2942. dwt_writetodevice(DIG_DIAG_ID, EVC_CTRL_OFFSET, 1, &temp) ;
  2943. if(enable)
  2944. {
  2945. temp = (uint8_t)(EVC_EN); //enable
  2946. dwt_writetodevice(DIG_DIAG_ID, EVC_CTRL_OFFSET, 1, &temp) ;
  2947. }
  2948. }
  2949. /*! ------------------------------------------------------------------------------------------------------------------
  2950. * @fn dwt_readeventcounters()
  2951. *
  2952. * @brief This is used to read the event counters in the IC
  2953. *
  2954. * input parameters
  2955. * @param counters - pointer to the dwt_deviceentcnts_t structure which will hold the read data
  2956. *
  2957. * output parameters
  2958. *
  2959. * no return value
  2960. */
  2961. void dwt_readeventcounters(dwt_deviceentcnts_t *counters)
  2962. {
  2963. uint32_t temp;
  2964. temp= dwt_read32bitoffsetreg(DIG_DIAG_ID, EVC_PHE_OFFSET); //read sync loss (31-16), PHE (15-0)
  2965. counters->PHE = temp & 0xFFF;
  2966. counters->RSL = (temp >> 16) & 0xFFF;
  2967. temp = dwt_read32bitoffsetreg(DIG_DIAG_ID, EVC_FCG_OFFSET); //read CRC bad (31-16), CRC good (15-0)
  2968. counters->CRCG = temp & 0xFFF;
  2969. counters->CRCB = (temp >> 16) & 0xFFF;
  2970. temp = dwt_read32bitoffsetreg(DIG_DIAG_ID, EVC_FFR_OFFSET); //overruns (31-16), address errors (15-0)
  2971. counters->ARFE = temp & 0xFFF;
  2972. counters->OVER = (temp >> 16) & 0xFFF;
  2973. temp = dwt_read32bitoffsetreg(DIG_DIAG_ID, EVC_STO_OFFSET); //read PTO (31-16), SFDTO (15-0)
  2974. counters->PTO = (temp >> 16) & 0xFFF;
  2975. counters->SFDTO = temp & 0xFFF;
  2976. temp = dwt_read32bitoffsetreg(DIG_DIAG_ID, EVC_FWTO_OFFSET); //read RX TO (31-16), TXFRAME (15-0)
  2977. counters->TXF = (temp >> 16) & 0xFFF;
  2978. counters->RTO = temp & 0xFFF;
  2979. temp = dwt_read32bitoffsetreg(DIG_DIAG_ID, EVC_HPW_OFFSET); //read half period warning events
  2980. counters->HPW = temp & 0xFFF;
  2981. counters->TXW = (temp >> 16) & 0xFFF; //power up warning events
  2982. }
  2983. /*! ------------------------------------------------------------------------------------------------------------------
  2984. * @fn dwt_rxreset()
  2985. *
  2986. * @brief this function resets the receiver of the DW1000
  2987. *
  2988. * input parameters:
  2989. *
  2990. * output parameters
  2991. *
  2992. * no return value
  2993. */
  2994. void dwt_rxreset(void)
  2995. {
  2996. uint8_t resetrx = 0xe0;
  2997. //set rx reset
  2998. dwt_writetodevice(PMSC_ID, 0x3, 1, &resetrx);
  2999. resetrx = 0xf0; //clear RX reset
  3000. dwt_writetodevice(PMSC_ID, 0x3, 1, &resetrx);
  3001. }
  3002. /*! ------------------------------------------------------------------------------------------------------------------
  3003. * @fn dwt_softreset()
  3004. *
  3005. * @brief this function resets the DW1000
  3006. *
  3007. * input parameters:
  3008. *
  3009. * output parameters
  3010. *
  3011. * no return value
  3012. */
  3013. void dwt_softreset(void)
  3014. {
  3015. uint8_t temp[1] = {0};
  3016. _dwt_disablesequencing();
  3017. //_dwt_enableclocks(FORCE_SYS_XTI); //set system clock to XTI
  3018. //clear any AON auto download bits (as reset will trigger AON download)
  3019. dwt_write16bitoffsetreg(AON_ID, AON_WCFG_OFFSET, 0x0);
  3020. //clear the wakeup configuration
  3021. dwt_writetodevice(AON_ID, AON_CFG0_OFFSET, 1, temp);
  3022. //upload the new configuration
  3023. _dwt_aonarrayupload();
  3024. //reset HIF, TX, RX and PMSC
  3025. dwt_readfromdevice(PMSC_ID, 0x3, 1, temp) ;
  3026. temp[0] &= 0x0F;
  3027. dwt_writetodevice(PMSC_ID, 0x3, 1, &temp[0]) ;
  3028. //DW1000 needs a 10us sleep to let clk PLL lock after reset - the PLL will automatically lock after the reset
  3029. Sleep(1);
  3030. //Can also poll the PLL lock flag, but then the SPI needs to be < 3MHz !!
  3031. temp[0] |= 0xF0;
  3032. dwt_writetodevice(PMSC_ID, 0x3, 1, &temp[0]) ;
  3033. dw1000local.wait4resp = 0;
  3034. }
  3035. /*! ------------------------------------------------------------------------------------------------------------------
  3036. * @fn dwt_xtaltrim()
  3037. *
  3038. * @brief This is used adjust the crystal frequency
  3039. *
  3040. * input parameters:
  3041. * @param value - crystal trim value (in range 0x0 to 0x1F) 31 steps (~1.5ppm per step)
  3042. *
  3043. * @output
  3044. *
  3045. * no return value
  3046. */
  3047. void dwt_xtaltrim(uint8_t value)
  3048. {
  3049. uint8_t write_buf;
  3050. dwt_readfromdevice(FS_CTRL_ID,FS_XTALT_OFFSET,1,&write_buf);
  3051. write_buf &= ~FS_XTALT_MASK ;
  3052. write_buf |= (FS_XTALT_MASK & value) ; // we should not change high bits, cause it will cause malfunction
  3053. dwt_writetodevice(FS_CTRL_ID,FS_XTALT_OFFSET,1,&write_buf);
  3054. }
  3055. /*! ------------------------------------------------------------------------------------------------------------------
  3056. * @fn dwt_configcwmode()
  3057. *
  3058. * @brief this function sets the DW1000 to transmit cw signal at specific channel frequency
  3059. *
  3060. * input parameters:
  3061. * @param chan - specifies the operating channel (e.g. 1, 2, 3, 4, 5, 6 or 7)
  3062. *
  3063. * output parameters
  3064. *
  3065. * returns DWT_DECA_SUCCESS for success, or DWT_DECA_ERROR for error
  3066. */
  3067. int dwt_configcwmode(uint8_t chan)
  3068. {
  3069. uint8_t write_buf[1];
  3070. #ifdef DWT_API_ERROR_CHECK
  3071. if ((chan < 1) || (chan > 7) || (6 == chan))
  3072. {
  3073. return DWT_ERROR ; // validate channel number parameter
  3074. }
  3075. #endif
  3076. //
  3077. // disable TX/RX RF block sequencing (needed for cw frame mode)
  3078. //
  3079. _dwt_disablesequencing();
  3080. //config RF pll (for a given channel)
  3081. //configure PLL2/RF PLL block CFG
  3082. dwt_writetodevice(FS_CTRL_ID, FS_PLLCFG_OFFSET, 5, &pll2_config[chan_idx[chan]][0]);
  3083. //configure PLL2/RF PLL block CAL
  3084. dwt_writetodevice(FS_CTRL_ID, FS_XTALT_OFFSET, 1, &pll2calcfg);
  3085. //PLL wont be enabled until a TX/RX enable is issued later on
  3086. // Configure RF TX blocks (for specified channel and prf)
  3087. //Config RF TX control
  3088. dwt_write32bitoffsetreg(RF_CONF_ID, RF_TXCTRL_OFFSET, tx_config[chan_idx[chan]]);
  3089. //
  3090. // enable RF PLL
  3091. //
  3092. dwt_write32bitreg(RF_CONF_ID, RF_CONF_TXPLLPOWEN_MASK); //enable LDO and RF PLL blocks
  3093. dwt_write32bitreg(RF_CONF_ID, RF_CONF_TXALLEN_MASK); //enable the rest of TX blocks
  3094. //
  3095. // configure TX clocks
  3096. //
  3097. write_buf[0] = 0x22;
  3098. dwt_writetodevice(PMSC_ID,PMSC_CTRL0_OFFSET,1,write_buf);
  3099. write_buf[0] = 0x07;
  3100. dwt_writetodevice(PMSC_ID,0x1,1,write_buf);
  3101. //disable fine grain TX seq
  3102. dwt_write16bitoffsetreg(PMSC_ID, PMSC_TXFINESEQ_OFFSET, PMSC_TXFINESEQ_DIS_MASK);
  3103. write_buf[0] = TC_PGTEST_CW;
  3104. //configure CW mode
  3105. dwt_writetodevice(TX_CAL_ID, TC_PGTEST_OFFSET, TC_PGTEST_LEN, write_buf);
  3106. return DWT_SUCCESS ;
  3107. }
  3108. /*! ------------------------------------------------------------------------------------------------------------------
  3109. * @fn dwt_configcontinuousframemode()
  3110. *
  3111. * @brief this function sets the DW1000 to continuous tx frame mode
  3112. *
  3113. * input parameters:
  3114. * @param framerepetitionrate - specifies the
  3115. *
  3116. * output parameters
  3117. *
  3118. * no return value
  3119. */
  3120. void dwt_configcontinuousframemode(uint32_t framerepetitionrate)
  3121. {
  3122. uint8_t write_buf[4];
  3123. //
  3124. // disable TX/RX RF block sequencing (needed for continuous frame mode)
  3125. //
  3126. _dwt_disablesequencing();
  3127. // enable RF PLL and TX blocks
  3128. //
  3129. dwt_write32bitreg(RF_CONF_ID, RF_CONF_TXPLLPOWEN_MASK); //enable LDO and RF PLL blocks
  3130. dwt_write32bitreg(RF_CONF_ID, RF_CONF_TXALLEN_MASK); //enable the rest of TX blocks
  3131. //
  3132. // configure TX clocks
  3133. //
  3134. _dwt_enableclocks(FORCE_SYS_PLL);
  3135. _dwt_enableclocks(FORCE_TX_PLL);
  3136. //set the frame repetition rate
  3137. if(framerepetitionrate < 4)
  3138. {
  3139. framerepetitionrate = 4;
  3140. }
  3141. dwt_write32bitoffsetreg(DX_TIME_ID, 0, framerepetitionrate) ;
  3142. //
  3143. // configure continuous frame TX
  3144. //
  3145. write_buf[0] = (uint8_t)(DIAG_TMC_TX_PSTM) ;
  3146. dwt_writetodevice(DIG_DIAG_ID, DIAG_TMC_OFFSET, 1,write_buf); //turn the tx power spectrum test mode - continuous sending of frames
  3147. }
  3148. /*! ------------------------------------------------------------------------------------------------------------------
  3149. * @fn dwt_readtempvbat()
  3150. *
  3151. * @brief this function reads the battery voltage and temperature of the MP
  3152. * The values read here will be the current values sampled by DW1000 AtoD converters.
  3153. * Note on Temperature: the temperature value needs to be converted to give the real temperature
  3154. * the formula is: 1.13 * reading - 113.0
  3155. * Note on Voltage: the voltage value needs to be converted to give the real voltage
  3156. * the formula is: 0.0057 * reading + 2.3
  3157. *
  3158. * NB: To correctly read the temperature this read should be done with xtal clock
  3159. * however that means that the receiver will be switched off, if receiver needs to be on then
  3160. * the timer is used to make sure the value is stable before reading
  3161. *
  3162. * input parameters:
  3163. * @param fastSPI - set to 1 if SPI rate > than 3MHz is used
  3164. *
  3165. * output parameters
  3166. *
  3167. * returns (temp_raw<<8)|(vbat_raw)
  3168. */
  3169. uint16_t dwt_readtempvbat(uint8_t fastSPI)
  3170. {
  3171. uint8_t wr_buf[2];
  3172. uint8_t vbat_raw;
  3173. uint8_t temp_raw;
  3174. //these writes should be single writes and in sequence
  3175. wr_buf[0] = 0x80; // Enable TLD Bias
  3176. dwt_writetodevice(RF_CONF_ID,0x11,1,wr_buf);
  3177. wr_buf[0] = 0x0A; // Enable TLD Bias and ADC Bias
  3178. dwt_writetodevice(RF_CONF_ID,0x12,1,wr_buf);
  3179. wr_buf[0] = 0x0f; // Enable Outputs (only after Biases are up and running)
  3180. dwt_writetodevice(RF_CONF_ID,0x12,1,wr_buf); //
  3181. // Reading All SAR inputs
  3182. wr_buf[0] = 0x00; //
  3183. dwt_writetodevice(TX_CAL_ID, TC_SARL_SAR_C,1,wr_buf);
  3184. wr_buf[0] = 0x01; // Set SAR enable
  3185. dwt_writetodevice(TX_CAL_ID, TC_SARL_SAR_C,1,wr_buf);
  3186. if(fastSPI == 1)
  3187. {
  3188. Sleep(1); //if using PLL clocks(and fast SPI rate) then this Sleep is needed
  3189. //read voltage and temperature.
  3190. dwt_readfromdevice(TX_CAL_ID, TC_SARL_SAR_LVBAT_OFFSET,2,wr_buf);
  3191. }
  3192. else //change to a slow clock
  3193. {
  3194. _dwt_enableclocks(FORCE_SYS_XTI); //NOTE: set system clock to XTI - this is necessary to make sure the values read are reliable
  3195. //read voltage and temperature.
  3196. dwt_readfromdevice(TX_CAL_ID, TC_SARL_SAR_LVBAT_OFFSET,2,wr_buf);
  3197. //default clocks (ENABLE_ALL_SEQ)
  3198. _dwt_enableclocks(ENABLE_ALL_SEQ); //enable clocks for sequencing
  3199. }
  3200. vbat_raw = wr_buf[0];
  3201. temp_raw = wr_buf[1];
  3202. wr_buf[0] = 0x00; // Clear SAR enable
  3203. dwt_writetodevice(TX_CAL_ID, TC_SARL_SAR_C,1,wr_buf);
  3204. return ((temp_raw<<8)|(vbat_raw));
  3205. }
  3206. /*! ------------------------------------------------------------------------------------------------------------------
  3207. * @fn dwt_readwakeuptemp()
  3208. *
  3209. * @brief this function reads the temperature of the DW1000 that was sampled
  3210. * on waking from Sleep/Deepsleep. They are not current values, but read on last
  3211. * wakeup if DWT_TANDV bit is set in mode parameter of dwt_configuresleep
  3212. *
  3213. * input parameters:
  3214. *
  3215. * output parameters:
  3216. *
  3217. * returns: 8-bit raw temperature sensor value
  3218. */
  3219. uint8_t dwt_readwakeuptemp(void)
  3220. {
  3221. uint8_t temp_raw;
  3222. dwt_readfromdevice(TX_CAL_ID,TC_SARL_SAR_LTEMP_OFFSET,1,&temp_raw);
  3223. return (temp_raw);
  3224. }
  3225. /*! ------------------------------------------------------------------------------------------------------------------
  3226. * @fn dwt_readwakeupvbat()
  3227. *
  3228. * @brief this function reads the battery voltage of the DW1000 that was sampled
  3229. * on waking from Sleep/Deepsleep. They are not current values, but read on last
  3230. * wakeup if DWT_TANDV bit is set in mode parameter of dwt_configuresleep
  3231. *
  3232. * input parameters:
  3233. *
  3234. * output parameters:
  3235. *
  3236. * returns: 8-bit raw battery voltage sensor value
  3237. */
  3238. uint8_t dwt_readwakeupvbat(void)
  3239. {
  3240. uint8_t vbat_raw;
  3241. dwt_readfromdevice(TX_CAL_ID,TC_SARL_SAR_LVBAT_OFFSET,1,&vbat_raw);
  3242. return (vbat_raw);
  3243. }
  3244. /*! ------------------------------------------------------------------------------------------------------------------
  3245. */
  3246. #if (REG_DUMP == 1)
  3247. void dwt_dumpregisters(char *str, size_t strSize)
  3248. {
  3249. uint32_t reg = 0;
  3250. uint8_t buff[5];
  3251. int i;
  3252. int cnt ;
  3253. //first print all single registers
  3254. for(i=0; i<0x3F; i++)
  3255. {
  3256. dwt_readfromdevice(i, 0, 5, buff) ;
  3257. str += cnt = sprintf_s(str,strSize,"reg[%02X]=%02X%02X%02X%02X%02X",i,buff[4], buff[3], buff[2], buff[1], buff[0] ) ;
  3258. strSize -= cnt ;
  3259. str += cnt = sprintf_s(str,strSize,"\n") ;
  3260. strSize -= cnt ;
  3261. }
  3262. //reg 0x20
  3263. for(i=0; i<=32; i+=4)
  3264. {
  3265. reg = dwt_read32bitoffsetreg(0x20,i) ;
  3266. str += cnt = sprintf_s(str,strSize,"reg[%02X:%02X]=%08X",0x20,i,reg) ;
  3267. strSize -= cnt ;
  3268. str += cnt = sprintf_s(str,strSize,"\n") ;
  3269. strSize -= cnt ;
  3270. }
  3271. //reg 0x21
  3272. for(i=0; i<=44; i+=4)
  3273. {
  3274. reg = dwt_read32bitoffsetreg(0x21,i) ;
  3275. str += cnt = sprintf_s(str,strSize,"reg[%02X:%02X]=%08X",0x21,i,reg) ;
  3276. strSize -= cnt ;
  3277. str += cnt = sprintf_s(str,strSize,"\n") ;
  3278. strSize -= cnt ;
  3279. }
  3280. //reg 0x23
  3281. for(i=0; i<=0x20; i+=4)
  3282. {
  3283. reg = dwt_read32bitoffsetreg(0x23,i) ;
  3284. str += cnt = sprintf_s(str,strSize,"reg[%02X:%02X]=%08X",0x23,i,reg) ;
  3285. strSize -= cnt ;
  3286. str += cnt = sprintf_s(str,strSize,"\n") ;
  3287. strSize -= cnt ;
  3288. }
  3289. //reg 0x24
  3290. for(i=0; i<=12; i+=4)
  3291. {
  3292. reg = dwt_read32bitoffsetreg(0x24,i) ;
  3293. str += cnt = sprintf_s(str,strSize,"reg[%02X:%02X]=%08X",0x24,i,reg) ;
  3294. strSize -= cnt ;
  3295. str += cnt = sprintf_s(str,strSize,"\n") ;
  3296. strSize -= cnt ;
  3297. }
  3298. //reg 0x27
  3299. for(i=0; i<=44; i+=4)
  3300. {
  3301. reg = dwt_read32bitoffsetreg(0x27,i) ;
  3302. str += cnt = sprintf_s(str,strSize,"reg[%02X:%02X]=%08X",0x27,i,reg) ;
  3303. strSize -= cnt ;
  3304. str += cnt = sprintf_s(str,strSize,"\n") ;
  3305. strSize -= cnt ;
  3306. }
  3307. //reg 0x28
  3308. for(i=0; i<=64; i+=4)
  3309. {
  3310. reg = dwt_read32bitoffsetreg(0x28,i) ;
  3311. str += cnt = sprintf_s(str,strSize,"reg[%02X:%02X]=%08X",0x28,i,reg) ;
  3312. strSize -= cnt ;
  3313. str += cnt = sprintf_s(str,strSize,"\n") ;
  3314. strSize -= cnt ;
  3315. }
  3316. //reg 0x2A
  3317. for(i=0; i<20; i+=4)
  3318. {
  3319. reg = dwt_read32bitoffsetreg(0x2A,i) ;
  3320. str += cnt = sprintf_s(str,strSize,"reg[%02X:%02X]=%08X",0x2A,i,reg) ;
  3321. strSize -= cnt ;
  3322. str += cnt = sprintf_s(str,strSize,"\n") ;
  3323. strSize -= cnt ;
  3324. }
  3325. //reg 0x2B
  3326. for(i=0; i<24; i+=4)
  3327. {
  3328. reg = dwt_read32bitoffsetreg(0x2B,i) ;
  3329. str += cnt = sprintf_s(str,strSize,"reg[%02X:%02X]=%08X",0x2B,i,reg) ;
  3330. strSize -= cnt ;
  3331. str += cnt = sprintf_s(str,strSize,"\n") ;
  3332. strSize -= cnt ;
  3333. }
  3334. //reg 0x2f
  3335. for(i=0; i<40; i+=4)
  3336. {
  3337. reg = dwt_read32bitoffsetreg(0x2f,i) ;
  3338. str += cnt = sprintf_s(str,strSize,"reg[%02X:%02X]=%08X",0x2f,i,reg) ;
  3339. strSize -= cnt ;
  3340. str += cnt = sprintf_s(str,strSize,"\n") ;
  3341. strSize -= cnt ;
  3342. }
  3343. //reg 0x31
  3344. for(i=0; i<84; i+=4)
  3345. {
  3346. reg = dwt_read32bitoffsetreg(0x31,i) ;
  3347. str += cnt = sprintf_s(str,strSize,"reg[%02X:%02X]=%08X",0x31,i,reg) ;
  3348. strSize -= cnt ;
  3349. str += cnt = sprintf_s(str,strSize,"\n") ;
  3350. strSize -= cnt ;
  3351. }
  3352. //reg 0x36 = PMSC_ID
  3353. for(i=0; i<=48; i+=4)
  3354. {
  3355. reg = dwt_read32bitoffsetreg(PMSC_ID,i) ;
  3356. str += cnt = sprintf_s(str,strSize,"reg[%02X:%02X]=%08X",PMSC_ID,i,reg) ;
  3357. strSize -= cnt ;
  3358. str += cnt = sprintf_s(str,strSize,"\n") ;
  3359. strSize -= cnt ;
  3360. }
  3361. }
  3362. #endif
  3363. /* ===============================================================================================
  3364. List of expected (known) device ID handled by this software
  3365. ===============================================================================================
  3366. 0xDECA0130 // DW1000 - MP
  3367. ===============================================================================================
  3368. */